Commit 02a29d1db400ed4905db7dca9c8fcfa0712d5a1b

Authored by Dmitriy Zaporozhets
2 parents 319f0c30 6a932d0a

Merge branch '4-0-stable' into stable

Showing 405 changed files with 8420 additions and 5121 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 405 files displayed.

.gitignore
... ... @@ -23,3 +23,4 @@ db/data.yml
23 23 .idea
24 24 .DS_Store
25 25 .chef
  26 +vendor/bundle/*
... ...
.travis.yml
... ... @@ -19,8 +19,7 @@ services:
19 19 before_script:
20 20 - "cp config/database.yml.$DB config/database.yml"
21 21 - "cp config/gitlab.yml.example config/gitlab.yml"
22   - - "bundle exec rake db:create RAILS_ENV=test"
23   - - "bundle exec rake db:migrate RAILS_ENV=test"
  22 + - "bundle exec rake db:setup RAILS_ENV=test"
24 23 - "bundle exec rake db:seed_fu RAILS_ENV=test"
25 24 - "sh -e /etc/init.d/xvfb start"
26 25 script: "bundle exec rake travis --trace"
... ...
CHANGELOG
  1 +v 4.0.0
  2 + - Remove project code and path from API. Use id instead
  3 + - Return valid clonable url to repo for web hook
  4 + - Fixed backup issue
  5 + - Reorganized settings
  6 + - Fixed commits compare
  7 + - Refactored scss
  8 + - Improve status checks
  9 + - Validates presence of User#name
  10 + - Fixed postgres support
  11 + - Removed sqlite support
  12 + - Modified post-receive hook
  13 + - Milestones can be closed now
  14 + - Show comment events on dashboard
  15 + - Quick add team members via group#people page
  16 + - [API] expose created date for hooks and SSH keys
  17 + - [API] list, create issue notes
  18 + - [API] list, create snippet notes
  19 + - [API] list, create wall notes
  20 + - Remove project code - use path instead
  21 + - added username field to user
  22 + - rake task to fill usernames based on emails create namespaces for users
  23 + - STI Group < Namespace
  24 + - Project has namespace_id
  25 + - Projects with namespaces also namespaced in gitolite and stored in subdir
  26 + - Moving project to group will move it under group namespace
  27 + - Ability to move project from namespaces to another
  28 + - Fixes commit patches getting escaped (see #2036)
  29 + - Support diff and patch generation for commits and merge request
  30 + - MergeReqest doesn't generate a temporary file for the patch any more
  31 + - Update the UI to allow downloading Patch or Diff
  32 +
1 33 v 3.1.0
2 34 - Updated gems
3 35 - Services: Gitlab CI integration
... ... @@ -34,7 +66,7 @@ v 3.0.0
34 66 - Fixed bug with gitolite keys
35 67 - UI improved
36 68 - Increased perfomance of application
37   - - Show user avatar in last commit when browsing Files
  69 + - Show user avatar in last commit when browsing Files
38 70 - Refactored Gitlab::Merge
39 71 - Use Font Awsome for icons
40 72 - Separate observing of Note and MergeRequestsa
... ...
CONTRIBUTING.md
1   -## Contribute to GitLab
  1 +# Contact & support
2 2  
3   -If you want to contribute to GitLab, follow this process:
  3 +If you want quick help, head over to our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq).
  4 +Otherwise you can follow our [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) for a more systematic and thorough guide to solving your issues.
4 5  
5   -1. Fork the project
6   -2. Create a feature branch
7   -3. Code
8   -4. Create a pull request
9 6  
10   -We will only accept pull requests if:
11 7  
12   -* Your code has proper tests and all tests pass
13   -* Your code can be merged w/o problems
14   -* It won't break existing functionality
15   -* It's quality code
16   -* We like it :)
  8 +# Contribute to GitLab
17 9  
18   -For examples of feedback on pull requests please look at the [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
  10 +## Recipes
19 11  
20   -## Installation
  12 +We collect user submitted installation scripts and config file templates for platforms we don't support officially.
  13 +We believe there is merit in allowing a certain amount of diversity.
  14 +You can get and submit your solution to running/configuring GitLab with your favorite OS/distro, database, web server, cloud hoster, configuration management tool, etc.
21 15  
22   -Install the Gitlab development in a virtual machine with the [Gitlab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm). Installing it in a virtual machine makes it much easier to set up all the dependencies for integration testing.
  16 +Help us improve the collection of [GitLab Recipes](https://github.com/gitlabhq/gitlab-recipes/)
23 17  
24   -## Running tests
25 18  
26   -For more information on running the tests please read the [development tips](https://github.com/gitlabhq/gitlabhq/blob/master/doc/development.md)
  19 +## Feature suggestions
  20 +
  21 +Follow the [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) and support other peoples ideas or propose your own.
  22 +
  23 +
  24 +## Code
  25 +
  26 +Follow our [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) to set you up for hacking on GitLab.
... ...
Gemfile
... ... @@ -11,7 +11,6 @@ end
11 11 gem "rails", "3.2.9"
12 12  
13 13 # Supported DBs
14   -gem "sqlite3", group: :sqlite
15 14 gem "mysql2", group: :mysql
16 15 gem "pg", group: :postgres
17 16  
... ... @@ -27,13 +26,13 @@ gem &quot;grit&quot;, git: &quot;https://github.com/gitlabhq/grit.git&quot;, ref:
27 26 gem "omniauth-ldap", git: "https://github.com/gitlabhq/omniauth-ldap.git", ref: 'f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e'
28 27 gem 'yaml_db', git: "https://github.com/gitlabhq/yaml_db.git", ref: '98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd'
29 28 gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8'
30   -gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '212fd40bea61f3c6a167223768e7295dc32bbc10'
  29 +gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '8e6afc2da821354774aa4d1ee8a1aa2082f84a3e'
31 30  
32 31 # Gitolite client (for work with gitolite-admin repo)
33 32 gem "gitolite", '1.1.0'
34 33  
35 34 # Syntax highlighter
36   -gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", ref: '4db80c599067e2d5f23c5c243bf85b8ca0368ad4'
  35 +gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master"
37 36  
38 37 # Language detection
39 38 gem "github-linguist", "~> 2.3.4" , require: "linguist"
... ... @@ -101,11 +100,11 @@ group :assets do
101 100 gem "therubyracer"
102 101  
103 102 gem 'chosen-rails', "0.9.8"
104   - gem 'jquery-atwho-rails', "0.1.6"
  103 + gem 'jquery-atwho-rails', "0.1.7"
105 104 gem "jquery-rails", "2.1.3"
106 105 gem "jquery-ui-rails", "2.0.2"
107 106 gem "modernizr", "2.6.2"
108   - gem "raphael-rails", "2.1.0"
  107 + gem "raphael-rails", "1.5.2"
109 108 gem 'bootstrap-sass', "2.2.1.1"
110 109 gem "font-awesome-sass-rails", "~> 2.0.0"
111 110 gem "gemoji", "~> 1.2.1", require: 'emoji/railtie'
... ... @@ -125,7 +124,7 @@ group :development, :test do
125 124 gem "capybara"
126 125 gem "pry"
127 126 gem "awesome_print"
128   - gem "database_cleaner"
  127 + gem "database_cleaner", ref: "f89c34300e114be99532f14c115b2799a3380ac6", git: "https://github.com/bmabey/database_cleaner.git"
129 128 gem "launchy"
130 129 gem 'factory_girl_rails'
131 130  
... ... @@ -139,7 +138,7 @@ group :development, :test do
139 138 gem 'rb-inotify', require: linux_only('rb-inotify')
140 139  
141 140 # PhantomJS driver for Capybara
142   - gem 'poltergeist'
  141 + gem 'poltergeist', git: 'https://github.com/jonleighton/poltergeist.git', ref: '5c2e092001074a8cf09f332d3714e9ba150bc8ca'
143 142 end
144 143  
145 144 group :test do
... ... @@ -152,5 +151,5 @@ group :test do
152 151 end
153 152  
154 153 group :production do
155   - gem "gitlab_meta", '3.1'
  154 + gem "gitlab_meta", '4.0'
156 155 end
... ...
Gemfile.lock
1 1 GIT
  2 + remote: https://github.com/bmabey/database_cleaner.git
  3 + revision: f89c34300e114be99532f14c115b2799a3380ac6
  4 + ref: f89c34300e114be99532f14c115b2799a3380ac6
  5 + specs:
  6 + database_cleaner (0.9.1)
  7 +
  8 +GIT
2 9 remote: https://github.com/ctran/annotate_models.git
3 10 revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
4 11 specs:
... ... @@ -26,10 +33,10 @@ GIT
26 33  
27 34 GIT
28 35 remote: https://github.com/gitlabhq/grit_ext.git
29   - revision: 212fd40bea61f3c6a167223768e7295dc32bbc10
30   - ref: 212fd40bea61f3c6a167223768e7295dc32bbc10
  36 + revision: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e
  37 + ref: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e
31 38 specs:
32   - grit_ext (0.6.0)
  39 + grit_ext (0.6.1)
33 40 charlock_holmes (~> 0.6.9)
34 41  
35 42 GIT
... ... @@ -45,8 +52,8 @@ GIT
45 52  
46 53 GIT
47 54 remote: https://github.com/gitlabhq/pygments.rb.git
48   - revision: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
49   - ref: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
  55 + revision: db1da0343adf86b49bdc3add04d02d2e80438d38
  56 + branch: master
50 57 specs:
51 58 pygments.rb (0.3.2)
52 59 posix-spawn (~> 0.3.6)
... ... @@ -59,6 +66,18 @@ GIT
59 66 specs:
60 67 yaml_db (0.2.2)
61 68  
  69 +GIT
  70 + remote: https://github.com/jonleighton/poltergeist.git
  71 + revision: 5c2e092001074a8cf09f332d3714e9ba150bc8ca
  72 + ref: 5c2e092001074a8cf09f332d3714e9ba150bc8ca
  73 + specs:
  74 + poltergeist (1.0.2)
  75 + capybara (~> 1.1)
  76 + childprocess (~> 0.3)
  77 + faye-websocket (~> 0.4, >= 0.4.4)
  78 + http_parser.rb (~> 0.5.3)
  79 + multi_json (~> 1.0)
  80 +
62 81 GEM
63 82 remote: http://rubygems.org/
64 83 specs:
... ... @@ -128,7 +147,6 @@ GEM
128 147 colorize (0.5.8)
129 148 crack (0.3.1)
130 149 daemons (1.1.9)
131   - database_cleaner (0.9.1)
132 150 devise (2.1.2)
133 151 bcrypt-ruby (~> 3.0)
134 152 orm_adapter (~> 0.1)
... ... @@ -171,7 +189,7 @@ GEM
171 189 mime-types (~> 1.19)
172 190 pygments.rb (>= 0.2.13)
173 191 github-markup (0.7.4)
174   - gitlab_meta (3.1)
  192 + gitlab_meta (4.0)
175 193 gitolite (1.1.0)
176 194 gratr19 (~> 0.4.4.1)
177 195 grit (~> 2.5.0)
... ... @@ -215,7 +233,7 @@ GEM
215 233 httpauth (0.2.0)
216 234 i18n (0.6.1)
217 235 journey (1.0.4)
218   - jquery-atwho-rails (0.1.6)
  236 + jquery-atwho-rails (0.1.7)
219 237 jquery-rails (2.1.3)
220 238 railties (>= 3.1.0, < 5.0)
221 239 thor (~> 0.14)
... ... @@ -279,12 +297,6 @@ GEM
279 297 omniauth-oauth (~> 1.0)
280 298 orm_adapter (0.4.0)
281 299 pg (0.14.1)
282   - poltergeist (1.0.2)
283   - capybara (~> 1.1)
284   - childprocess (~> 0.3)
285   - faye-websocket (~> 0.4, >= 0.4.4)
286   - http_parser.rb (~> 0.5.3)
287   - multi_json (~> 1.0)
288 300 polyglot (0.3.3)
289 301 posix-spawn (0.3.6)
290 302 pry (0.9.10)
... ... @@ -329,7 +341,7 @@ GEM
329 341 thor (>= 0.14.6, < 2.0)
330 342 raindrops (0.10.0)
331 343 rake (10.0.1)
332   - raphael-rails (2.1.0)
  344 + raphael-rails (1.5.2)
333 345 rb-fsevent (0.9.2)
334 346 rb-inotify (0.8.8)
335 347 ffi (>= 0.5.0)
... ... @@ -404,7 +416,6 @@ GEM
404 416 multi_json (~> 1.0)
405 417 rack (~> 1.0)
406 418 tilt (~> 1.1, != 1.3.0)
407   - sqlite3 (1.3.6)
408 419 stamp (0.3.0)
409 420 test_after_commit (0.0.1)
410 421 therubyracer (0.10.2)
... ... @@ -453,7 +464,7 @@ DEPENDENCIES
453 464 chosen-rails (= 0.9.8)
454 465 coffee-rails (~> 3.2.2)
455 466 colored
456   - database_cleaner
  467 + database_cleaner!
457 468 devise (~> 2.1.0)
458 469 draper (~> 0.18.0)
459 470 email_spec
... ... @@ -465,7 +476,7 @@ DEPENDENCIES
465 476 git
466 477 github-linguist (~> 2.3.4)
467 478 github-markup (~> 0.7.4)
468   - gitlab_meta (= 3.1)
  479 + gitlab_meta (= 4.0)
469 480 gitolite (= 1.1.0)
470 481 grack!
471 482 grape (~> 0.2.1)
... ... @@ -476,7 +487,7 @@ DEPENDENCIES
476 487 guard-spinach
477 488 haml-rails (~> 0.3.5)
478 489 httparty
479   - jquery-atwho-rails (= 0.1.6)
  490 + jquery-atwho-rails (= 0.1.7)
480 491 jquery-rails (= 2.1.3)
481 492 jquery-ui-rails (= 2.0.2)
482 493 kaminari (~> 0.14.1)
... ... @@ -490,14 +501,14 @@ DEPENDENCIES
490 501 omniauth-ldap!
491 502 omniauth-twitter
492 503 pg
493   - poltergeist
  504 + poltergeist!
494 505 pry
495 506 pygments.rb!
496 507 quiet_assets (~> 1.0.1)
497 508 rack-mini-profiler
498 509 rails (= 3.2.9)
499 510 rails-dev-tweaks
500   - raphael-rails (= 2.1.0)
  511 + raphael-rails (= 1.5.2)
501 512 rb-fsevent
502 513 rb-inotify
503 514 redcarpet (~> 2.2.2)
... ... @@ -512,7 +523,6 @@ DEPENDENCIES
512 523 simplecov
513 524 six
514 525 spinach-rails
515   - sqlite3
516 526 stamp
517 527 test_after_commit
518 528 therubyracer
... ...
README.md
1   -# Welcome to GitLab [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://secure.travis-ci.org/gitlabhq/gitlabhq) [![build status](https://secure.travis-ci.org/gitlabhq/grit.png)](https://secure.travis-ci.org/gitlabhq/grit) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
  1 +# Welcome to GitLab [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) [![build status](https://secure.travis-ci.org/gitlabhq/grit.png)](https://travis-ci.org/gitlabhq/grit) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq)
2 2  
3 3 GitLab is a free project and repository management application
4 4  
... ...
VERSION
1   -3.1.0
  1 +4.0.0
... ...
app/assets/fonts/korolev-medium-compressed.otf
No preview for this file type
app/assets/images/ajax_loader_gray.gif 0 → 100644

8.17 KB

app/assets/images/logo.png

2.93 KB

app/assets/images/logo_basic.png

3.2 KB

app/assets/images/logo_text.png

4.49 KB

app/assets/images/logo_text_tr.png

3.21 KB

app/assets/images/logo_white.png

1.48 KB | W: | H:

1.88 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
app/assets/images/service-disabled-gitlab-ci.png

2.13 KB

app/assets/images/service-gitlab-ci.png

2.34 KB

app/assets/images/switch_icon.png 0 → 100644

1.17 KB

app/assets/javascripts/admin.js.coffee
... ... @@ -10,3 +10,8 @@ $ -&gt;
10 10 $('.log-tabs a').click (e) ->
11 11 e.preventDefault()
12 12 $(this).tab('show')
  13 +
  14 + $('.log-bottom').click (e) ->
  15 + e.preventDefault()
  16 + visible_log = $(".file_content:visible")
  17 + visible_log.animate({ scrollTop: visible_log.find('ol').height() }, "fast")
... ...
app/assets/javascripts/gfm_auto_complete.js.coffee
1 1 # Creates the variables for setting up GFM auto-completion
2 2  
3 3 window.GitLab ?= {}
4   -GitLab.GfmAutoComplete ?= {}
5   -
6   -# Emoji
7   -data = []
8   -template = "<li data-value='${insert}'>${name} <img alt='${name}' height='20' src='${image}' width='20' /></li>"
9   -GitLab.GfmAutoComplete.Emoji = {data, template}
10   -
11   -# Team Members
12   -data = []
13   -url = '';
14   -params = {private_token: '', page: 1}
15   -GitLab.GfmAutoComplete.Members = {data, url, params}
16   -
17   -# Add GFM auto-completion to all input fields, that accept GFM input.
18   -GitLab.GfmAutoComplete.setup = ->
19   - input = $('.js-gfm-input')
20   -
  4 +GitLab.GfmAutoComplete =
21 5 # Emoji
22   - input.atWho ':',
23   - data: GitLab.GfmAutoComplete.Emoji.data,
24   - tpl: GitLab.GfmAutoComplete.Emoji.template
  6 + Emoji:
  7 + data: []
  8 + template: '<li data-value="${insert}">${name} <img alt="${name}" height="20" src="${image}" width="20" /></li>'
25 9  
26 10 # Team Members
27   - input.atWho '@', (query, callback) ->
28   - (getMoreMembers = ->
29   - $.getJSON(GitLab.GfmAutoComplete.Members.url, GitLab.GfmAutoComplete.Members.params)
30   - .success (members) ->
31   - # pick the data we need
32   - newMembersData = $.map(members, (m) -> m.name )
33   -
34   - # add the new page of data to the rest
35   - $.merge(GitLab.GfmAutoComplete.Members.data, newMembersData)
36   -
37   - # show the pop-up with a copy of the current data
38   - callback(GitLab.GfmAutoComplete.Members.data[..])
39   -
40   - # are we past the last page?
41   - if newMembersData.length is 0
42   - # set static data and stop callbacks
43   - input.atWho '@',
44   - data: GitLab.GfmAutoComplete.Members.data
45   - callback: null
46   - else
47   - # get next page
48   - getMoreMembers()
  11 + Members:
  12 + data: []
  13 + url: ''
  14 + params:
  15 + private_token: ''
  16 + template: '<li data-value="${username}">${username} <small>${name}</small></li>'
  17 +
  18 + # Add GFM auto-completion to all input fields, that accept GFM input.
  19 + setup: ->
  20 + input = $('.js-gfm-input')
  21 +
  22 + # Emoji
  23 + input.atWho ':',
  24 + data: @Emoji.data
  25 + tpl: @Emoji.template
  26 +
  27 + # Team Members
  28 + input.atWho '@',
  29 + tpl: @Members.template
  30 + callback: (query, callback) =>
  31 + request_params = $.extend({}, @Members.params, query: query)
  32 + $.getJSON(@Members.url, request_params).done (members) =>
  33 + new_members_data = $.map(members, (m) ->
  34 + username: m.username,
  35 + name: m.name
  36 + )
  37 + callback(new_members_data)
49 38  
50   - # so the next request gets the next page
51   - GitLab.GfmAutoComplete.Members.params.page += 1
52   - ).call()
... ...
app/assets/javascripts/issues.js
1   -function switchToNewIssue(){
2   - $(".issues_content").hide("fade", { direction: "left" }, 150, function(){
3   - $('select#issue_assignee_id').chosen();
4   - $('select#issue_milestone_id').chosen();
5   - $("#new_issue_dialog").show("fade", { direction: "right" }, 150);
6   - $('.top-tabs .add_new').hide();
7   - disableButtonIfEmptyField("#issue_title", ".save-btn");
8   - GitLab.GfmAutoComplete.setup();
9   - });
10   -}
11   -
12   -function switchToEditIssue(){
13   - $(".issues_content").hide("fade", { direction: "left" }, 150, function(){
14   - $('select#issue_assignee_id').chosen();
15   - $('select#issue_milestone_id').chosen();
16   - $("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
17   - $('.add_new').hide();
18   - disableButtonIfEmptyField("#issue_title", ".save-btn");
19   - GitLab.GfmAutoComplete.setup();
20   - });
21   -}
22   -
23   -function switchFromNewIssue(){
24   - backToIssues();
25   -}
26   -
27   -function switchFromEditIssue(){
28   - backToIssues();
29   -}
30   -
31   -function backToIssues(){
32   - $("#edit_issue_dialog, #new_issue_dialog").hide("fade", { direction: "right" }, 150, function(){
33   - $(".issues_content").show("fade", { direction: "left" }, 150, function() {
34   - $("#edit_issue_dialog").html("");
35   - $("#new_issue_dialog").html("");
36   - $('.add_new').show();
37   - });
38   - });
39   -}
40   -
41 1 function initIssuesSearch() {
42 2 var href = $('#issue_search_form').attr('action');
43 3 var last_terms = '';
... ... @@ -76,23 +36,15 @@ function issuesPage(){
76 36 $(this).closest("form").submit();
77 37 });
78 38  
79   - $("#new_issue_link").click(function(){
80   - updateNewIssueURL();
81   - });
82   -
83   - $('body').on('ajax:success', '.close_issue, .reopen_issue, #new_issue', function(){
  39 + $('body').on('ajax:success', '.close_issue, .reopen_issue', function(){
84 40 var t = $(this),
85 41 totalIssues,
86   - reopen = t.hasClass('reopen_issue'),
87   - newIssue = false;
88   - if( this.id == 'new_issue' ){
89   - newIssue = true;
90   - }
91   - $('.issue_counter, #new_issue').each(function(){
  42 + reopen = t.hasClass('reopen_issue');
  43 + $('.issue_counter').each(function(){
92 44 var issue = $(this);
93 45 totalIssues = parseInt( $(this).html(), 10 );
94 46  
95   - if( newIssue || ( reopen && issue.closest('.main_menu').length ) ){
  47 + if( reopen && issue.closest('.main_menu').length ){
96 48 $(this).html( totalIssues+1 );
97 49 }else {
98 50 $(this).html( totalIssues-1 );
... ... @@ -126,20 +78,3 @@ function issuesCheckChanged() {
126 78 $('.issues_filters').show();
127 79 }
128 80 }
129   -
130   -function updateNewIssueURL(){
131   - var new_issue_link = $("#new_issue_link");
132   - var milestone_id = $("#milestone_id").val();
133   - var assignee_id = $("#assignee_id").val();
134   - var new_href = "";
135   - if(milestone_id){
136   - new_href = "issue[milestone_id]=" + milestone_id + "&";
137   - }
138   - if(assignee_id){
139   - new_href = new_href + "issue[assignee_id]=" + assignee_id;
140   - }
141   - if(new_href.length){
142   - new_href = new_issue_link.attr("href") + "?" + new_href;
143   - new_issue_link.attr("href", new_href);
144   - }
145   -};
... ...
app/assets/javascripts/main.js.coffee
... ... @@ -7,6 +7,18 @@ window.slugify = (text) -&gt;
7 7 window.ajaxGet = (url) ->
8 8 $.ajax({type: "GET", url: url, dataType: "script"})
9 9  
  10 +window.errorMessage = (message) ->
  11 + ehtml = $("<p>")
  12 + ehtml.addClass("error_message")
  13 + ehtml.html(message)
  14 + ehtml
  15 +
  16 +window.split = (val) ->
  17 + return val.split( /,\s*/ )
  18 +
  19 +window.extractLast = (term) ->
  20 + return split( term ).pop()
  21 +
10 22 # Disable button if text field is empty
11 23 window.disableButtonIfEmptyField = (field_selector, button_selector) ->
12 24 field = $(field_selector)
... ... @@ -33,6 +45,11 @@ $ -&gt;
33 45 # Bottom tooltip
34 46 $('.has_bottom_tooltip').tooltip(placement: 'bottom')
35 47  
  48 + # Flash
  49 + if (flash = $("#flash-container")).length > 0
  50 + flash.click -> $(@).slideUp("slow")
  51 + flash.slideDown "slow"
  52 + setTimeout (-> flash.slideUp("slow")), 3000
36 53  
37 54 # Disable form buttons while a form is submitting
38 55 $('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
... ...
app/assets/javascripts/merge_requests.js
... ... @@ -14,14 +14,6 @@ var MergeRequest = {
14 14 $(".mr_show_all_commits").bind("click", function() {
15 15 self.showAllCommits();
16 16 });
17   -
18   - $(".line_note_link, .line_note_reply_link").live("click", function(e) {
19   - var form = $(".per_line_form");
20   - $(this).parent().parent().after(form);
21   - form.find("#note_line_code").val($(this).attr("line_code"));
22   - form.show();
23   - return false;
24   - });
25 17 },
26 18  
27 19 initMergeWidget:
... ... @@ -34,6 +26,12 @@ var MergeRequest = {
34 26 self.showState(data.state);
35 27 }, "json");
36 28 }
  29 +
  30 + if(self.opts.ci_enable){
  31 + $.get(self.opts.url_to_ci_check, function(data){
  32 + self.showCiState(data.status);
  33 + }, "json");
  34 + }
37 35 },
38 36  
39 37 initTabs:
... ... @@ -87,6 +85,11 @@ var MergeRequest = {
87 85 $(".automerge_widget." + state).show();
88 86 },
89 87  
  88 + showCiState:
  89 + function(state){
  90 + $(".ci_widget").hide();
  91 + $(".ci_widget.ci-" + state).show();
  92 + },
90 93  
91 94 loadDiff:
92 95 function() {
... ...
app/assets/javascripts/profile.js.coffee
... ... @@ -8,3 +8,13 @@ $ -&gt;
8 8  
9 9 # Go up the hierarchy and show the corresponding submission feedback element
10 10 $(@).closest('fieldset').find('.update-feedback').show('highlight', {color: '#DFF0D8'}, 500)
  11 +
  12 + $('.update-username form').on 'ajax:before', ->
  13 + $('.loading-gif').show()
  14 + $(this).find('.update-success').hide()
  15 + $(this).find('.update-failed').hide()
  16 +
  17 + $('.update-username form').on 'ajax:complete', ->
  18 + $(this).find('.save-btn').removeAttr('disabled')
  19 + $(this).find('.save-btn').removeClass('disabled')
  20 + $(this).find('.loading-gif').hide()
... ...
app/assets/javascripts/projects.js.coffee
1 1 window.Projects = ->
2   - $('#project_name').on 'change', ->
3   - slug = slugify $(@).val()
4   - $('#project_code, #project_path').val slug
5   -
6 2 $('.new_project, .edit_project').on 'ajax:before', ->
7 3 $('.project_new_holder, .project_edit_holder').hide()
8 4 $('.save-project-loader').show()
... ... @@ -22,10 +18,3 @@ $ -&gt;
22 18 # Ref switcher
23 19 $('.project-refs-select').on 'change', ->
24 20 $(@).parents('form').submit()
25   -
26   -class @GraphNav
27   - @init: ->
28   - $('.graph svg').css 'position', 'relative'
29   - $('body').bind 'keyup', (e) ->
30   - $('.graph svg').animate(left: '+=400') if e.keyCode is 37 # left
31   - $('.graph svg').animate(left: '-=400') if e.keyCode is 39 # right
... ...
app/assets/javascripts/tree.js.coffee
... ... @@ -28,7 +28,7 @@ $ -&gt;
28 28 return false
29 29  
30 30 $('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live 'click', (e) ->
31   - History.pushState(null, null, $(@).attr('href'))
  31 + History.pushState(null, null, decodeURIComponent($(@).attr('href')))
32 32 return false
33 33  
34 34 History.Adapter.bind window, 'statechange', ->
... ...
app/assets/stylesheets/application.css
... ... @@ -1,11 +0,0 @@
1   -/*
2   - * This is a manifest file that'll automatically include all the stylesheets available in this directory
3   - * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4   - * the top of the compiled file, but it's generally better to create a new file per style scope.
5   - *= require jquery.ui.all
6   - *= require jquery.ui.aristo
7   - *= require jquery.atwho
8   - *= require chosen
9   - *= require_self
10   - *= require main
11   -*/
app/assets/stylesheets/application.scss 0 → 100644
... ... @@ -0,0 +1,47 @@
  1 +/*
  2 + * This is a manifest file that'll automatically include all the stylesheets available in this directory
  3 + * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
  4 + * the top of the compiled file, but it's generally better to create a new file per style scope.
  5 + *= require jquery.ui.gitlab
  6 + *= require jquery.atwho
  7 + *= require chosen
  8 + *= require_self
  9 +*/
  10 +
  11 +/**
  12 + * GitLab bootstrap:
  13 + */
  14 +@import "gitlab_bootstrap.scss";
  15 +
  16 +@import "common.scss";
  17 +@import "ref_select.scss";
  18 +
  19 +@import "sections/header.scss";
  20 +@import "sections/nav.scss";
  21 +@import "sections/commits.scss";
  22 +@import "sections/issues.scss";
  23 +@import "sections/projects.scss";
  24 +@import "sections/snippets.scss";
  25 +@import "sections/votes.scss";
  26 +@import "sections/merge_requests.scss";
  27 +@import "sections/graph.scss";
  28 +@import "sections/events.scss";
  29 +@import "sections/themes.scss";
  30 +@import "sections/tree.scss";
  31 +@import "sections/notes.scss";
  32 +@import "sections/profile.scss";
  33 +@import "sections/login.scss";
  34 +@import "sections/editor.scss";
  35 +
  36 +@import "highlight/white.scss";
  37 +@import "highlight/dark.scss";
  38 +
  39 +/**
  40 + * UI themes:
  41 + */
  42 +@import "themes/ui_basic.scss";
  43 +@import "themes/ui_mars.scss";
  44 +@import "themes/ui_modern.scss";
  45 +@import "themes/ui_gray.scss";
  46 +@import "themes/ui_color.scss";
  47 +
... ...
app/assets/stylesheets/common.scss
1 1 /** LAYOUT **/
2 2  
3 3 body {
4   - margin-bottom:20px;
  4 + margin-bottom: 20px;
5 5 }
6 6  
7 7 .container {
8   - padding-top:0;
9   - z-index:5;
  8 + padding-top: 0;
  9 + z-index: 5;
10 10 }
11 11  
12 12 .container .content {
13   - margin:0 0;
  13 + margin: 0 0;
14 14 }
15 15  
16   -.container .sidebar {
17   - width: 200px;
18   - height:100%;
19   - min-height:450px;
20   - float:right;
21   -}
22   -
23   -
24 16 .visible_link,
25 17 .author_link {
26 18 color: $link_color;
27 19 }
28 20  
29   -.help li { color:#111 }
  21 +.help li { color:$style_color; }
30 22  
31 23 .back_link {
32   - text-decoration:underline;
33   - font-size:14px;
34   - font-weight:bold;
35   - padding:10px 0;
36   - padding-bottom:0;
  24 + text-decoration: underline;
  25 + font-size: 14px;
  26 + font-weight: bold;
  27 + padding: 10px 0;
  28 + padding-bottom: 0;
37 29 }
38 30  
39 31 .info_link {
40   - margin-right:5px;
41   - float:left;
  32 + margin-right: 5px;
  33 + float: left;
42 34  
43 35 img {
44   - width:20px;
  36 + width: 20px;
45 37 }
46 38 }
47 39  
48 40 .download_repo_link {
49 41 background: url("images.png") no-repeat 0 -48px;
50   - padding-left:20px;
  42 + padding-left: 20px;
51 43 }
52 44  
53 45 table a code {
... ... @@ -61,32 +53,37 @@ table a code {
61 53 }
62 54  
63 55 .loading {
64   - margin:20px auto;
  56 + margin: 20px auto;
65 57 background: url(ajax_loader.gif) no-repeat center center;
66   - width:40px;
67   - height:40px;
  58 + width: 40px;
  59 + height: 40px;
  60 + &.loading-gray {
  61 + background: url(ajax_loader_gray.gif) no-repeat center center;
  62 + }
68 63 }
69 64  
70 65 /** FLASH message **/
71   -#flash_container {
72   - height:50px;
73   - position:fixed;
74   - z-index:10001;
75   - top:0px;
76   - width:100%;
77   - margin-bottom:15px;
78   - overflow:hidden;
79   - background:white;
80   - cursor:pointer;
81   - border-bottom:1px solid #ccc;
  66 +#flash-container {
  67 + height: 50px;
  68 + position: fixed;
  69 + z-index: 10001;
  70 + top: 0px;
  71 + width: 100%;
  72 + margin-bottom: 15px;
  73 + overflow: hidden;
  74 + background: white;
  75 + cursor: pointer;
  76 + border-bottom: 1px solid #ccc;
  77 + text-align: center;
  78 + display: none;
82 79  
83 80 h4 {
84   - color:#666;
85   - font-size:18px;
86   - line-height:38px;
87   - padding-top:5px;
88   - margin:2px;
89   - font-weight:normal;
  81 + color: #666;
  82 + font-size: 18px;
  83 + line-height: 38px;
  84 + padding-top: 5px;
  85 + margin: 2px;
  86 + font-weight: normal;
90 87 }
91 88 }
92 89  
... ... @@ -94,40 +91,29 @@ table a code {
94 91 margin-right:50px
95 92 }
96 93  
97   -.handle:hover {
98   - cursor:move;
99   -}
100   -
101   -span.update-author {
102   - display:block;
103   -}
104 94 span.update-author {
105   - color:#999;
106   - font-weight:normal;
107   - font-style:italic;
108   -}
109   -span.update-author strong {
110   - font-weight:bold;
111   - font-style: normal;
  95 + display: block;
  96 + color: #999;
  97 + font-weight: normal;
  98 + font-style: italic;
  99 + strong {
  100 + font-weight: bold;
  101 + font-style: normal;
  102 + }
112 103 }
113 104  
114   -/** UPDATE ITEM **/
115   -span.update-author {
116   - display:block;
117   -}
118   -/** END UPDATE ITEM **/
119 105 .dashboard-loader {
120   - float:left;
121   - margin:10px;
122   - display:none;
  106 + float: left;
  107 + margin: 10px;
  108 + display: none;
123 109 }
124 110 .user-mention {
125   - color:#2FA0BB;
126   - font-weight:bold;
  111 + color: #2FA0BB;
  112 + font-weight: bold;
127 113 }
128 114  
129 115 .neib {
130   - margin-right:10px;
  116 + margin-right: 10px;
131 117 }
132 118  
133 119 .label {
... ... @@ -136,9 +122,9 @@ span.update-author {
136 122 &.label-tag {
137 123 background: none;
138 124 border: none;
139   - padding:4px 6px;
140   - color:#444;
141   - text-shadow:0 0 1px #fff;
  125 + padding: 4px 6px;
  126 + color: #444;
  127 + text-shadow: 0 0 1px #fff;
142 128  
143 129 &.grouped {
144 130 float: left;
... ... @@ -149,9 +135,9 @@ span.update-author {
149 135 &.label-issue {
150 136 background-color: #eee;
151 137 border: 1px solid #ccc;
152   - padding:4px 6px;
153   - color:#444;
154   - text-shadow:0 0 1px #fff;
  138 + padding: 4px 6px;
  139 + color: #444;
  140 + text-shadow: 0 0 1px #fff;
155 141  
156 142 &.grouped {
157 143 float: left;
... ... @@ -201,21 +187,21 @@ form {
201 187  
202 188  
203 189 .field_with_errors {
204   - display:inline;
  190 + display: inline;
205 191 }
206 192  
207 193 ul.breadcrumb {
208   - background:white;
209   - border:none;
  194 + background: white;
  195 + border: none;
210 196 li {
211 197 display: inline;
212 198 text-shadow: 0 1px 0 white
213 199 }
214 200  
215 201 a {
216   - color:#474D57;
217   - font-weight:bold;
218   - font-size:14px;
  202 + color: #474D57;
  203 + font-weight: bold;
  204 + font-size: 14px;
219 205 }
220 206  
221 207 .arrow {
... ... @@ -225,31 +211,31 @@ ul.breadcrumb {
225 211 float: left;
226 212 position: relative;
227 213 left: -10px;
228   - padding:0;
229   - margin:0;
  214 + padding: 0;
  215 + margin: 0;
230 216 }
231 217 }
232 218  
233 219 input[type=text] {
234 220 &.large_text {
235   - padding:6px;
236   - font-size:16px;
  221 + padding: 6px;
  222 + font-size: 16px;
237 223 }
238 224 }
239 225  
240 226 input.git_clone_url {
241   - width:325px;
  227 + width: 325px;
242 228 }
243 229  
244 230 .merge-request-form-holder {
245 231 select {
246   - width:300px;
  232 + width: 300px;
247 233 }
248 234 }
249 235  
250 236 /** Issues **/
251 237 #issue_assignee_id {
252   - width:300px;
  238 + width: 300px;
253 239 }
254 240  
255 241 #new_issue_dialog textarea{
... ... @@ -257,26 +243,11 @@ input.git_clone_url {
257 243 }
258 244  
259 245 .project_list_url {
260   - width:250px;
  246 + width: 250px;
261 247 background:#fff !important;
262 248 }
263 249  
264 250  
265   -/** bordered list **/
266   -ul.bordered-list {
267   - margin:5px 0px;
268   - padding:0px;
269   - li {
270   - padding: 5px 0;
271   - border-bottom: 1px solid #EEE;
272   - overflow: hidden;
273   - display: block;
274   - margin:0px;
275   - }
276   -}
277   -
278   -ul.bordered-list li:last-child { border:none }
279   -
280 251 .line_holder {
281 252 &:hover {
282 253 td {
... ... @@ -287,10 +258,10 @@ ul.bordered-list li:last-child { border:none }
287 258  
288 259 li.commit {
289 260 .avatar {
290   - width:24px;
  261 + width: 24px;
291 262 top:-5px;
292   - margin-right:10px;
293   - margin-left:10px;
  263 + margin-right: 10px;
  264 + margin-left: 10px;
294 265 }
295 266  
296 267 code {
... ... @@ -310,102 +281,10 @@ p.time {
310 281  
311 282  
312 283 .styled_image {
313   - border:2px solid #ddd;
314   -}
315   -
316   -
317   -.ico {
318   - background: url("images.png") no-repeat -85px -77px;
319   - width: 19px;
320   - height: 16px;
321   - float: left;
322   - position: relative;
323   - margin-right: 10px;
324   - top: 8px;
325   -
326   - &.project {
327   - background-position: -37px -77px;
328   - }
329   -
330   - &.activities {
331   - background-position:-162px -22px;
332   - }
333   - &.projects {
334   - background-position:-209px -21px;
335   - }
  284 + border: 2px solid #ddd;
336 285 }
337 286  
338   -.leftbar {
339   - h5, .title {
340   - padding:5px 10px;
341   - }
342 287  
343   - h4 {
344   - font-size:14px;
345   - padding:2px 10px;
346   - color:#666;
347   - border-bottom:1px solid #f1f1f1;
348   - }
349   - a:last-child h4 { border:none; }
350   -
351   - a:hover {
352   - h4 {
353   - color:#111;
354   - background:$hover;
355   - border-color:#CCC;
356   - .ico.project {
357   - background-position:-209px -21px;
358   - }
359   - }
360   - }
361   - .bottom {
362   - padding:10px;
363   - }
364   -}
365   -
366   -.votes {
367   - font-size: 13px;
368   - line-height: 15px;
369   - .progress {
370   - height: 4px;
371   - margin: 0;
372   - .bar {
373   - float: left;
374   - height: 100%;
375   - }
376   - .bar-success {
377   - background-color: #468847;
378   - @include bg-gradient(#62C462, #51A351);
379   - }
380   - .bar-danger {
381   - background-color: #B94A48;
382   - @include bg-gradient(#EE5F5B, #BD362F);
383   - }
384   - }
385   - .upvotes {
386   - display: inline-block;
387   - color: #468847;
388   - }
389   - .downvotes {
390   - display: inline-block;
391   - color: #B94A48;
392   - }
393   -}
394   -.votes-block {
395   - margin: 14px 6px 6px 0;
396   - .downvotes {
397   - float: right;
398   - }
399   -}
400   -.votes-inline {
401   - display: inline-block;
402   - margin: 0 8px;
403   - .progress {
404   - display: inline-block;
405   - padding: 0 0 2px;
406   - width: 45px;
407   - }
408   -}
409 288  
410 289 /* Fix for readme code (stopped it from being yellow) */
411 290 .readme {
... ... @@ -418,63 +297,45 @@ p.time {
418 297 }
419 298 }
420 299  
421   -
422 300 .highlight_word {
423   - background:#EEDC94;
  301 + background: #EEDC94;
424 302 }
425 303  
426 304 .status_info {
427   - font-size:14px;
428   - padding:5px 15px;
429   - line-height:24px;
430   - width:60px;
431   - text-align:center;
432   - float:left;
433   - margin-right:20px;
434   -
435   - &.success {
436   - background: #5BB75B;
437   - color: white;
438   - text-shadow: 0 1px #111;
439   - border-color: #9A9;
440   - }
  305 + font-size: 14px;
  306 + padding: 5px 15px;
  307 + line-height: 26px;
  308 + text-align: center;
  309 + float: right;
  310 + position: relative;
  311 + top: -5px;
  312 + @include border-radius(4px);
  313 +
441 314 &.error {
442 315 background: #DA4E49;
443   - border-color: #BD362F;
444   - color: white;
445   - text-shadow: 0 1px #111;
  316 + color: #FFF;
446 317 }
447 318 }
448 319  
449 320 .arrow{
450 321 background: #E3E5EA;
451 322 padding: 5px;
452   - margin-top:5px;
453   - border-radius: 5px;
  323 + margin-top: 5px;
  324 + @include border-radius(5px);
454 325 text-shadow: none;
455 326 color: #999;
456 327 line-height: 16px;
457   - font-weight:bold;
  328 + font-weight: bold;
458 329 }
459 330  
460 331 .thin_area{
461 332 height: 150px;
462 333 }
463 334  
464   -.gitlab_pagination {
465   - span a { color:$link_color; }
466   - .prev, .next, .current, .page a {
467   - padding:10px;
468   - }
469   - .current {
470   - border-bottom:2px solid $style_color;
471   - }
472   -}
473   -
474 335 // Fixes alignment on notes.
475 336 .new_note {
476 337 label {
477   - text-align:left;
  338 + text-align: left;
478 339 }
479 340 }
480 341  
... ... @@ -486,7 +347,7 @@ li.note {
486 347 border-bottom:none !important;
487 348 }
488 349 .file {
489   - padding-left:20px;
  350 + padding-left: 20px;
490 351 background:url("icon-attachment.png") no-repeat left center;
491 352 }
492 353 }
... ... @@ -494,7 +355,7 @@ li.note {
494 355  
495 356 .markdown {
496 357 img {
497   - max-width:100%;
  358 + max-width: 100%;
498 359 }
499 360 }
500 361  
... ... @@ -504,19 +365,19 @@ li.note {
504 365  
505 366 .team_member_show {
506 367 td:first-child {
507   - color:#aaa;
  368 + color: #aaa;
508 369 }
509 370 }
510 371  
511 372 .remember_me {
512   - text-align:left;
  373 + text-align: left;
513 374  
514 375 input {
515   - margin:0;
  376 + margin: 0;
516 377 }
517 378  
518 379 span {
519   - padding-left:5px;
  380 + padding-left: 5px;
520 381 }
521 382 }
522 383  
... ... @@ -530,10 +391,10 @@ li.note {
530 391 .data {
531 392 a {
532 393 h1 {
533   - line-height:48px;
534   - font-size:48px;
535   - padding:20px;
536   - text-align:center;
  394 + line-height: 48px;
  395 + font-size: 48px;
  396 + padding: 20px;
  397 + text-align: center;
537 398 }
538 399 }
539 400 }
... ... @@ -541,12 +402,12 @@ li.note {
541 402  
542 403 .rss-icon {
543 404 img {
544   - width:24px;
545   - vertical-align:top;
  405 + width: 24px;
  406 + vertical-align: top;
546 407 }
547 408  
548 409 strong {
549   - line-height:24px;
  410 + line-height: 24px;
550 411 }
551 412 }
552 413  
... ... @@ -554,43 +415,43 @@ li.note {
554 415  
555 416 /* CHZN reset few styles */
556 417 .chzn-container-single .chzn-single {
557   - background:#FFF;
  418 + background: #FFF;
558 419 border: 1px solid #bbb;
559   - box-shadow:none;
  420 + box-shadow: none;
560 421 }
561 422 .chzn-container-active .chzn-single {
562   - background:#fff;
  423 + background: #fff;
563 424 }
564 425  
565 426  
566 427 .supp_diff_link,
567 428 .mr_show_all_commits {
568   - cursor:pointer;
  429 + cursor: pointer;
569 430 }
570 431  
571 432 .merge_request,
572 433 .issue {
573 434 &.today{
574 435 background: #EFE;
575   - border-color:#CEC;
  436 + border-color: #CEC;
576 437 }
577 438 &.closed {
578 439 background: #F5f5f5;
579   - border-color:#E5E5E5;
  440 + border-color: #E5E5E5;
580 441 }
581 442 &.merged {
582 443 background: #F5f5f5;
583   - border-color:#E5E5E5;
  444 + border-color: #E5E5E5;
584 445 }
585 446 }
586 447  
587 448 .git_error_tips {
588 449 @extend .span6;
589   - text-align:left;
590   - margin-top:40px;
  450 + text-align: left;
  451 + margin-top: 40px;
591 452 pre {
592   - background:white;
593   - border:none;
  453 + background: white;
  454 + border: none;
594 455 font-size: 12px;
595 456 }
596 457 }
... ... @@ -602,18 +463,22 @@ li.note {
602 463 margin-bottom: 10px;
603 464 background: #FEE;
604 465 padding-left: 20px;
  466 +
  467 + &.centered {
  468 + text-align: center;
  469 + }
605 470 }
606 471  
607 472 .oauth_select_holder {
608   - padding:20px;
  473 + padding: 20px;
609 474 img {
610   - padding:5px;
611   - margin-right:10px;
  475 + padding: 5px;
  476 + margin-right: 10px;
612 477 }
613 478 .active {
614 479 img {
615   - border:1px solid #ccc;
616   - background:$hover;
  480 + border: 1px solid #ccc;
  481 + background: $hover;
617 482 @include border-radius(5px);
618 483 }
619 484 }
... ... @@ -627,29 +492,67 @@ li.note {
627 492  
628 493 .gitlab-promo {
629 494 a {
630   - color:#aaa;
  495 + color: #aaa;
631 496 margin-right: 30px;
632 497 }
633 498 }
634 499  
635 500 pre {
636 501 &.clean {
637   - background:none;
638   - border:none;
639   - margin:0;
640   - padding:0;
  502 + background: none;
  503 + border: none;
  504 + margin: 0;
  505 + padding: 0;
641 506 }
642 507 }
643 508  
644   -.milestone .progress {
645   - margin-bottom: 0;
646   - margin-top:4px;
  509 +.milestone {
  510 + &.milestone-closed {
  511 + background: #eee;
  512 + }
  513 + .progress {
  514 + margin-bottom: 0;
  515 + margin-top: 4px;
  516 + }
647 517 }
648 518  
649 519 .float-link {
650   - float:left;
651   - margin-right:15px;
  520 + float: left;
  521 + margin-right: 15px;
652 522 .s16 {
653   - margin-right:5px;
  523 + margin-right: 5px;
  524 + }
  525 +}
  526 +
  527 +.dashboard-search-filter {
  528 + padding:5px;
  529 +
  530 + .search-text-input {
  531 + float:left;
  532 + @extend .span2;
  533 + }
  534 + .btn {
  535 + margin-left: 5px;
  536 + float:left;
  537 + }
  538 +}
  539 +
  540 +h1.http_status_code {
  541 + font-size: 56px;
  542 + line-height: 100px;
  543 + font-weight: normal;
  544 + color: #456;
  545 +}
  546 +
  547 +.control-group {
  548 + .controls {
  549 + span {
  550 + &.descr {
  551 + position: relative;
  552 + top: 2px;
  553 + left: 5px;
  554 + color: #666;
  555 + }
  556 + }
654 557 }
655 558 }
... ...
app/assets/stylesheets/gitlab_bootstrap.scss 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +/** Override bootstrap variables **/
  2 +$baseFontSize: 13px !default;
  3 +$baseLineHeight: 18px !default;
  4 +
  5 +// BOOTSTRAP
  6 +@import "bootstrap";
  7 +@import "bootstrap/responsive-utilities";
  8 +@import "bootstrap/responsive-1200px-min";
  9 +
  10 +@import "font-awesome";
  11 +
  12 +/**
  13 + * GitLab bootstrap.
  14 + * Overrides some styles of twitter bootstrap.
  15 + * Also give some common classes for GitLab app
  16 + */
  17 +@import "gitlab_bootstrap/variables.scss";
  18 +@import "gitlab_bootstrap/fonts.scss";
  19 +@import "gitlab_bootstrap/mixins.scss";
  20 +@import "gitlab_bootstrap/common.scss";
  21 +@import "gitlab_bootstrap/typography.scss";
  22 +@import "gitlab_bootstrap/buttons.scss";
  23 +@import "gitlab_bootstrap/blocks.scss";
  24 +@import "gitlab_bootstrap/files.scss";
  25 +@import "gitlab_bootstrap/tables.scss";
  26 +@import "gitlab_bootstrap/lists.scss";
... ...
app/assets/stylesheets/gitlab_bootstrap/blocks.scss
... ... @@ -15,8 +15,8 @@
15 15 @extend .borders;
16 16 @extend .prepend-top-20;
17 17 @extend .append-bottom-20;
18   - border-width:1px;
19   - @include solid_shade;
  18 + border-width: 1px;
  19 + @include solid-shade;
20 20  
21 21  
22 22 img { max-width: 100%; }
... ... @@ -30,27 +30,37 @@
30 30 .top_box_content,
31 31 .middle_box_content,
32 32 .bottom_box_content {
33   - padding:15px;
  33 + padding: 15px;
  34 + word-wrap: break-word;
34 35  
35 36 pre {
36 37 background: none !important;
37   - margin:0;
38   - border:none;
39   - padding:0;
  38 + margin: 0;
  39 + border: none;
  40 + padding: 0;
  41 + }
  42 + }
  43 +
  44 + .top_box_content {
  45 + .box-title {
  46 + color: $style_color;
  47 + font-size: 18px;
  48 + font-weight: normal;
  49 + line-height: 28px;
40 50 }
41 51 }
42 52  
43 53 .middle_box_content {
44   - border-radius:0;
45   - border:none;
46   - font-size:12px;
47   - background-color:#f5f5f5;
48   - border:none;
49   - border-top:1px solid #eee;
  54 + @include border-radius(0);
  55 + border: none;
  56 + font-size: 12px;
  57 + background-color: #f5f5f5;
  58 + border: none;
  59 + border-top: 1px solid #eee;
50 60 }
51 61  
52 62 .bottom_box_content {
53   - border-top:1px solid #eee;
  63 + border-top: 1px solid #eee;
54 64 }
55 65 }
56 66  
... ... @@ -59,44 +69,52 @@
59 69 *
60 70 */
61 71 .ui-box {
62   - background:#F9F9F9;
  72 + background: #F9F9F9;
63 73 margin-bottom: 25px;
64   - @include round-borders-all(4px);
  74 +
  75 + border: 1px solid #eaeaea;
  76 + @include border-radius(4px);
  77 +
65 78 border-color: #CCC;
66   - @include solid_shade;
  79 + @include solid-shade;
67 80  
68 81 &.white {
69   - background:#fff;
  82 + background: #fff;
70 83 }
71 84  
72 85 ul {
73   - margin:0;
  86 + margin: 0;
74 87 }
75 88  
76 89 h5, .title {
77 90 padding: 0 10px;
78   - @include round-borders-top(4px);
  91 + @include border-radius(4px 4px 0 0);
79 92 @include bg-gray-gradient;
  93 + border-top: 1px solid #eaeaea;
80 94 border-bottom: 1px solid #bbb;
81 95  
  96 + > a {
  97 + text-shadow: 0 1px 1px #fff;
  98 + }
  99 +
82 100 &.small {
83 101 line-height: 28px;
84 102 font-size: 14px;
85   - line-height:28px;
  103 + line-height: 28px;
86 104 text-shadow: 0 1px 1px white;
87 105 }
88 106  
89 107 form {
90   - padding:9px 0;
91   - margin:0px;
  108 + padding: 9px 0;
  109 + margin: 0px;
92 110 }
93 111  
94 112 .nav-pills {
95 113 li {
96   - padding:3px 0;
97   - &.active a { background-color:$style_color; }
  114 + padding: 3px 0;
  115 + &.active a { background-color: $style_color; }
98 116 a {
99   - border-radius:7px;
  117 + @include border-radius(7px);
100 118 }
101 119 }
102 120 }
... ... @@ -104,8 +122,8 @@
104 122  
105 123 .bottom {
106 124 @include bg-gray-gradient;
107   - @include round-borders-bottom(4px);
108   - border-bottom:none;
  125 + @include border-radius(0 0 4px 4px);
  126 + border-bottom: none;
109 127 border-top: 1px solid #bbb;
110 128 }
111 129  
... ... @@ -116,38 +134,25 @@
116 134 padding: 5px 20px;
117 135 }
118 136 .middle_title {
119   - background:#f5f5f5;
  137 + background: #f5f5f5;
120 138 margin:20px -20px;
121 139 padding: 0 20px;
122   - border-top:1px solid #eee;
123   - border-bottom:1px solid #eee;
124   - font-size:14px;
125   - color:#777;
  140 + border-top: 1px solid #eee;
  141 + border-bottom: 1px solid #eee;
  142 + font-size: 14px;
  143 + color: #777;
126 144 }
127 145 }
128 146 .row_title {
129   - font-weight:bold;
130   - color:#444;
  147 + font-weight: bold;
  148 + color: #444;
131 149 &:hover {
132   - color:#444;
133   - text-decoration:underline;
134   - }
135   - }
136   -
137   - li, .wll {
138   - padding:10px;
139   - &:first-child {
140   - @include round-borders-top(4px);
141   - border-top:none;
142   - }
143   -
144   - &:last-child {
145   - @include round-borders-bottom(4px);
146   - border:none;
  150 + color: #444;
  151 + text-decoration: underline;
147 152 }
148 153 }
149 154  
150 155 .ui-box-body {
151   - padding:10px;
  156 + padding: 10px;
152 157 }
153 158 }
... ...
app/assets/stylesheets/gitlab_bootstrap/buttons.scss
1 1 .btn {
2   - @include bg-gradient(#f7f7f7, #d5d5d5);
3   - border-color:#aaa;
  2 + @include linear-gradient(#f7f7f7, #d5d5d5);
  3 + border-color: #aaa;
4 4 &:hover {
5 5 @include bg-gray-gradient;
6   - border-color:#bbb;
7   - color:#333;
  6 + border-color: #bbb;
  7 + color: #333;
8 8 }
9 9  
10 10 &.primary {
11   - background:#2a79A3;
12   - @include bg-gradient(#47A7b7, #2585b5);
  11 + background: #2a79A3;
  12 + @include linear-gradient(#47A7b7, #2585b5);
13 13 border-color: #2A79A3;
14   - color:#fff;
  14 + color: #fff;
15 15 text-shadow: 0 1px 1px #268;
16 16 &:hover {
17   - background:$blue_link;
18   - color:#fff;
  17 + background: $primary_color;
  18 + color: #fff;
19 19 }
20 20  
21 21 &.disabled {
22   - color:#fff;
23   - background:#29B;
  22 + color: #fff;
  23 + background: #29B;
24 24 }
25 25 }
26 26  
27 27 &.btn-info {
28   - background:#5aB9C3;
29   - border-color: $blue_link;
30   - color:#fff;
  28 + background: #5aB9C3;
  29 + border-color: $primary_color;
  30 + color: #fff;
31 31 text-shadow: 0 1px 1px #268;
32 32 &:hover {
33   - background:$blue_link;
34   - color:#fff;
  33 + background: $primary_color;
  34 + color: #fff;
35 35 }
36 36  
37 37 &.disabled {
38   - color:#fff;
39   - background:#29B;
  38 + color: #fff;
  39 + background: #29B;
40 40 }
41 41 }
42 42  
... ... @@ -49,8 +49,8 @@
49 49 }
50 50  
51 51 &.disabled {
52   - color:#fff;
53   - background:#2b2;
  52 + color: #fff;
  53 + background: #2b2;
54 54 }
55 55 }
56 56  
... ... @@ -60,12 +60,12 @@
60 60 }
61 61  
62 62 &.cancel-btn {
63   - float:right;
  63 + float: right;
64 64 }
65 65  
66 66 &.wide {
67   - padding-left:30px;
68   - padding-right:30px;
  67 + padding-left: 30px;
  68 + padding-right: 30px;
69 69 }
70 70  
71 71 &.danger {
... ... @@ -73,7 +73,7 @@
73 73 border-color: #BD362F;
74 74  
75 75 &:hover {
76   - color:#fff;
  76 + color: #fff;
77 77 background: #EE4E49;
78 78 }
79 79 }
... ... @@ -87,24 +87,24 @@
87 87 }
88 88  
89 89 &.active {
90   - border-color:#aaa;
91   - background-color:#ccc;
  90 + border-color: #aaa;
  91 + background-color: #ccc;
92 92 }
93 93  
94 94 &.very_small {
95   - font-size:11px;
96   - padding:2px 6px;
  95 + font-size: 11px;
  96 + padding: 2px 6px;
97 97 line-height: 16px;
98   - margin:2px;
  98 + margin: 2px;
99 99 }
100 100  
101 101 &.grouped {
102   - margin-right:7px;
103   - float:left;
  102 + margin-right: 7px;
  103 + float: left;
104 104 }
105 105  
106 106 &.padded {
107   - margin-right:3px;
108   - padding:4px 10px 4px;
  107 + margin-right: 3px;
  108 + padding: 4px 10px 4px;
109 109 }
110 110 }
... ...
app/assets/stylesheets/gitlab_bootstrap/common.scss
... ... @@ -10,11 +10,6 @@
10 10 /** COMMON CLASSES **/
11 11 .left { float:left }
12 12 .right { float:right!important }
13   -.width-50p { width:50% }
14   -.width-49p { width:49% }
15   -.width-30p { width:30% }
16   -.width-65p { width:65% }
17   -.width-100p { width:100% }
18 13 .append-bottom-10 { margin-bottom:10px }
19 14 .append-bottom-20 { margin-bottom:20px }
20 15 .prepend-top-10 { margin-top:10px }
... ... @@ -24,40 +19,42 @@
24 19 .lborder { border-left:1px solid #eee }
25 20 .no-padding { padding:0 !important; }
26 21 .underlined { border-bottom: 1px solid #CCC; }
27   -.no-borders { border:none; }
  22 +.no-borders { border: none; }
28 23 .vlink { color: $link_color !important; }
29 24 .underlined_link { text-decoration: underline; }
30 25 .borders { border: 1px solid #ccc; @include shade; }
31 26 .hint { font-style: italic; color: #999; }
32 27 .light { color: #888 }
  28 +.tiny { font-weight: normal }
33 29  
34 30 /** PILLS & TABS**/
35   -.nav-pills a:hover { background-color:#888; }
  31 +.nav-pills a:hover { background-color: #888; }
36 32 .nav-pills .active a { background-color: $style_color; }
37   -.nav-tabs > li > a, .nav-pills > li > a { color:$style_color; }
  33 +.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
  34 +.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
38 35 .nav.nav-tabs {
39 36 li {
40 37 > a {
41   - padding:8px 20px;
  38 + padding: 8px 20px;
42 39 margin-right: 7px;
43 40 line-height: 19px;
44 41 border-color: #EEE;
45   - color:#888;
  42 + color: #888;
46 43 border-bottom: 1px solid #ddd;
47 44 .badge {
48 45 background-color: #eee;
49   - color:#888;
50   - text-shadow:0 1px 1px #fff;
  46 + color: #888;
  47 + text-shadow: 0 1px 1px #fff;
51 48 }
52 49 i[class^="icon-"] {
53   - line-height:14px;
  50 + line-height: 14px;
54 51 }
55 52 }
56 53 &.active {
57 54 > a {
58 55 border-color: #CCC;
59 56 border-bottom: 1px solid #fff;
60   - color:#333;
  57 + color: #333;
61 58 }
62 59 }
63 60 }
... ... @@ -69,25 +66,50 @@
69 66 .alert-message.error { @extend .alert-error; }
70 67  
71 68 /** AVATARS **/
72   -img.avatar { float:left; margin-right:12px; width:40px; border:1px solid #ddd; padding:1px; }
73   -img.avatar.s16 { width:16px; height:16px; margin-right:6px; }
74   -img.avatar.s24 { width:24px; height:24px; margin-right:8px; }
75   -img.avatar.s32 { width:32px; height:32px; margin-right:10px; }
76   -img.lil_av { padding-left: 4px; padding-right:3px; }
  69 +img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
  70 +img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
  71 +img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
  72 +img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
  73 +img.lil_av { padding-left: 4px; padding-right: 3px; }
77 74 img.small { width: 80px; }
78 75  
79 76 /** HELPERS **/
80   -.nothing_here_message { text-align:center; padding:20px; color:#777; }
81   -p.slead { color:#456; font-size:16px; margin-bottom: 12px; font-weight: 200; line-height: 24px; }
  77 +.nothing_here_message {
  78 + text-align: center;
  79 + padding: 20px;
  80 + color: #666;
  81 + font-weight: normal;
  82 + font-size: 16px;
  83 + line-height: 36px;
  84 +}
  85 +
  86 +p.slead { color: #456; font-size: 16px; margin-bottom: 12px; font-weight: 200; line-height: 24px; }
82 87  
83 88 /** FORMS **/
84 89 input[type='search'].search-text-input {
85 90 background-image: url("icon-search.png");
86 91 background-repeat: no-repeat;
87 92 background-position: 10px;
88   - padding-left:25px;
  93 + padding-left: 25px;
89 94 @include border-radius(4px);
90   - border:1px solid #ccc;
  95 + border: 1px solid #ccc;
  96 +}
  97 +
  98 +input[type='text'].danger {
  99 + background: #F2DEDE!important;
  100 + border-color: #D66;
  101 + text-shadow: 0 1px 1px #fff
91 102 }
92 103  
93 104 fieldset legend { font-size: 17px; }
  105 +
  106 +/** PAGINATION **/
  107 +.gitlab_pagination {
  108 + span a { color: $link_color; }
  109 + .prev, .next, .current, .page a {
  110 + padding: 10px;
  111 + }
  112 + .current {
  113 + border-bottom: 2px solid $style_color;
  114 + }
  115 +}
... ...
app/assets/stylesheets/gitlab_bootstrap/files.scss
... ... @@ -3,9 +3,9 @@
3 3 *
4 4 */
5 5 .file_holder {
6   - border:1px solid #BBB;
7   - margin-bottom:1em;
8   - @include solid_shade;
  6 + border: 1px solid #BBB;
  7 + margin-bottom: 1em;
  8 + @include solid-shade;
9 9  
10 10 .file_title {
11 11 border-bottom: 1px solid #bbb;
... ... @@ -16,47 +16,51 @@
16 16 text-align: left;
17 17 color: #666;
18 18 padding: 9px 10px;
19   - height:18px;
  19 + height: 18px;
20 20  
21 21 .options {
22   - float:right;
  22 + float: right;
23 23 margin-top: -5px;
24 24 }
25 25  
26 26 .file_name {
27   - color:$style_color;
28   - font-size:14px;
  27 + color: $style_color;
  28 + font-size: 14px;
29 29 text-shadow: 0 1px 1px #fff;
30 30 small {
31   - color:#999;
32   - font-size:13px;
  31 + color: #999;
  32 + font-size: 13px;
33 33 }
34 34 }
35 35 }
36 36 .file_content {
37   - background:#fff;
  37 + background: #fff;
38 38 font-size: 11px;
39 39  
40 40 &.wiki {
41 41 font-size: 13px;
42 42 code {
43   - padding:0 4px;
  43 + padding: 0 4px;
44 44 }
45   - padding:20px;
46   - h1, h2 {
47   - line-height: 46px;
48   - }
49   - h3, h4 {
50   - line-height: 40px;
  45 + padding: 20px;
  46 +
  47 + h1 { font-size: 26px; line-height: 46px; }
  48 + h2 { font-size: 22px; line-height: 42px; }
  49 + h3 { font-size: 20px; line-height: 40px; }
  50 + h4 { font-size: 18px; line-height: 32px; }
  51 + h5 { font-size: 16px; line-height: 26px; }
  52 +
  53 + .white .highlight pre {
  54 + background: #f5f5f5;
51 55 }
52 56 }
53 57  
54 58 &.image_file {
55   - background:#eee;
56   - text-align:center;
  59 + background: #eee;
  60 + text-align: center;
57 61 img {
58   - padding:100px;
59   - max-width:300px;
  62 + padding: 100px;
  63 + max-width: 300px;
60 64 }
61 65 }
62 66  
... ... @@ -69,60 +73,60 @@
69 73 */
70 74 &.blame {
71 75 table {
72   - border:none;
73   - box-shadow:none;
74   - margin:0;
  76 + border: none;
  77 + box-shadow: none;
  78 + margin: 0;
75 79 }
76 80 tr {
77 81 border-bottom: 1px solid #eee;
78 82 }
79 83 td {
80 84 &:first-child {
81   - border-left:none;
  85 + border-left: none;
82 86 }
83 87 &:last-child {
84   - border-right:none;
  88 + border-right: none;
85 89 }
86   - background:#fff;
87   - padding:5px;
  90 + background: #fff;
  91 + padding: 5px;
88 92 }
89 93 .author,
90 94 .blame_commit {
91   - background:#f5f5f5;
92   - vertical-align:top;
  95 + background: #f5f5f5;
  96 + vertical-align: top;
93 97 }
94 98 .lines {
95 99 pre {
96   - padding:0;
97   - margin:0;
98   - background:none;
99   - border:none;
  100 + padding: 0;
  101 + margin: 0;
  102 + background: none;
  103 + border: none;
100 104 }
101 105 }
102 106 }
103 107  
104 108 &.logs {
105   - background:#eee;
  109 + background: #eee;
106 110 max-height: 700px;
107 111 overflow-y: auto;
108 112  
109 113 ol {
110   - margin-left:40px;
  114 + margin-left: 40px;
111 115 padding: 10px 0;
112 116 border-left: 1px solid #CCC;
113   - margin-bottom:0;
  117 + margin-bottom: 0;
114 118 background: white;
115 119 li {
116   - color:#888;
  120 + color: #888;
117 121 p {
118   - margin:0;
119   - color:#333;
120   - line-height:24px;
  122 + margin: 0;
  123 + color: #333;
  124 + line-height: 24px;
121 125 padding-left: 10px;
122 126 }
123 127  
124 128 &:hover {
125   - background:$hover;
  129 + background: $hover;
126 130 }
127 131 }
128 132 }
... ... @@ -142,8 +146,8 @@
142 146 table-layout: fixed;
143 147  
144 148 pre {
145   - background: none;
146 149 border: none;
  150 + border-radius: 0;
147 151 font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
148 152 font-size: 12px !important;
149 153 line-height: 16px !important;
... ...
app/assets/stylesheets/gitlab_bootstrap/fonts.scss 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +@font-face{
  2 + font-family: Korolev;
  3 + src: font-url('korolev-medium-compressed.otf');
  4 +}
  5 +
  6 +/** Typo **/
  7 +$monospace: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
0 8 \ No newline at end of file
... ...
app/assets/stylesheets/gitlab_bootstrap/lists.scss
1   -/** LISTS **/
2   -
3   -ul {
4   - /**
5   - * List li block element #1
6   - *
7   - */
8   - .wll {
  1 +/**
  2 + * Well styled list
  3 + *
  4 + */
  5 +.well-list {
  6 + margin: 0;
  7 + list-style: none;
  8 + li {
9 9 background-color: #FFF;
10   - padding: 10px 5px;
  10 + padding: 10px;
11 11 min-height: 20px;
12 12 border-bottom: 1px solid #eee;
13 13 border-bottom: 1px solid rgba(0, 0, 0, 0.05);
14 14  
15   - &.smoke { background-color:#f5f5f5; }
  15 + &.disabled {
  16 + color: #888;
  17 + }
  18 +
  19 + &.smoke { background-color: #f5f5f5; }
  20 +
16 21 &:hover {
17   - background:$hover;
18   - border-bottom:1px solid #ADF;
  22 + background: $hover;
  23 + border-bottom: 1px solid #ADF;
19 24 }
20   - &:last-child { border:none }
  25 +
  26 + &:first-child {
  27 + @include border-radius(4px 4px 0 0);
  28 + border-top: none;
  29 + }
  30 +
  31 + &:last-child {
  32 + @include border-radius(0 0 4px 4px);
  33 + border: none;
  34 + }
  35 +
21 36 .author { color: #999; }
22 37  
23 38 p {
24 39 padding-top: 1px;
25   - margin:0;
26   - color:#222;
  40 + margin: 0;
  41 + color: #222;
27 42 img {
28   - position:relative;
29   - top:3px;
  43 + position: relative;
  44 + top: 3px;
30 45 }
31 46 }
  47 +
  48 + .well-title {
  49 + font-size: 14px;
  50 + line-height: 18px;
  51 + }
32 52 }
33 53 }
34 54  
35 55 ol, ul {
36 56 &.styled {
37 57 li {
38   - padding:2px;
  58 + padding: 2px;
39 59 }
40 60 }
41 61 }
  62 +
  63 +/** light list with border-bottom between li **/
  64 +ul.bordered-list {
  65 + margin: 5px 0px;
  66 + padding: 0px;
  67 + li {
  68 + padding: 5px 0;
  69 + border-bottom: 1px solid #EEE;
  70 + overflow: hidden;
  71 + display: block;
  72 + margin: 0px;
  73 + &:last-child { border:none }
  74 + }
  75 +}
... ...
app/assets/stylesheets/gitlab_bootstrap/mixins.scss 0 → 100644
... ... @@ -0,0 +1,69 @@
  1 +/**
  2 + * Generic mixins
  3 + */
  4 + @mixin box-shadow($shadow) {
  5 + -webkit-box-shadow: $shadow;
  6 + -moz-box-shadow: $shadow;
  7 + -ms-box-shadow: $shadow;
  8 + -o-box-shadow: $shadow;
  9 + box-shadow: $shadow;
  10 +}
  11 +
  12 +@mixin border-radius($radius) {
  13 + -webkit-border-radius: $radius;
  14 + -moz-border-radius: $radius;
  15 + -ms-border-radius: $radius;
  16 + -o-border-radius: $radius;
  17 + border-radius: $radius;
  18 +}
  19 +
  20 +@mixin linear-gradient($from, $to) {
  21 + background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
  22 + background-image: -webkit-linear-gradient($from, $to);
  23 + background-image: -moz-linear-gradient($from, $to);
  24 + background-image: -o-linear-gradient($from, $to);
  25 +}
  26 +
  27 +/**
  28 + * Prefilled mixins
  29 + * Mixins with fixed values
  30 + */
  31 +@mixin bg-light-gray-gradient {
  32 + background: #f1f1f1;
  33 + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
  34 + background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
  35 + background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
  36 + background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
  37 +}
  38 +
  39 +@mixin bg-gray-gradient {
  40 + background: #eee;
  41 + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
  42 + background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
  43 + background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
  44 + background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
  45 +}
  46 +
  47 +@mixin bg-dark-gray-gradient {
  48 + background: #eee;
  49 + background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
  50 + background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
  51 + background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
  52 +}
  53 +
  54 +@mixin shade {
  55 + @include box-shadow(0 0 3px #ddd);
  56 +}
  57 +
  58 +@mixin solid-shade {
  59 + @include box-shadow(0 0 0 3px #f1f1f1);
  60 +}
  61 +
  62 +@mixin header-font {
  63 + color: $style_color;
  64 + text-shadow: 0 1px 1px #FFF;
  65 + font-family: 'Korolev', sans-serif;
  66 + font-size: 28px;
  67 + line-height: 48px;
  68 + font-weight: normal;
  69 +}
... ...
app/assets/stylesheets/gitlab_bootstrap/tables.scss
1 1 table {
2 2 @extend .table;
3 3 @extend .table-striped;
4   - @include solid_shade;
5   - border:1px solid #bbb;
6   - width:100%;
  4 + @include solid-shade;
  5 + border: 1px solid #bbb;
  6 + width: 100%;
7 7  
8 8 &.low {
9 9 td {
10   - line-height:18px;
  10 + line-height: 18px;
11 11 }
12 12 }
13 13  
... ... @@ -31,8 +31,8 @@ table {
31 31 }
32 32  
33 33 td {
34   - border-color:#f1f1f1;
35   - line-height:28px;
  34 + border-color: #f1f1f1;
  35 + line-height: 28px;
36 36  
37 37 .s16 {
38 38 margin-top: 5px;
... ... @@ -40,11 +40,11 @@ table {
40 40 }
41 41  
42 42 &:first-child {
43   - border-left:1px solid #bbb;
  43 + border-left: 1px solid #bbb;
44 44 }
45 45  
46 46 &:last-child {
47   - border-right:1px solid #bbb;
  47 + border-right: 1px solid #bbb;
48 48 }
49 49 }
50 50  
... ... @@ -53,10 +53,10 @@ table {
53 53 }
54 54  
55 55 &.lite {
56   - border:none;
57   - box-shadow:none;
  56 + border: none;
  57 + box-shadow: none;
58 58 tr, td {
59   - border:none;
  59 + border: none;
60 60 background:none !important;
61 61 }
62 62 }
... ...
app/assets/stylesheets/gitlab_bootstrap/typography.scss
... ... @@ -5,11 +5,11 @@
5 5  
6 6 h1, h2, h3, h4, h5, h6 { margin: 0; }
7 7 h3, h4, h5, h6 { line-height: 36px; }
8   -h5 { font-size:14px; }
  8 +h5 { font-size: 14px; }
9 9  
10 10 h3.page_title {
11   - color:#456;
12   - font-size:20px;
  11 + color: #456;
  12 + font-size: 20px;
13 13 font-weight: normal;
14 14 line-height: 28px;
15 15 }
... ... @@ -25,7 +25,7 @@ pre {
25 25  
26 26 &.dark {
27 27 background: #333;
28   - color:#f5f5f5;
  28 + color: #f5f5f5;
29 29 }
30 30 }
31 31  
... ... @@ -37,8 +37,8 @@ a {
37 37 outline: none;
38 38 color: $link_color;
39 39 &:hover {
40   - text-decoration:none;
41   - color: $blue_link;
  40 + text-decoration: none;
  41 + color: $primary_color;
42 42 }
43 43  
44 44 &.btn {
... ... @@ -53,27 +53,31 @@ a {
53 53 }
54 54  
55 55 &.lined {
56   - text-decoration:underline;
57   - &:hover { text-decoration:underline; }
  56 + text-decoration: underline;
  57 + &:hover { text-decoration: underline; }
58 58 }
59 59  
60 60 &.gray {
61   - color:gray;
  61 + color: gray;
62 62 }
63 63  
64 64 &.supp_diff_link {
65   - text-align:center;
66   - padding:20px 0;
67   - background:#f1f1f1;
68   - width:100%;
69   - float:left;
  65 + text-align: center;
  66 + padding: 20px 0;
  67 + background: #f1f1f1;
  68 + width: 100%;
  69 + float: left;
70 70 }
71 71  
72 72 &.neib {
73   - margin-right:15px;
  73 + margin-right: 15px;
74 74 }
75 75 }
76 76  
77 77 a:focus {
78 78 outline: none;
79 79 }
  80 +
  81 +.monospace {
  82 + font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
  83 +}
... ...
app/assets/stylesheets/gitlab_bootstrap/variables.scss 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +/** Colors **/
  2 +$primary_color: #2FA0BB;
  3 +$link_color: #3A89A3;
  4 +$style_color: #474D57;
  5 +$hover: #D9EDF7;
... ...
app/assets/stylesheets/highlight/dark.scss
1   -.black .lines .highlight {
2   - background: #333;
3   - pre { color: #eee; }
  1 +.black .highlight {
  2 + background-color: #333;
  3 + pre {
  4 + color: #eee;
  5 + background: inherit;
  6 + }
4 7  
5 8 .hll { display: block; background-color: darken($hover, 65%) }
6 9 .c { color: #888888; font-style: italic } /* Comment */
... ... @@ -21,43 +24,43 @@
21 24 .gs { font-weight: bold } /* Generic.Strong */
22 25 .gu { color: #606060 } /* Generic.Subheading */
23 26 .gt { color: #aa0000 } /* Generic.Traceback */
24   - .kc{font-weight:bold;} /* Keyword.Constant */
25   - .kd{font-weight:bold;} /* Keyword.Declaration */
26   - .kn{font-weight:bold;} /* Keyword.Namespace */
27   - .kp{font-weight:bold;} /* Keyword.Pseudo */
28   - .kr{font-weight:bold;} /* Keyword.Reserved */
29   - .kt{color:#458;font-weight:bold;} /* Keyword.Type */
  27 + .kc{font-weight: bold;} /* Keyword.Constant */
  28 + .kd{font-weight: bold;} /* Keyword.Declaration */
  29 + .kn{font-weight: bold;} /* Keyword.Namespace */
  30 + .kp{font-weight: bold;} /* Keyword.Pseudo */
  31 + .kr{font-weight: bold;} /* Keyword.Reserved */
  32 + .kt{color: #458;font-weight: bold;} /* Keyword.Type */
30 33 .m { color: #0000DD; font-weight: bold } /* Literal.Number */
31 34 .p { color: #eee; }
32 35 .s { color: #0AD; background-color: transparent } /* Literal.String */
33   - .na{color:#008080;} /* Name.Attribute */
34   - .nb{color:#0086B3;} /* Name.Builtin */
35   - .nc{color:#ccc;font-weight:bold;} /* Name.Class */
36   - .no{color:turquoise;} /* Name.Constant */
37   - .ni{color:#800080;}
38   - .ne{color:#900;font-weight:bold;} /* Name.Exception */
39   - .nf{color:#ccc;font-weight:bold;} /* Name.Function */
40   - .nn{color:#79C3E0;font-weight:bold;} /* Name.Namespace */
41   - .nt{color:#fc5;} /* Name.Tag */
42   - .nv{color:#FA4;} /* Name.Variable */
  36 + .na{color: #008080;} /* Name.Attribute */
  37 + .nb{color: #0086B3;} /* Name.Builtin */
  38 + .nc{color: #ccc;font-weight: bold;} /* Name.Class */
  39 + .no{color: turquoise;} /* Name.Constant */
  40 + .ni{color: #800080;}
  41 + .ne{color: #900;font-weight: bold;} /* Name.Exception */
  42 + .nf{color: #ccc;font-weight: bold;} /* Name.Function */
  43 + .nn{color: #79C3E0;font-weight: bold;} /* Name.Namespace */
  44 + .nt{color: #fc5;} /* Name.Tag */
  45 + .nv{color: #FA4;} /* Name.Variable */
43 46 .py { color: #336699; font-weight: bold } /* Name.Property */
44 47 .ow { color: #008800 } /* Operator.Word */
45 48 .w { color: #bbbbbb } /* Text.Whitespace */
46 49 .mf { color: #7AC; font-weight: bold } /* Literal.Number.Float */
47 50 .mh { color: #7AC; font-weight: bold } /* Literal.Number.Hex */
48   - .mi {color:#099;} /* Literal.Number.Integer */
  51 + .mi {color: #099;} /* Literal.Number.Integer */
49 52 .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
50 53 .sb { color: #dd2200; background-color: transparent; } /* Literal.String.Backtick */
51   - .sc{color:#d14;} /* Literal.String.Char */
  54 + .sc{color: #d14;} /* Literal.String.Char */
52 55 .sd { color: #dd2200; background-color: transparent; } /* Literal.String.Doc */
53   - .s2{color:orange;} /* Literal.String.Double */
54   - .se{color:orange;} /* Literal.String.Escape */
55   - .sh{color:orange;} /* Literal.String.Heredoc */
56   - .si{color:orange;} /* Literal.String.Interpol */
57   - .sx{color:orange;} /* Literal.String.Other */
58   - .sr{color:orange;} /* Literal.String.Regex */
59   - .s1{color:orange;} /* Literal.String.Single */
60   - .ss{color:orange;} /* Literal.String.Symbol */
  56 + .s2{color: orange;} /* Literal.String.Double */
  57 + .se{color: orange;} /* Literal.String.Escape */
  58 + .sh{color: orange;} /* Literal.String.Heredoc */
  59 + .si{color: orange;} /* Literal.String.Interpol */
  60 + .sx{color: orange;} /* Literal.String.Other */
  61 + .sr{color: orange;} /* Literal.String.Regex */
  62 + .s1{color: orange;} /* Literal.String.Single */
  63 + .ss{color: orange;} /* Literal.String.Symbol */
61 64 .bp { color: #D58 } /* Name.Builtin.Pseudo */
62 65 .vc { color: #336699 } /* Name.Variable.Class */
63 66 .vg { color: #dd7700 } /* Name.Variable.Global */
... ...
app/assets/stylesheets/highlight/white.scss
1   -.white .lines .highlight {
2   - background: white;
3   - pre { color: #333; }
  1 +.white .highlight {
  2 + pre {
  3 + background-color: #fff;
  4 + color: #333;
  5 + }
4 6  
5 7 .hll { display: block; background-color: $hover }
6 8 .c { color: #888888; font-style: italic } /* Comment */
... ... @@ -20,42 +22,42 @@
20 22 .gs { font-weight: bold } /* Generic.Strong */
21 23 .gu { color: #606060 } /* Generic.Subheading */
22 24 .gt { color: #aa0000 } /* Generic.Traceback */
23   - .kc{font-weight:bold;} /* Keyword.Constant */
24   - .kd{font-weight:bold;} /* Keyword.Declaration */
25   - .kn{font-weight:bold;} /* Keyword.Namespace */
26   - .kp{font-weight:bold;} /* Keyword.Pseudo */
27   - .kr{font-weight:bold;} /* Keyword.Reserved */
28   - .kt{color:#458;font-weight:bold;} /* Keyword.Type */
  25 + .kc{font-weight: bold;} /* Keyword.Constant */
  26 + .kd{font-weight: bold;} /* Keyword.Declaration */
  27 + .kn{font-weight: bold;} /* Keyword.Namespace */
  28 + .kp{font-weight: bold;} /* Keyword.Pseudo */
  29 + .kr{font-weight: bold;} /* Keyword.Reserved */
  30 + .kt{color: #458;font-weight: bold;} /* Keyword.Type */
29 31 .m { color: #0000DD; font-weight: bold } /* Literal.Number */
30 32 .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
31   - .na{color:#008080;} /* Name.Attribute */
32   - .nb{color:#0086B3;} /* Name.Builtin */
33   - .nc{color:#458;font-weight:bold;} /* Name.Class */
34   - .no{color:#008080;} /* Name.Constant */
35   - .ni{color:#800080;}
36   - .ne{color:#900;font-weight:bold;} /* Name.Exception */
37   - .nf{color:#900;font-weight:bold;} /* Name.Function */
38   - .nn{color:#005;font-weight:bold;} /* Name.Namespace */
39   - .nt{color:#000080;} /* Name.Tag */
40   - .nv{color:#008080;} /* Name.Variable */
  33 + .na{color: #008080;} /* Name.Attribute */
  34 + .nb{color: #0086B3;} /* Name.Builtin */
  35 + .nc{color: #458;font-weight: bold;} /* Name.Class */
  36 + .no{color: #008080;} /* Name.Constant */
  37 + .ni{color: #800080;}
  38 + .ne{color: #900;font-weight: bold;} /* Name.Exception */
  39 + .nf{color: #900;font-weight: bold;} /* Name.Function */
  40 + .nn{color: #005;font-weight: bold;} /* Name.Namespace */
  41 + .nt{color: #000080;} /* Name.Tag */
  42 + .nv{color: #008080;} /* Name.Variable */
41 43 .py { color: #336699; font-weight: bold } /* Name.Property */
42 44 .ow { color: #008800 } /* Operator.Word */
43 45 .w { color: #bbbbbb } /* Text.Whitespace */
44 46 .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
45 47 .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
46   - .mi {color:#099;} /* Literal.Number.Integer */
  48 + .mi {color: #099;} /* Literal.Number.Integer */
47 49 .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
48 50 .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
49   - .sc{color:#d14;} /* Literal.String.Char */
  51 + .sc{color: #d14;} /* Literal.String.Char */
50 52 .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
51   - .s2{color:#d14;} /* Literal.String.Double */
52   - .se{color:#d14;} /* Literal.String.Escape */
53   - .sh{color:#d14;} /* Literal.String.Heredoc */
54   - .si{color:#d14;} /* Literal.String.Interpol */
55   - .sx{color:#d14;} /* Literal.String.Other */
56   - .sr{color:#d14;} /* Literal.String.Regex */
57   - .s1{color:#d14;} /* Literal.String.Single */
58   - .ss{color:#d14;} /* Literal.String.Symbol */
  53 + .s2{color: #d14;} /* Literal.String.Double */
  54 + .se{color: #d14;} /* Literal.String.Escape */
  55 + .sh{color: #d14;} /* Literal.String.Heredoc */
  56 + .si{color: #d14;} /* Literal.String.Interpol */
  57 + .sx{color: #d14;} /* Literal.String.Other */
  58 + .sr{color: #d14;} /* Literal.String.Regex */
  59 + .s1{color: #d14;} /* Literal.String.Single */
  60 + .ss{color: #d14;} /* Literal.String.Symbol */
59 61 .bp { color: #003388 } /* Name.Builtin.Pseudo */
60 62 .vc { color: #336699 } /* Name.Variable.Class */
61 63 .vg { color: #dd7700 } /* Name.Variable.Global */
... ... @@ -63,7 +65,5 @@
63 65 }
64 66  
65 67 .shadow {
66   - -webkit-box-shadow:0 5px 15px #000;
67   - -moz-box-shadow:0 5px 15px #000;
68   - box-shadow:0 5px 15px #000;
  68 + @include box-shadow(0 5px 15px #000);
69 69 }
... ...
app/assets/stylesheets/jquery.ui.gitlab.css 0 → 100644
... ... @@ -0,0 +1,257 @@
  1 +/* Interaction Cues
  2 +----------------------------------*/
  3 +.ui-state-disabled { cursor: default !important; }
  4 +
  5 +
  6 +/* Icons
  7 +----------------------------------*/
  8 +
  9 +/* states and images */
  10 +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
  11 +
  12 +
  13 +/* Misc visuals
  14 +----------------------------------*/
  15 +
  16 +/* Overlays */
  17 +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
  18 +
  19 +
  20 +/*
  21 + * jQuery UI CSS Framework 1.8.7
  22 + *
  23 + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  24 + * Dual licensed under the MIT or GPL Version 2 licenses.
  25 + * http://jquery.org/license
  26 + *
  27 + * http://docs.jquery.com/UI/Theming/API
  28 + *
  29 + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller
  30 + */
  31 +
  32 +
  33 +/* Component containers
  34 +----------------------------------*/
  35 +.ui-widget { font-family: Arial,sans-serif; font-size: 1.1em; }
  36 +.ui-widget .ui-widget { font-size: 1em; }
  37 +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Arial,sans-serif; font-size: 1em; }
  38 +.ui-widget-content { border: 1px solid #CCC; background: #ffffff; color: #4F4F4F; }
  39 +.ui-widget-content a { color: #4F4F4F; }
  40 +.ui-widget-header { border: 1px solid #B6B6B6; color: #4F4F4F; font-weight: bold; }
  41 +.ui-widget-header {
  42 + background: #ededed url(bg_fallback.png) 0 0 repeat-x; /* Old browsers */
  43 + background: -moz-linear-gradient(top, #ededed 0%, #c4c4c4 100%); /* FF3.6+ */
  44 + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ededed), color-stop(100%,#c4c4c4)); /* Chrome,Safari4+ */
  45 + background: -webkit-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Chrome10+,Safari5.1+ */
  46 + background: -o-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Opera11.10+ */
  47 + background: -ms-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* IE10+ */
  48 + background: linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* W3C */
  49 +}
  50 +.ui-widget-header a { color: #4F4F4F; }
  51 +
  52 +/* Interaction states
  53 +----------------------------------*/
  54 +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #B6B6B6; font-weight: normal; color: #4F4F4F; }
  55 +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
  56 + background: #ededed url(bg_fallback.png) 0 0 repeat-x; /* Old browsers */
  57 + background: -moz-linear-gradient(top, #ededed 0%, #c4c4c4 100%); /* FF3.6+ */
  58 + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ededed), color-stop(100%,#c4c4c4)); /* Chrome,Safari4+ */
  59 + background: -webkit-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Chrome10+,Safari5.1+ */
  60 + background: -o-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Opera11.10+ */
  61 + background: -ms-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* IE10+ */
  62 + background: linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* W3C */
  63 + -webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
  64 + -moz-box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
  65 + box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
  66 +}
  67 +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #4F4F4F; text-decoration: none; }
  68 +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #9D9D9D; font-weight: normal; color: #313131; }
  69 +.ui-state-hover a, .ui-state-hover a:hover { color: #313131; text-decoration: none; }
  70 +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {
  71 + outline: none;
  72 + color: #1c4257; border: 1px solid #7096ab;
  73 + background: #ededed url(bg_fallback.png) 0 -50px repeat-x; /* Old browsers */
  74 + background: -moz-linear-gradient(top, #b9e0f5 0%, #92bdd6 100%); /* FF3.6+ */
  75 + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b9e0f5), color-stop(100%,#92bdd6)); /* Chrome,Safari4+ */
  76 + background: -webkit-linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* Chrome10+,Safari5.1+ */
  77 + background: -o-linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* Opera11.10+ */
  78 + background: -ms-linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* IE10+ */
  79 + background: linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* W3C */
  80 + -webkit-box-shadow: none;
  81 + -moz-box-shadow: none;
  82 + box-shadow: none;
  83 +}
  84 +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #313131; text-decoration: none; }
  85 +.ui-widget :active { outline: none; }
  86 +
  87 +/* Interaction Cues
  88 +----------------------------------*/
  89 +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight { border: 1px solid #d2dbf4; background: #f4f8fd; color: #0d2054; -moz-border-radius: 0 !important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }
  90 +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
  91 +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error { border: 1px solid #e2d0d0; background: #fcf0f0; color: #280b0b; -moz-border-radius: 0 !important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }
  92 +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
  93 +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
  94 +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
  95 +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
  96 +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
  97 +
  98 +/* Icons
  99 +----------------------------------*/
  100 +
  101 +/* states and images */
  102 +.ui-icon { width: 16px; height: 16px; background-image: url(ui-icons_222222_256x240.png); }
  103 +.ui-widget-content .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
  104 +.ui-widget-header .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
  105 +.ui-state-default .ui-icon { background-image: url(ui-icons_454545_256x240.png); }
  106 +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
  107 +.ui-state-active .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
  108 +.ui-state-highlight .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
  109 +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon { background: url(icon_sprite.png) -16px 0 no-repeat !important; }
  110 +.ui-state-highlight .ui-icon, .ui-state-error .ui-icon { margin-top: -1px; }
  111 +
  112 +
  113 +/* Misc visuals
  114 +----------------------------------*/
  115 +
  116 +/* Overlays */
  117 +.ui-widget-overlay { background: #262b33; opacity: .70;filter:Alpha(Opacity=70); }
  118 +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #000000; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
  119 +/*
  120 + * jQuery UI Selectable 1.8.7
  121 + *
  122 + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  123 + * Dual licensed under the MIT or GPL Version 2 licenses.
  124 + * http://jquery.org/license
  125 + *
  126 + * http://docs.jquery.com/UI/Selectable#theming
  127 + */
  128 +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
  129 +/*
  130 + * jQuery UI Autocomplete 1.8.7
  131 + *
  132 + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  133 + * Dual licensed under the MIT or GPL Version 2 licenses.
  134 + * http://jquery.org/license
  135 + *
  136 + * http://docs.jquery.com/UI/Autocomplete#theming
  137 + */
  138 +.ui-autocomplete {
  139 + position: absolute; cursor: default; z-index: 3;
  140 + -moz-border-radius: 0;
  141 + -webkit-border-radius: 0;
  142 + border-radius: 0;
  143 + -moz-box-shadow: 0 1px 5px rgba(0,0,0,0.3);
  144 + -webkit-box-shadow: 0 1px 5px rgba(0,0,0,0.3);
  145 + box-shadow: 0 1px 5px rgba(0,0,0,0.3);
  146 +}
  147 +
  148 +/* workarounds */
  149 +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
  150 +
  151 +/*
  152 + * jQuery UI Menu 1.8.7
  153 + *
  154 + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  155 + * Dual licensed under the MIT or GPL Version 2 licenses.
  156 + * http://jquery.org/license
  157 + *
  158 + * http://docs.jquery.com/UI/Menu#theming
  159 + */
  160 +.ui-menu {
  161 + list-style:none;
  162 + padding: 1px;
  163 + margin: 0;
  164 + display:block;
  165 + float: left;
  166 +}
  167 +.ui-menu .ui-menu {
  168 + margin-top: -3px;
  169 +}
  170 +.ui-menu .ui-menu-item {
  171 + margin:0;
  172 + padding: 0;
  173 + zoom: 1;
  174 + float: left;
  175 + clear: left;
  176 + width: 100%;
  177 +}
  178 +.ui-menu .ui-menu-item a {
  179 + text-decoration:none;
  180 + display:block;
  181 + padding:.2em .4em;
  182 + line-height:1.5;
  183 + zoom:1;
  184 + color: #666;
  185 + font-size: 13px;
  186 +}
  187 +.ui-menu .ui-menu-item a.ui-state-hover,
  188 +.ui-menu .ui-menu-item a.ui-state-active {
  189 + font-weight: normal;
  190 + margin: -1px;
  191 + background: #D9EDF7;
  192 + color: #3A89A3;
  193 + text-shadow: 0px 1px 1px #fff;
  194 + border: none;
  195 + border: 1px solid #ADE;
  196 + cursor: pointer;
  197 + font-weight: bold;
  198 +}
  199 +
  200 +/*
  201 + * jQuery UI Datepicker 1.8.7
  202 + *
  203 + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
  204 + * Dual licensed under the MIT or GPL Version 2 licenses.
  205 + * http://jquery.org/license
  206 + *
  207 + * http://docs.jquery.com/UI/Datepicker#theming
  208 + */
  209 +.ui-datepicker {
  210 + width: 17em;
  211 + padding: 0;
  212 + display: none;
  213 + border-color: #DDDDDD;
  214 + border: none;
  215 + box-shadow: none;
  216 +}
  217 +.ui-datepicker .ui-datepicker-header {
  218 + position:relative;
  219 + padding:.35em 0;
  220 + border: none;
  221 + border-bottom: 1px solid #B6B6B6;
  222 + -moz-border-radius: 0;
  223 + -webkit-border-radius: 0;
  224 + border-radius: 0;
  225 + margin-bottom: 10px;
  226 + border: 1px solid #bbb;
  227 + -webkit-box-shadow: 0 0 0 3px #F1F1F1;
  228 + -moz-box-shadow: 0 0 0 3px #f1f1f1;
  229 + -ms-box-shadow: 0 0 0 3px #f1f1f1;
  230 + -o-box-shadow: 0 0 0 3px #f1f1f1;
  231 + box-shadow: 0 0 0 3px #F1F1F1;
  232 +}
  233 +
  234 +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 6px; width: 1.8em; height: 1.8em; }
  235 +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { border: 1px none; }
  236 +.ui-datepicker .ui-datepicker-prev { left:2px; }
  237 +.ui-datepicker .ui-datepicker-next { right:2px; }
  238 +.ui-datepicker .ui-datepicker-prev span { background-position: 0px -32px !important; }
  239 +.ui-datepicker .ui-datepicker-next span { background-position: -16px -32px !important; }
  240 +.ui-datepicker .ui-datepicker-prev-hover span { background-position: 0px -48px !important; }
  241 +.ui-datepicker .ui-datepicker-next-hover span { background-position: -16px -48px !important; }
  242 +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; background: url(icon_sprite.png) no-repeat; }
  243 +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; font-size: 12px; text-shadow: 0 1px 0 rgba(255,255,255,0.6); }
  244 +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
  245 +.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
  246 +.ui-datepicker select.ui-datepicker-month,
  247 +.ui-datepicker select.ui-datepicker-year { width: 49%;}
  248 +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
  249 +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
  250 +.ui-datepicker td { border: 0; padding: 1px; line-height: 24px; background-color: #FFF!important; }
  251 +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
  252 +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
  253 +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
  254 +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
  255 +.ui-datepicker table .ui-state-highlight { border-color: #ADE; }
  256 +.ui-datepicker-calendar .ui-state-default { background: transparent; border-color: #FFF; }
  257 +.ui-datepicker-calendar .ui-state-active { background: #D9EDF7; border-color: #ADE; color: #3A89A3; font-weight: bold; text-shadow: 0 1px 1px #fff; }
... ...
app/assets/stylesheets/main.scss
... ... @@ -1,204 +0,0 @@
1   -/** Override bootstrap variables **/
2   -$baseFontSize: 13px !default;
3   -$baseLineHeight: 18px !default;
4   -
5   -@import "bootstrap";
6   -@import "bootstrap-responsive";
7   -@import 'font-awesome';
8   -
9   -/** GitLab colors **/
10   -$link_color: #3A89A3;
11   -$blue_link: #2FA0BB;
12   -$style_color: #474D57;
13   -$hover: #D9EDF7;
14   -$hover_border: #ADF;
15   -
16   -/** GitLab Fonts **/
17   -@font-face { font-family: Korolev; src: font-url('korolev-medium-compressed.otf'); }
18   -$monospace: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
19   -
20   -/** MIXINS **/
21   -@mixin shade {
22   - -moz-box-shadow: 0 0 3px #ddd;
23   - -webkit-box-shadow: 0 0 3px #ddd;
24   - box-shadow: 0 0 3px #ddd;
25   -}
26   -
27   -@mixin solid_shade {
28   - -moz-box-shadow: 0 0 0 3px #f1f1f1;
29   - -webkit-box-shadow: 0 0 0 3px #f1f1f1;
30   - box-shadow: 0 0 0 3px #f1f1f1;
31   -}
32   -
33   -@mixin border-radius($radius) {
34   - -moz-border-radius: $radius;
35   - -webkit-border-radius: $radius;
36   - border-radius: $radius;
37   -}
38   -
39   -@mixin round-borders-bottom($radius) {
40   - border-top: 1px solid #eaeaea;
41   - -moz-border-radius-bottomright: $radius;
42   - -moz-border-radius-bottomleft: $radius;
43   - border-bottom-right-radius: $radius;
44   - border-bottom-left-radius: $radius;
45   - -webkit-border-bottom-left-radius: $radius;
46   - -webkit-border-bottom-right-radius: $radius;
47   -}
48   -
49   -@mixin round-borders-top($radius) {
50   - border-top: 1px solid #eaeaea;
51   - -moz-border-radius-topright: $radius;
52   - -moz-border-radius-topleft: $radius;
53   - border-top-right-radius: $radius;
54   - border-top-left-radius: $radius;
55   - -webkit-border-top-left-radius: $radius;
56   - -webkit-border-top-right-radius: $radius;
57   -}
58   -
59   -@mixin round-borders-all($radius) {
60   - border: 1px solid #eaeaea;
61   - -moz-border-radius: $radius;
62   - -webkit-border-radius: $radius;
63   - border-radius: $radius;
64   -}
65   -
66   -@mixin bg-gradient($from, $to) {
67   - background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
68   - background-image: -webkit-linear-gradient($from, $to);
69   - background-image: -moz-linear-gradient($from, $to);
70   - background-image: -o-linear-gradient($from, $to);
71   -}
72   -
73   -@mixin bg-light-gray-gradient {
74   - background:#f1f1f1;
75   - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
76   - background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
77   - background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
78   - background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
79   -}
80   -
81   -@mixin bg-gray-gradient {
82   - background:#eee;
83   - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
84   - background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
85   - background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
86   - background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
87   -}
88   -
89   -@mixin bg-dark-gray-gradient {
90   - background:#eee;
91   - background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
92   - background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
93   - background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
94   -}
95   -
96   -/**
97   - * Header of application.
98   - * Contain application logo, search panel, profile icon
99   - */
100   -@import "sections/header.scss";
101   -
102   -/**
103   - * Navigation menu of application.
104   - * Panel with links to pages depends on project, profile or admin area
105   - */
106   -@import "sections/nav.scss";
107   -
108   -/**
109   - * This file represent some UI that can be changed
110   - * during web app restyle or theme select.
111   - *
112   - * Next items should be placed there
113   - * - link, button colors
114   - * - header restyles
115   - * - main menu restyles
116   - *
117   - */
118   -@import "themes/ui_basic.scss";
119   -
120   -/**
121   - * UI themes:
122   - */
123   -@import "themes/ui_mars.scss";
124   -@import "themes/ui_modern.scss";
125   -@import "themes/ui_gray.scss";
126   -@import "themes/ui_color.scss";
127   -
128   -/**
129   - * GitLab bootstrap.
130   - * Overrides some styles of twitter bootstrap.
131   - * Also give some common classes for GitLab app
132   - */
133   -@import "gitlab_bootstrap/common.scss";
134   -@import "gitlab_bootstrap/typography.scss";
135   -@import "gitlab_bootstrap/buttons.scss";
136   -@import "gitlab_bootstrap/blocks.scss";
137   -@import "gitlab_bootstrap/files.scss";
138   -@import "gitlab_bootstrap/tables.scss";
139   -@import "gitlab_bootstrap/lists.scss";
140   -
141   -
142   -/**
143   - * Most of application styles placed here.
144   - * This file represent common UI that should not be changed between themes
145   - * or project restyling like form width or user avatar class or commit title
146   - *
147   - * TODO: clean it
148   - */
149   -@import "common.scss";
150   -
151   -/**
152   - * Styles related to specific part of app
153   - */
154   -@import "sections/commits.scss";
155   -@import "sections/issues.scss";
156   -@import "sections/projects.scss";
157   -@import "sections/merge_requests.scss";
158   -@import "sections/graph.scss";
159   -@import "sections/events.scss";
160   -@import "sections/themes.scss";
161   -
162   -/**
163   - * This scss file redefine chozen selectbox styles for
164   - * project Branch/Tag select element
165   - */
166   -@import "ref_select.scss";
167   -
168   -/**
169   - * Code (files list) styles. Browsing project files there
170   - */
171   -@import "sections/tree.scss";
172   -
173   -/**
174   - * This file represent notes(comments) styles
175   - */
176   -@import "sections/notes.scss";
177   -
178   -/**
179   - * This file represent profile styles
180   - */
181   -@import "sections/profile.scss";
182   -
183   -/**
184   - * Devise styles
185   - */
186   -@import "sections/login.scss";
187   -
188   -/**
189   - * CODE HIGHTLIGHT BASE
190   - *
191   - */
192   -@import "highlight/white.scss";
193   -
194   -/**
195   - * CODE HIGHTLIGHT DARK schema
196   - *
197   - */
198   -@import "highlight/dark.scss";
199   -
200   -/**
201   - * File Editor styles
202   - *
203   - */
204   -@import "sections/editor.scss";
app/assets/stylesheets/ref_select.scss
1 1 /** Branch/tag selector **/
2 2 .project-refs-form {
3   - margin:0;
  3 + margin: 0;
4 4 span {
5 5 background:none !important;
6 6 position:static !important;
... ... @@ -9,7 +9,7 @@
9 9 }
10 10 }
11 11 .project-refs-select {
12   - width:120px;
  12 + width: 120px;
13 13 }
14 14  
15 15 .project-refs-form .chzn-container {
... ... @@ -21,10 +21,10 @@
21 21 .chzn-drop {
22 22 min-width: 400px;
23 23 .chzn-results {
24   - max-height:300px;
  24 + max-height: 300px;
25 25 }
26 26 .chzn-search input {
27   - min-width:365px;
  27 + min-width: 365px;
28 28 }
29 29 }
30 30 }
... ... @@ -33,21 +33,19 @@
33 33 .chzn-container {
34 34 .chzn-search {
35 35 input:focus {
36   - -webkit-box-shadow: none;
37   - -moz-box-shadow: none;
38   - box-shadow: none;
  36 + @include box-shadow(none);
39 37 }
40 38 }
41 39  
42 40 .chzn-drop {
43   - margin:7px 0;
  41 + margin: 7px 0;
44 42 min-width: 200px;
45 43 border: 1px solid #bbb;
46   - border-radius:0;
  44 + @include border-radius(0);
47 45  
48 46 .chzn-results {
49 47 margin-top: 5px;
50   - max-height:300px;
  48 + max-height: 300px;
51 49  
52 50 .group-result {
53 51 color: $style_color;
... ... @@ -55,7 +53,7 @@
55 53 padding: 8px;
56 54 }
57 55 .active-result {
58   - border-radius: 0;
  56 + @include border-radius(0);
59 57  
60 58 &.highlighted {
61 59 background: $hover;
... ... @@ -71,7 +69,7 @@
71 69 .chzn-search {
72 70 @include bg-gray-gradient;
73 71 input {
74   - min-width:165px;
  72 + min-width: 165px;
75 73 border-color: #CCC;
76 74 }
77 75 }
... ... @@ -81,8 +79,8 @@
81 79 @include bg-light-gray-gradient;
82 80  
83 81 div {
84   - background:transparent;
85   - border-left:none;
  82 + background: transparent;
  83 + border-left: none;
86 84 }
87 85  
88 86 span {
... ...
app/assets/stylesheets/sections/commits.scss
... ... @@ -6,14 +6,14 @@
6 6  
7 7 .commit-title {
8 8 line-height: 26px;
9   - margin:0;
  9 + margin: 0;
10 10 }
11 11  
12 12 .commit-description {
13 13 font-size: 14px;
14 14 border: none;
15 15 background-color: white;
16   - padding-top:10px;
  16 + padding-top: 10px;
17 17 }
18 18  
19 19 .browse-button {
... ... @@ -28,9 +28,9 @@
28 28 @extend .clearfix;
29 29  
30 30 .sha-block {
31   - text-align:right;
  31 + text-align: right;
32 32 &:first-child {
33   - padding-bottom:6px;
  33 + padding-bottom: 6px;
34 34 }
35 35  
36 36 a {
... ... @@ -49,10 +49,10 @@
49 49  
50 50 .author a,
51 51 .committer a {
52   - font-size:14px;
53   - line-height:22px;
54   - text-shadow:0 1px 1px #fff;
55   - color:#777;
  52 + font-size: 14px;
  53 + line-height: 22px;
  54 + text-shadow: 0 1px 1px #fff;
  55 + color: #777;
56 56 &:hover {
57 57 color: #999;
58 58 }
... ... @@ -70,15 +70,16 @@
70 70 *
71 71 */
72 72 .diff_file {
73   - border:1px solid #CCC;
74   - margin-bottom:1em;
  73 + border: 1px solid #CCC;
  74 + margin-bottom: 1em;
75 75  
76 76 .diff_file_header {
77 77 @extend .clearfix;
78 78 padding: 5px 5px 5px 10px;
79 79 color: #555;
80   - border-bottom:1px solid #CCC;
  80 + border-bottom: 1px solid #CCC;
81 81 background: #eee;
  82 + // TODO Replace with linear-gradient mixin
82 83 background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
83 84 background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
84 85 background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
... ... @@ -86,7 +87,7 @@
86 87  
87 88 > span {
88 89 font-family: $monospace;
89   - font-size:14px;
  90 + font-size: 14px;
90 91 line-height: 30px;
91 92 }
92 93  
... ... @@ -104,36 +105,36 @@
104 105 }
105 106 }
106 107 .diff_file_content {
107   - overflow:auto;
108   - overflow-y:hidden;
109   - background:#fff;
110   - color:#333;
  108 + overflow: auto;
  109 + overflow-y: hidden;
  110 + background: #fff;
  111 + color: #333;
111 112 font-size: 12px;
112 113 font-family: $monospace;
113 114 .old{
114 115 span.idiff{
115   - background-color:#FAA;
  116 + background-color: #FAA;
116 117 }
117 118 }
118 119 .new{
119 120 span.idiff{
120   - background-color:#AFA;
  121 + background-color: #AFA;
121 122 }
122 123 }
123 124  
124 125 table {
125 126 td {
126   - line-height:18px;
  127 + line-height: 18px;
127 128 }
128 129 }
129 130 }
130 131 .diff_file_content_image {
131   - background:#eee;
132   - text-align:center;
  132 + background: #eee;
  133 + text-align: center;
133 134 .image {
134 135 display: inline-block;
135   - margin:50px;
136   - max-width:400px;
  136 + margin: 50px;
  137 + max-width: 400px;
137 138  
138 139 img{
139 140 background: url('trans_bg.gif');
... ... @@ -158,7 +159,7 @@
158 159  
159 160 &.img_compared {
160 161 .image {
161   - max-width:300px;
  162 + max-width: 300px;
162 163 }
163 164 }
164 165 }
... ... @@ -166,46 +167,46 @@
166 167  
167 168 .diff_file_content{
168 169 table {
169   - border:none;
170   - margin:0px;
171   - padding:0px;
  170 + border: none;
  171 + margin: 0px;
  172 + padding: 0px;
172 173 tr {
173 174 td {
174   - font-size:12px;
  175 + font-size: 12px;
175 176 }
176 177 }
177 178 }
178 179 .old_line, .new_line {
179   - margin:0px;
180   - padding:0px;
181   - border:none;
182   - background:#EEE;
183   - color:#666;
  180 + margin: 0px;
  181 + padding: 0px;
  182 + border: none;
  183 + background: #EEE;
  184 + color: #666;
184 185 padding: 0px 5px;
185 186 border-right: 1px solid #ccc;
186   - text-align:right;
187   - min-width:35px;
188   - max-width:35px;
189   - width:35px;
  187 + text-align: right;
  188 + min-width: 35px;
  189 + max-width: 35px;
  190 + width: 35px;
190 191 moz-user-select: none;
191 192 -khtml-user-select: none;
192 193 user-select: none;
193 194 a {
194   - float:left;
195   - width:35px;
196   - font-weight:normal;
197   - color:#666;
  195 + float: left;
  196 + width: 35px;
  197 + font-weight: normal;
  198 + color: #666;
198 199 &:hover {
199   - text-decoration:underline;
  200 + text-decoration: underline;
200 201 }
201 202 }
202 203 }
203 204 .line_content {
204   - white-space:pre;
205   - height:14px;
206   - margin:0px;
207   - padding:0px;
208   - border:none;
  205 + white-space: pre;
  206 + height: 14px;
  207 + margin: 0px;
  208 + padding: 0px;
  209 + border: none;
209 210 &.new {
210 211 background: #CFD;
211 212 }
... ... @@ -213,8 +214,8 @@
213 214 background: #FDD;
214 215 }
215 216 &.matched {
216   - color:#ccc;
217   - background:#fafafa;
  217 + color: #ccc;
  218 + background: #fafafa;
218 219 }
219 220 }
220 221 }
... ... @@ -228,32 +229,30 @@
228 229  
229 230 /** COMMIT ROW **/
230 231 .commit {
231   - @extend .wll;
232   -
233 232 .browse_code_link_holder {
234 233 @extend .span2;
235   - float:right;
  234 + float: right;
236 235 }
237 236  
238 237 .committed_ago {
239   - float:right;
  238 + float: right;
240 239 @extend .cgray;
241 240 }
242 241  
243 242 .notes_count {
244   - float:right;
  243 + float: right;
245 244 margin: -6px 8px 6px;
246 245 }
247 246  
248 247 code {
249   - background:#FCEEC1;
250   - color:$style_color;
  248 + background: #FCEEC1;
  249 + color: $style_color;
251 250 }
252 251  
253 252 .commit_short_id {
254   - float:left;
  253 + float: left;
255 254 @extend .lined;
256   - min-width:65px;
  255 + min-width: 65px;
257 256 font-family: $monospace;
258 257 }
259 258  
... ... @@ -294,11 +293,24 @@
294 293 }
295 294  
296 295 .label_commit {
297   - @include round-borders-all(4px);
298   - padding:2px 4px;
299   - border:none;
300   - font-size:13px;
  296 + @include border-radius(4px);
  297 + padding: 2px 4px;
  298 + font-size: 13px;
301 299 background: #474D57;
302   - color:#fff;
  300 + color: #fff;
303 301 font-family: $monospace;
304 302 }
  303 +
  304 +
  305 +.commits-compare-switch{
  306 + background: url("switch_icon.png") no-repeat center center;
  307 + width: 16px;
  308 + height: 18px;
  309 + text-indent: -9999px;
  310 + float: left;
  311 + margin-right: 9px;
  312 + border: 1px solid #DDD;
  313 + @include border-radius(4px);
  314 + padding: 4px;
  315 + background-color: #EEE;
  316 +}
... ...
app/assets/stylesheets/sections/editor.scss
1 1 .file-editor {
2 2 #editor{
3 3 border: none;
4   - border-radius: 0;
  4 + @include border-radius(0);
5 5 height: 500px;
6 6 margin: 0;
7 7 padding: 0;
... ...
app/assets/stylesheets/sections/events.scss
... ... @@ -4,25 +4,25 @@
4 4 */
5 5 .event_label {
6 6 &.pushed {
7   - padding:0 2px;
  7 + padding: 0 2px;
8 8 }
9 9  
10 10 &.opened {
11   - padding:0 2px;
  11 + padding: 0 2px;
12 12 }
13 13  
14 14 &.closed {
15   - padding:0 2px;
  15 + padding: 0 2px;
16 16 }
17 17  
18 18 &.merged {
19   - padding:0 2px;
  19 + padding: 0 2px;
20 20 }
21 21  
22 22 &.left,
23 23 &.joined {
24   - padding:0 2px;
25   - float:none;
  24 + padding: 0 2px;
  25 + float: none;
26 26 }
27 27 }
28 28  
... ... @@ -31,49 +31,51 @@
31 31 *
32 32 */
33 33 .event-item {
34   - min-height:40px;
35   - border-bottom:1px solid #eee;
  34 + border-bottom: 1px solid #eee;
36 35 .event-title {
37   - color:#333;
  36 + color: #333;
38 37 font-weight: bold;
39 38 .author_name {
40   - color:#333;
  39 + color: #333;
41 40 }
42 41 }
43 42 .event-body {
44 43 p {
45   - color:#555;
  44 + color: #555;
46 45 padding-top: 5px;
47 46 }
48 47 .event-info {
49   - color:#666;
  48 + color: #666;
50 49 }
51 50 }
52 51 .avatar {
53   - width:32px;
  52 + position: relative;
  53 + top: -3px;
54 54 }
55 55 .event_icon {
  56 + position: relative;
56 57 float: right;
57 58 border: 1px solid #EEE;
58 59 padding: 5px;
59 60 @include border-radius(5px);
60 61 background: #F9F9F9;
  62 + margin-left: 10px;
  63 + top: -6px;
61 64 img {
62   - width:20px;
  65 + width: 20px;
63 66 }
64 67 }
65 68 ul {
66   - margin-left:50px;
67   - margin-bottom:5px;
  69 + margin-left: 50px;
  70 + margin-bottom: 5px;
68 71 .avatar {
69   - width:18px;
70   - margin-top:3px;
  72 + width: 18px;
  73 + margin-top: 3px;
71 74 }
72 75 }
73 76  
74   - padding: 15px 5px;
  77 + padding: 16px 5px;
75 78 &:last-child { border:none }
76   - .wll:hover { background:none }
77 79  
78 80 .event_commits {
79 81 margin-top: 5px;
... ... @@ -81,9 +83,9 @@
81 83 li {
82 84 &.commit {
83 85 background: transparent;
84   - padding:3px;
85   - border:none;
86   - font-size:12px;
  86 + padding: 3px;
  87 + border: none;
  88 + font-size: 12px;
87 89 }
88 90 &.commits-stat {
89 91 display: block;
... ... @@ -98,15 +100,15 @@
98 100 *
99 101 */
100 102 .event_lp {
101   - color:#777;
102   - padding:10px;
103   - min-height:22px;
  103 + color: #777;
  104 + padding: 10px;
  105 + min-height: 22px;
104 106 border-left: 5px solid #5AB9C3;
105   - margin-bottom:20px;
106   - background:#f9f9f9;
  107 + margin-bottom: 20px;
  108 + background: #f9f9f9;
107 109  
108 110 .avatar {
109   - width:24px;
  111 + width: 24px;
110 112 }
111 113  
112 114 .btn-new-mr {
... ... @@ -133,7 +135,7 @@
133 135 background: #f9f9f9;
134 136 margin-bottom: 10px;
135 137 img {
136   - width:20px;
  138 + width: 20px;
137 139 }
138 140  
139 141 &.inactive {
... ...
app/assets/stylesheets/sections/graph.scss
1 1 .graph_holder {
2 2 border: 1px solid #aaa;
3   - padding:1px;
  3 + padding: 1px;
4 4  
5 5  
6 6 h4 {
7   - padding:0 10px;
  7 + padding: 0 10px;
8 8 border-bottom: 1px solid #bbb;
9 9 @include bg-gray-gradient;
10 10 }
... ...
app/assets/stylesheets/sections/header.scss
... ... @@ -5,7 +5,7 @@
5 5 header {
6 6 &.navbar-gitlab {
7 7 .navbar-inner {
8   - height:45px;
  8 + height: 45px;
9 9 padding: 5px;
10 10 background: #F1F1F1;
11 11  
... ... @@ -24,8 +24,8 @@ header {
24 24 }
25 25 }
26 26  
27   - z-index:10;
28   - /*height:60px;*/
  27 + z-index: 10;
  28 + /*height: 60px;*/
29 29  
30 30 /**
31 31 *
... ... @@ -33,25 +33,20 @@ header {
33 33 *
34 34 */
35 35 .app_logo {
36   - width:170px;
37   - float:left;
  36 + width: 170px;
  37 + float: left;
38 38 a {
39   - float:left;
  39 + float: left;
40 40 padding: 0px;
41 41  
42 42 h1 {
43   - width:90px;
  43 + width: 90px;
44 44 background: url('logo_dark.png') no-repeat 0px 2px;
45   - float:left;
46   - margin-left:2px;
47   - font-size:30px;
48   - line-height:48px;
49   - font-weight:normal;
50   - color:$style_color;
51   - text-shadow: 0 1px 1px #FFF;
52   - padding-left:45px;
53   - height:40px;
54   - font-family: 'Korolev', sans-serif;
  45 + float: left;
  46 + margin-left: 2px;
  47 + padding-left: 45px;
  48 + height: 40px;
  49 + @include header-font;
55 50 }
56 51 }
57 52 }
... ... @@ -62,16 +57,11 @@ header {
62 57 *
63 58 */
64 59 .project_name {
65   - position:relative;
66   - float:left;
67   - margin:0;
68   - margin-right:30px;
69   - font-size:30px;
70   - line-height:48px;
71   - font-weight:normal;
72   - color:$style_color;
73   - text-shadow: 0 1px 1px #FFF;
74   - font-family: 'Korolev', sans-serif;
  60 + position: relative;
  61 + float: left;
  62 + margin: 0;
  63 + margin-right: 30px;
  64 + @include header-font;
75 65 }
76 66  
77 67 /**
... ... @@ -81,7 +71,7 @@ header {
81 71 */
82 72 .search {
83 73 margin-right: 45px;
84   - margin-left:10px;
  74 + margin-left: 10px;
85 75 margin-top: 2px;
86 76  
87 77 .search-input {
... ... @@ -89,11 +79,11 @@ header {
89 79 background-image: url("icon-search.png");
90 80 background-repeat: no-repeat;
91 81 background-position: 10px;
92   - padding-left:25px;
  82 + padding-left: 25px;
93 83 font-size: 13px;
94 84 @include border-radius(3px);
95   - border:1px solid #c6c6c6;
96   - box-shadow:none;
  85 + border: 1px solid #c6c6c6;
  86 + box-shadow: none;
97 87 &:focus {
98 88 @extend .span3;
99 89 }
... ... @@ -122,7 +112,7 @@ header {
122 112 width: 28px;
123 113 height: 28px;
124 114 display: block;
125   - top:1px;
  115 + top: 1px;
126 116 &:after {
127 117 content: " ";
128 118 display: block;
... ... @@ -132,12 +122,15 @@ header {
132 122 left: 0;
133 123 bottom: 0;
134 124 float: right;
135   - border-radius: 5px;
  125 + @include border-radius(5px);
136 126 border: 1px solid rgba(255, 255, 255, 0.1);
137 127 border-bottom: 0;
138   - background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, 0.15)), to(rgba(0, 0, 0, 0.25))), -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(255, 255, 255, 0)), color-stop(0.5, rgba(255, 255, 255, 0.1)), color-stop(0.501, rgba(255, 255, 255, 0)), color-stop(1, rgba(255, 255, 255, 0)));
139   - background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)), -moz-linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
140   - background: linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)), linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
  128 + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, 0.15)), to(rgba(0, 0, 0, 0.25))),
  129 + -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(255, 255, 255, 0)), color-stop(0.5, rgba(255, 255, 255, 0.1)), color-stop(0.501, rgba(255, 255, 255, 0)), color-stop(1, rgba(255, 255, 255, 0)));
  130 + background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)),
  131 + -moz-linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
  132 + background: linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)),
  133 + linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
141 134 -webkit-background-origin: border-box;
142 135 -moz-background-origin: border;
143 136 background-origin: border-box; } } }
... ... @@ -149,7 +142,7 @@ header {
149 142 display: block; } }
150 143  
151 144 .account-links {
152   - border-radius: 5px;
  145 + @include border-radius(5px);
153 146 box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
154 147 position: relative;
155 148 &:before {
... ... @@ -169,7 +162,7 @@ header {
169 162 display: none;
170 163 z-index: 100000;
171 164 @include border-radius(4px);
172   - width: 100px;
  165 + width: 130px;
173 166 position: absolute;
174 167 right: 5px;
175 168 top: 38px;
... ... @@ -178,13 +171,13 @@ header {
178 171 box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
179 172 a {
180 173 color: #fff;
181   - padding: 7px 10px;
  174 + padding: 12px 15px;
182 175 display: block;
183 176 text-shadow: none;
184 177 border-bottom: 1px solid #666;
185 178 font-size: 12px;
186 179 &:hover {
187   - color:#fff;
  180 + color: #fff;
188 181 background: #333;
189 182 }
190 183 }
... ... @@ -197,20 +190,13 @@ header {
197 190  
198 191 .account-links a {
199 192 &:first-child {
200   - -webkit-border-top-left-radius: 5px;
201   - -webkit-border-top-right-radius: 5px;
202   - -moz-border-radius-topleft: 5px;
203   - -moz-border-radius-topright: 5px;
204   - border-top-left-radius: 5px;
205   - border-top-right-radius: 5px; }
  193 + @include border-radius(5px 5px 0 0);
  194 + }
206 195 &:last-child {
207   - -webkit-border-bottom-right-radius: 5px;
208   - -webkit-border-bottom-left-radius: 5px;
209   - -moz-border-radius-bottomright: 5px;
210   - -moz-border-radius-bottomleft: 5px;
211   - border-bottom-right-radius: 5px;
212   - border-bottom-left-radius: 5px;
213   - border-bottom: 0; } }
  196 + @include border-radius(0 0 5px 5px);
  197 + border-bottom: 0;
  198 + }
  199 + }
214 200  
215 201  
216 202  
... ... @@ -248,13 +234,13 @@ header {
248 234 a {
249 235 h1 {
250 236 background: url('logo_white.png') no-repeat 0px 2px;
251   - color:#fff;
  237 + color: #fff;
252 238 text-shadow: 0 1px 1px #111;
253 239 }
254 240 }
255 241 }
256 242 .project_name {
257   - color:#fff;
  243 + color: #fff;
258 244 text-shadow: 0 1px 1px #111;
259 245 }
260 246 }
... ...
app/assets/stylesheets/sections/issues.scss
... ... @@ -3,7 +3,7 @@
3 3 .issue_title {
4 4 @extend .top_box_content;
5 5 .clearfix {
6   - margin-bottom:0px;
  6 + margin-bottom: 0px;
7 7 input {
8 8 @extend .span8;
9 9 }
... ... @@ -11,14 +11,14 @@
11 11 }
12 12 .issue_middle_block {
13 13 @extend .middle_box_content;
14   - height:30px;
  14 + height: 30px;
15 15 .issue_assignee {
16 16 @extend .span6;
17   - float:left;
  17 + float: left;
18 18 }
19 19 .issue_milestone {
20 20 @extend .span4;
21   - float:left;
  21 + float: left;
22 22 }
23 23 }
24 24 .issue_description {
... ... @@ -28,31 +28,31 @@
28 28  
29 29 .issues_table {
30 30 .issue {
31   - padding:7px 10px;
  31 + padding: 7px 10px;
32 32  
33 33 .issue_check {
34   - float:left;
  34 + float: left;
35 35 padding: 8px 0;
36 36 padding-right: 8px;
37 37 min-width: 15px;
38 38 }
39 39  
40 40 p {
41   - padding-top:0;
42   - padding-bottom:2px;
  41 + padding-top: 0;
  42 + padding-bottom: 2px;
43 43 }
44 44  
45 45 img.avatar {
46   - width:32px;
47   - margin-top:1px;
  46 + width: 32px;
  47 + margin-top: 1px;
48 48 }
49 49 }
50 50 }
51 51  
52 52 input.check_all_issues {
53   - float:left;
  53 + float: left;
54 54 padding: 0;
55   - margin:0;
  55 + margin: 0;
56 56 margin-right: 10px;
57 57 position: relative;
58 58 top: 8px;
... ... @@ -82,16 +82,16 @@ input.check_all_issues {
82 82 }
83 83 }
84 84  
85   -@media (min-width: 800px) { .issues_filters select { width:160px; } }
86   -@media (min-width: 1000px) { .issues_filters select { width:200px; } }
87   -@media (min-width: 1200px) { .issues_filters select { width:220px; } }
  85 +@media (min-width: 800px) { .issues_filters select { width: 160px; } }
  86 +@media (min-width: 1000px) { .issues_filters select { width: 200px; } }
  87 +@media (min-width: 1200px) { .issues_filters select { width: 220px; } }
88 88  
89 89  
90 90 #issues-table-holder {
91 91 .issues_filters {
92 92 form {
93   - padding:0;
94   - margin:0;
  93 + padding: 0;
  94 + margin: 0;
95 95 margin-top:7px
96 96 }
97 97 }
... ... @@ -99,48 +99,25 @@ input.check_all_issues {
99 99 .issues_bulk_update {
100 100 margin: 0;
101 101 form {
102   - padding:0;
103   - margin:0;
  102 + padding: 0;
  103 + margin: 0;
104 104 margin-top:7px
105 105 }
106 106 .update_selected_issues {
107   - position:relative;
  107 + position: relative;
108 108 top:-2px;
109   - margin-left:4px;
110   - float:left;
  109 + margin-left: 4px;
  110 + float: left;
111 111 }
112 112  
113 113 .update_issues_text {
114   - padding:3px;
  114 + padding: 3px;
115 115 line-height: 18px;
116   - float:left;
  116 + float: left;
117 117 }
118 118 }
119 119 }
120 120  
121 121 #update_status {
122   - width:100px;
123   -}
124   -
125   -
126   -/**
127   - * Milestones list
128   - *
129   - */
130   -.milestone {
131   - @extend .wll;
132   -}
133   -
134   -/**
135   - * Fix milestone calendar
136   - */
137   -
138   -.ui-datepicker {
139   - border:none;
140   - box-shadow:none;
141   - .ui-datepicker-header {
142   - @include solid_shade;
143   - margin-bottom:10px;
144   - border:1px solid #bbb;
145   - }
  122 + width: 100px;
146 123 }
... ...
app/assets/stylesheets/sections/login.scss
1 1 /* Login Page */
2 2 body.login-page{
3 3 padding-top: 10%;
4   - background:#f1f1f1;
  4 + background: #f1f1f1;
5 5 }
6 6  
7 7 .login-box{
8 8 width: 304px;
9 9 position: relative;
10   - border-radius: 5px;
  10 + @include border-radius(5px);
11 11 margin: auto;
12 12 padding: 20px;
13 13 background: white;
... ... @@ -18,25 +18,15 @@ body.login-page{
18 18 display: block;
19 19 }
20 20  
21   -.login-box input.text{background-color: #f1f1f1; font-size: 16px; border-radius: 0; padding: 14px 10px; width: 280px}
  21 +.login-box input.text{background-color: #f1f1f1; font-size: 16px; @include border-radius(0); padding: 14px 10px; width: 280px}
22 22  
23 23 .login-box input.text.top{
24   - -webkit-border-top-left-radius: 5px;
25   - -webkit-border-top-right-radius: 5px;
26   - -moz-border-radius-topleft: 5px;
27   - -moz-border-radius-topright: 5px;
28   - border-top-left-radius: 5px;
29   - border-top-right-radius: 5px;
30   - margin-bottom:0px;
  24 + @include border-radius(5px 5px 0 0);
  25 + margin-bottom: 0px;
31 26 }
32 27  
33 28 .login-box input.text.bottom{
34   - -webkit-border-bottom-right-radius: 5px;
35   - -webkit-border-bottom-left-radius: 5px;
36   - -moz-border-radius-bottomright: 5px;
37   - -moz-border-radius-bottomleft: 5px;
38   - border-bottom-right-radius: 5px;
39   - border-bottom-left-radius: 5px;
  29 + @include border-radius(0 0 5px 5px);
40 30 border-top: 0;
41 31 margin-bottom: 20px;
42 32 }
... ...
app/assets/stylesheets/sections/merge_requests.scss
... ... @@ -5,10 +5,10 @@
5 5  
6 6 .mr_branch_box {
7 7 @extend .ui-box;
8   - margin-bottom:20px;
  8 + margin-bottom: 20px;
9 9  
10 10 .body {
11   - background:#f1f1f1;
  11 + background: #f1f1f1;
12 12 }
13 13  
14 14 }
... ... @@ -23,31 +23,30 @@
23 23 }
24 24  
25 25 form {
26   - margin-bottom:0;
  26 + margin-bottom: 0;
27 27 .clearfix {
28   - margin-bottom:0;
  28 + margin-bottom: 0;
29 29 }
30 30 }
31 31  
32 32 .accept_group {
33   - float:left;
  33 + float: left;
34 34 border: 1px solid #ADA;
35 35 padding: 2px;
36 36 @include border-radius(5px);
37   - border-radius: 5px;
38 37 background: #CEB;
39 38  
40 39 .accept_merge_request {
41   - font-size:13px;
42   - float:left;
  40 + font-size: 13px;
  41 + float: left;
43 42 }
44 43 .remove_branch_holder {
45   - margin-left:20px;
46   - margin-right:10px;
47   - float:left;
  44 + margin-left: 20px;
  45 + margin-right: 10px;
  46 + float: left;
48 47 }
49 48 label {
50   - color:#444;
  49 + color: #444;
51 50 }
52 51 }
53 52  
... ... @@ -60,15 +59,15 @@
60 59 .mr_nav_tabs {
61 60 li {
62 61 a {
63   - font-weight:bold;
64   - padding:8px 20px;
65   - text-align:center;
  62 + font-weight: bold;
  63 + padding: 8px 20px;
  64 + text-align: center;
66 65 }
67 66 }
68 67 }
69 68  
70 69 li.merge_request {
71   - padding:7px 10px;
  70 + padding: 7px 10px;
72 71 img.avatar {
73 72 width: 32px;
74 73 margin-top: 1px;
... ... @@ -85,35 +84,35 @@ li.merge_request {
85 84 }
86 85  
87 86 .label_branch {
88   - @include round-borders-all(4px);
89   - padding:2px 4px;
90   - border:none;
91   - font-size:14px;
  87 + @include border-radius(4px);
  88 + padding: 2px 4px;
  89 + border: none;
  90 + font-size: 14px;
92 91 background: #474D57;
93   - color:#fff;
  92 + color: #fff;
94 93 font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
95 94 }
96 95  
97 96 .mr_source_commit,
98 97 .mr_target_commit {
99 98 .commit {
100   - margin:0;
101   - padding:0;
  99 + margin: 0;
  100 + padding: 0;
102 101 padding: 5px;
103 102 margin-bottom: 5px;
104 103 .avatar { position:relative }
105 104 .row_title {
106   - color:#444;
  105 + color: #444;
107 106 }
108 107 .commit-author-name,
109 108 .dash,
110 109 .committed_ago,
111 110 .browse_code_link_holder {
112   - display:none;
  111 + display: none;
113 112 }
114   - list-style:none;
  113 + list-style: none;
115 114 &:hover {
116   - background:none;
  115 + background: none;
117 116 }
118 117 }
119 118 }
... ... @@ -126,20 +125,14 @@ li.merge_request {
126 125 @extend .main_box;
127 126 .merge_requests_middle_box {
128 127 @extend .middle_box_content;
129   - height:30px;
  128 + height: 30px;
130 129 .merge_requests_assignee {
131 130 @extend .span6;
132   - float:left;
  131 + float: left;
133 132 }
134 133 .merge_requests_milestone {
135 134 @extend .span4;
136   - float:left;
  135 + float: left;
137 136 }
138 137 }
139 138 }
140   -
141   -.status-badge {
142   - height: 32px;
143   - width: 100%;
144   - @include border-radius(5px);
145   -}
... ...
app/assets/stylesheets/sections/nav.scss
... ... @@ -3,64 +3,40 @@
3 3 *
4 4 */
5 5 ul.main_menu {
6   - border-radius: 4px;
7 6 margin: auto;
8   - margin:30px 0;
9   - border:1px solid #BBB;
10   - height:37px;
11   - @include bg-gray-gradient;
12   - position:relative;
13   - overflow:hidden;
14   - @include shade;
  7 + margin: 30px 0;
  8 + margin-top: 10px;
  9 + border-bottom: 1px solid #DDD;
  10 + height: 37px;
  11 + position: relative;
  12 + overflow: hidden;
15 13 .count {
16 14 position: relative;
17   - top: -1px;
18   - display: inline-block;
19   - height: 15px;
20   - margin: 0 0 0 5px;
21   - padding: 0 8px 1px 8px;
22   - height: auto;
23   - font-size: 0.82em;
24   - line-height: 14px;
25   - text-align: center;
26   - color: #777;
27   - background: #f2f2f2;
28   - border-top: 1px solid #CCC;
29   - border-radius: 8px;
30   - -moz-border-radius: 8px;
  15 + top: -1px;
  16 + display: inline-block;
  17 + height: 15px;
  18 + margin: 0 0 0 5px;
  19 + padding: 0 8px 1px 8px;
  20 + height: auto;
  21 + font-size: 0.82em;
  22 + line-height: 14px;
  23 + text-align: center;
  24 + color: #777;
31 25 }
32 26 .label {
33   - background:$hover;
34   - text-shadow:none;
35   - color:$style_color;
  27 + background: $hover;
  28 + text-shadow: none;
  29 + color: $style_color;
36 30 }
37 31 li {
38 32 list-style-type: none;
39 33 margin: 0;
40 34 display: table-cell;
41 35 width: 1%;
42   - border-right: 1px solid #DDD;
43   - border-left: 1px solid #EEE;
44   - border-bottom:2px solid #CFCFCF;
45   -
46   - &:first-child{
47   - -webkit-border-top-left-radius: 4px;
48   - -webkit-border-bottom-left-radius: 4px;
49   - -moz-border-radius-topleft: 4px;
50   - -moz-border-radius-bottomleft: 4px;
51   - border-top-left-radius: 4px;
52   - border-bottom-left-radius: 4px;
53   - border-left: 0;
54   - }
55   -
56 36 &.active {
57   - background-color:#D5D5D5;
58   - border-right: 1px solid #BBB;
59   - border-left: 1px solid #BBB;
60   - border-radius: 0 0 1px 1px;
61   - &:first-child{
62   - border-bottom:none;
63   - border-left:none;
  37 + border-bottom: 2px solid #474D57;
  38 + a {
  39 + color: $style_color;
64 40 }
65 41 }
66 42  
... ... @@ -68,10 +44,10 @@ ul.main_menu {
68 44 a {
69 45 background: url(home_icon.PNG) no-repeat center center;
70 46 text-indent:-9999px;
71   - min-width:20px;
  47 + min-width: 20px;
72 48 img {
73   - position:relative;
74   - top:4px;
  49 + position: relative;
  50 + top: 4px;
75 51 }
76 52 }
77 53 }
... ... @@ -79,12 +55,12 @@ ul.main_menu {
79 55 a {
80 56 display: block;
81 57 text-align: center;
82   - font-weight:bold;
83   - height:35px;
84   - line-height:36px;
85   - color: $style_color;
86   - text-shadow:0 1px 1px white;
87   - padding:0 10px;
  58 + font-weight: normal;
  59 + height: 35px;
  60 + line-height: 36px;
  61 + color: #777;
  62 + text-shadow: 0 1px 1px white;
  63 + padding: 0 10px;
88 64 }
89 65 }
90 66 /*
... ...
app/assets/stylesheets/sections/notes.scss
... ... @@ -4,30 +4,30 @@
4 4 */
5 5 #notes-list,
6 6 #new-notes-list {
7   - display:block;
8   - list-style:none;
9   - margin:0px;
10   - padding:0px;
  7 + display: block;
  8 + list-style: none;
  9 + margin: 0px;
  10 + padding: 0px;
11 11 }
12 12  
13 13 .issue_notes,
14 14 .wiki_notes {
15 15 .note_content {
16   - float:left;
17   - width:400px;
  16 + float: left;
  17 + width: 400px;
18 18 }
19 19 }
20 20  
21 21 /* Note textare */
22 22 #note_note {
23   - height:80px;
24   - width:99%;
25   - font-size:14px;
  23 + height: 80px;
  24 + width: 99%;
  25 + font-size: 14px;
26 26 }
27 27  
28 28 #new_note {
29 29 .attach_holder {
30   - display:none;
  30 + display: none;
31 31 }
32 32 }
33 33  
... ... @@ -36,34 +36,34 @@
36 36 border: 1px solid #ddd;
37 37 padding: 10px;
38 38 min-height: 60px;
39   - background:#f5f5f5;
  39 + background: #f5f5f5;
40 40 }
41 41  
42 42 .note {
43 43 padding: 8px 0;
44 44 overflow: hidden;
45 45 display: block;
46   - position:relative;
  46 + position: relative;
47 47 img {float: left; margin-right: 10px;}
48   - img.emoji {float:none;margin:0;}
  48 + img.emoji {float: none;margin: 0;}
49 49 .note-author cite{font-style: italic;}
50   - p { color:$style_color; }
  50 + p { color: $style_color; }
51 51 .note-author { color: $style_color;}
52 52  
53   - .note-title { margin-left:45px; padding-top: 5px;}
  53 + .note-title { margin-left: 45px; padding-top: 5px;}
54 54 .avatar {
55   - margin-top:3px;
  55 + margin-top: 3px;
56 56 }
57 57  
58 58 .delete-note {
59   - display:none;
60   - position:absolute;
61   - right:0;
62   - top:0;
  59 + display: none;
  60 + position: absolute;
  61 + right: 0;
  62 + top: 0;
63 63 }
64 64  
65 65 &:hover {
66   - .delete-note { display:block; }
  66 + .delete-note { display: block; }
67 67 }
68 68 }
69 69 #notes-list:not(.reversed) .note,
... ... @@ -94,30 +94,31 @@ p.notify_controls span{
94 94 }
95 95  
96 96 tr.line_notes_row {
97   - border-bottom:1px solid #DDD;
  97 + border-bottom: 1px solid #DDD;
98 98 border-left: 7px solid #2A79A3;
99 99  
100 100 &.reply {
101   - background:#eee;
  101 + background: #eee;
102 102 border-left: 7px solid #2A79A3;
103   - border-top:1px solid #ddd;
  103 + border-top: 1px solid #ddd;
104 104 td {
105   - padding:7px 10px;
  105 + padding: 7px 10px;
106 106 }
107 107 a.line_note_reply_link {
108   - @include round-borders-all(4px);
  108 + border: 1px solid #eaeaea;
  109 + @include border-radius(4px);
109 110 padding: 3px 10px;
110   - margin-left:5px;
  111 + margin-left: 5px;
111 112 color: white;
112 113 background: #2A79A3;
113 114 border-color: #2A79A3;
114 115 }
115 116 }
116 117 ul {
117   - margin:0;
  118 + margin: 0;
118 119 li {
119   - padding:0;
120   - border:none;
  120 + padding: 0;
  121 + border: none;
121 122 }
122 123 }
123 124 }
... ... @@ -125,28 +126,28 @@ tr.line_notes_row {
125 126 .line_notes_row, .per_line_form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
126 127  
127 128 .per_line_form {
128   - background:#f5f5f5;
129   - border-top:1px solid #eee;
  129 + background: #f5f5f5;
  130 + border-top: 1px solid #eee;
130 131 form { margin: 0; }
131 132 td {
132   - border-bottom:1px solid #ddd;
  133 + border-bottom: 1px solid #ddd;
133 134 }
134 135 .note_actions {
135   - margin:0;
  136 + margin: 0;
136 137 padding-top: 10px;
137 138  
138 139 .buttons {
139   - float:left;
140   - width:300px;
  140 + float: left;
  141 + width: 300px;
141 142 }
142 143 .options {
143 144 .labels {
144   - float:left;
145   - padding-left:10px;
  145 + float: left;
  146 + padding-left: 10px;
146 147 label {
147 148 padding: 6px 0;
148 149 margin: 0;
149   - width:120px;
  150 + width: 120px;
150 151 }
151 152 }
152 153 }
... ... @@ -154,13 +155,13 @@ tr.line_notes_row {
154 155 }
155 156  
156 157 td .line_note_link {
157   - position:absolute;
  158 + position: absolute;
158 159 margin-left:-70px;
159 160 margin-top:-10px;
160   - z-index:10;
  161 + z-index: 10;
161 162 background: url("comment_add.png") no-repeat left 0;
162   - width:32px;
163   - height:32px;
  163 + width: 32px;
  164 + height: 32px;
164 165  
165 166 opacity: 0.0;
166 167 filter: alpha(opacity=0);
... ... @@ -180,13 +181,13 @@ td .line_note_link {
180 181 .new_note {
181 182 .input-file {
182 183 font: 500px monospace;
183   - opacity:0;
  184 + opacity: 0;
184 185 filter: alpha(opacity=0);
185 186 position: absolute;
186 187 z-index: 1;
187   - top:0;
188   - right:0;
189   - padding:0;
  188 + top: 0;
  189 + right: 0;
  190 + padding: 0;
190 191 margin: 0;
191 192 }
192 193  
... ... @@ -198,24 +199,24 @@ td .line_note_link {
198 199 }
199 200  
200 201 .attachments {
201   - position:relative;
  202 + position: relative;
202 203 width: 350px;
203 204 height: 50px;
204   - overflow:hidden;
  205 + overflow: hidden;
205 206 margin:0 0 5px !important;
206 207  
207 208 .input_file {
208 209 .file_upload {
209 210 position: absolute;
210   - right:14px;
211   - top:7px;
  211 + right: 14px;
  212 + top: 7px;
212 213 }
213 214  
214 215 .file_name {
215   - line-height:30px;
216   - width:240px;
217   - height:28px;
218   - overflow:hidden;
  216 + line-height: 30px;
  217 + width: 240px;
  218 + height: 28px;
  219 + overflow: hidden;
219 220 }
220 221 .input-file {
221 222 width: 260px;
... ... @@ -228,5 +229,5 @@ td .line_note_link {
228 229  
229 230 .note-text {
230 231 border: 1px solid #aaa;
231   - box-shadow:none;
  232 + box-shadow: none;
232 233 }
... ...
app/assets/stylesheets/sections/profile.scss
1 1 .profile_history {
2 2 .event_feed {
3   - min-height:20px;
  3 + min-height: 20px;
4 4 .avatar {
5   - width:20px;
  5 + width: 20px;
6 6 }
7 7 }
8 8 }
9 9  
10 10 .profile_avatar_holder {
11   - float:left;
12   - width:60px;
13   - height:60px;
14   - margin-right:20px;
  11 + float: left;
  12 + width: 60px;
  13 + height: 60px;
  14 + margin-right: 20px;
15 15 img {
16   - width:60px;
17   - height:60px;
18   - background:#fff;
  16 + width: 60px;
  17 + height: 60px;
  18 + background: #fff;
19 19 padding: 1px;
20 20 border: 1px solid #ddd;
21 21 }
... ...
app/assets/stylesheets/sections/projects.scss
... ... @@ -4,50 +4,34 @@
4 4 }
5 5  
6 6 .side {
7   - @extend .span4;
8 7 @extend .right;
9 8  
10 9 .groups_box,
11 10 .projects_box {
12   - h5 {
13   - color:$style_color;
14   - font-size:16px;
  11 + > h5 {
  12 + color: $style_color;
  13 + font-size: 16px;
15 14 text-shadow: 0 1px 1px #fff;
16 15 padding: 2px 10px;
17   - line-height:32px;
18   - font-size:14px;
  16 + line-height: 32px;
  17 + font-size: 14px;
19 18 }
20   - ul {
21   - li {
22   - padding:0;
23   - a {
24   - display:block;
25   - .group_name {
26   - font-size:14px;
27   - line-height:18px;
28   - }
29   - .project_name {
30   - color:#4fa2bd;
31   - font-size:14px;
32   - line-height:18px;
33   - }
34   - .arrow {
35   - float:right;
36   - padding:10px;
37   - margin:0;
38   - }
39   - .last_activity {
40   - padding-top:5px;
41   - display:block;
42   - span, strong {
43   - font-size:12px;
44   - color:#666;
45   - }
46   - }
  19 + .nav-projects-tabs li { padding: 0; }
  20 + .well-list {
  21 + .arrow {
  22 + float: right;
  23 + padding: 10px;
  24 + margin: 0;
  25 + }
  26 + .last_activity {
  27 + padding-top: 5px;
  28 + display: block;
  29 + span, strong {
  30 + font-size: 12px;
  31 + color: #666;
47 32 }
48 33 }
49 34 }
50   - @extend .leftbar;
51 35 @extend .ui-box;
52 36 }
53 37 }
... ... @@ -58,21 +42,27 @@
58 42 .project_name_holder {
59 43 input,
60 44 label {
61   - font-size:16px;
62   - line-height:20px;
63   - padding:8px;
  45 + font-size: 16px;
  46 + line-height: 20px;
  47 + padding: 8px;
64 48 }
65 49 label {
66   - color:#888;
  50 + color: #888;
67 51 }
68 52 .btn {
69   - padding:6px 10px;
70   - margin-left:10px;
71   - margin-bottom:8px;
  53 + padding: 6px 10px;
  54 + margin-left: 10px;
  55 + margin-bottom: 8px;
72 56 }
73 57 }
74 58 .adv_settings {
75   - h6 { margin-left:40px; }
  59 + h6 { margin-left: 40px; }
  60 + }
  61 +
  62 + fieldset.features {
  63 + .control-label {
  64 + font-weight: bold;
  65 + }
76 66 }
77 67 }
78 68  
... ... @@ -81,19 +71,20 @@
81 71 @include bg-gray-gradient;
82 72 padding: 4px 7px;
83 73 border: 1px solid #CCC;
84   - margin-bottom:20px;
  74 + margin-bottom: 20px;
85 75 }
86 76  
87 77 .project_clone_holder {
88 78 input[type="text"],
89 79 .btn {
90   - font-size:12px;
  80 + font-size: 12px;
91 81 line-height: 18px;
92 82 margin: 0;
93 83 padding: 3px 10px;
94 84 }
95 85  
96 86 input[type="text"] {
  87 + @extend .monospace;
97 88 border: 1px solid #BBB;
98 89 box-shadow: none;
99 90 margin-left: -1px;
... ... @@ -102,11 +93,33 @@
102 93  
103 94 .save-project-loader {
104 95 img {
105   - margin-top:50px;
106   - margin-bottom:50px;
  96 + margin-top: 50px;
  97 + margin-bottom: 50px;
107 98 }
108 99 h3 {
109 100 @extend .page_title;
110 101 }
111 102  
112 103 }
  104 +
  105 +ul.nav.nav-projects-tabs {
  106 + @extend .nav-tabs;
  107 +
  108 + padding-left: 8px;
  109 +
  110 + li {
  111 + a {
  112 + padding: 4px 20px;
  113 + margin-top: 2px;
  114 + border-color: #DDD;
  115 + background-color: #EEE;
  116 + text-shadow: 0 1px 1px white;
  117 + color: #555;
  118 + }
  119 + &.active {
  120 + a {
  121 + font-weight: bold;
  122 + }
  123 + }
  124 + }
  125 +}
... ...
app/assets/stylesheets/sections/snippets.scss 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +.snippet.file_holder {
  2 + .file_title {
  3 + .snippet-file-name {
  4 + position: relative;
  5 + top: -4px;
  6 + left: -4px;
  7 + }
  8 + }
  9 +}
... ...
app/assets/stylesheets/sections/themes.scss
... ... @@ -6,17 +6,17 @@
6 6 }
7 7  
8 8 .themes_opts {
9   - padding-left:20px;
  9 + padding-left: 20px;
10 10  
11 11 label {
12   - width:175px;
13   - margin-right:40px;
  12 + width: 175px;
  13 + margin-right: 40px;
14 14  
15 15 .prev {
16 16 @extend .thumbnail;
17   - height:30px;
18   - width:175px;
19   - margin-bottom:10px;
  17 + height: 30px;
  18 + width: 175px;
  19 + margin-bottom: 10px;
20 20  
21 21 &.classic {
22 22 background: #31363e;
... ... @@ -42,17 +42,17 @@
42 42 }
43 43  
44 44 .code_highlight_opts {
45   - padding-left:20px;
  45 + padding-left: 20px;
46 46  
47 47 label {
48   - width:220px;
49   - margin-right:40px;
  48 + width: 220px;
  49 + margin-right: 40px;
50 50  
51 51 .prev {
52 52 @extend .thumbnail;
53   - height:151px;
54   - width:220px;
55   - margin-bottom:10px;
  53 + height: 151px;
  54 + width: 220px;
  55 + margin-bottom: 10px;
56 56 }
57 57 }
58 58 }
... ...
app/assets/stylesheets/sections/tree.scss
1 1 .tree-holder {
2 2 .tree-content-holder {
3   - float:left;
4   - width:100%;
  3 + float: left;
  4 + width: 100%;
5 5 }
6 6  
7 7 .tree_progress {
8   - display:none;
9   - margin:20px;
  8 + display: none;
  9 + margin: 20px;
10 10 &.loading {
11   - display:block;
  11 + display: block;
12 12 }
13 13 }
14 14  
... ... @@ -18,20 +18,20 @@
18 18 &:hover {
19 19 td {
20 20 background: $hover;
21   - border-top:1px solid #ADF;
22   - border-bottom:1px solid #ADF;
  21 + border-top: 1px solid #ADF;
  22 + border-bottom: 1px solid #ADF;
23 23 }
24   - cursor:pointer;
  24 + cursor: pointer;
25 25 }
26 26 }
27 27 }
28 28  
29 29 .tree-item {
30 30 .tree-item-file-name {
31   - vertical-align:middle;
  31 + vertical-align: middle;
32 32 a {
33 33 &:hover {
34   - color:$blue_link;
  34 + color: $primary_color;
35 35 }
36 36 }
37 37  
... ... @@ -48,8 +48,8 @@
48 48 padding: 2px 10px;
49 49 }
50 50 td {
51   - line-height:20px;
52   - background:#fafafa;
  51 + line-height: 20px;
  52 + background: #fafafa;
53 53 }
54 54 }
55 55  
... ... @@ -86,7 +86,7 @@
86 86 .tree-btn-group {
87 87 .btn {
88 88 margin-right:-3px;
89   - padding:2px 10px;
  89 + padding: 2px 10px;
90 90 }
91 91 }
92 92  
... ...
app/assets/stylesheets/sections/votes.scss 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +.votes {
  2 + font-size: 13px;
  3 + line-height: 15px;
  4 + .progress {
  5 + height: 4px;
  6 + margin: 0;
  7 + .bar {
  8 + float: left;
  9 + height: 100%;
  10 + }
  11 + .bar-success {
  12 + @include linear-gradient(#62C462, #51A351);
  13 + background-color: #468847;
  14 + }
  15 + .bar-danger {
  16 + @include linear-gradient(#EE5F5B, #BD362F);
  17 + background-color: #B94A48;
  18 + }
  19 + }
  20 + .upvotes {
  21 + display: inline-block;
  22 + color: #468847;
  23 + }
  24 + .downvotes {
  25 + display: inline-block;
  26 + color: #B94A48;
  27 + }
  28 +}
  29 +.votes-block {
  30 + margin: 14px 6px 6px 0;
  31 + .downvotes {
  32 + float: right;
  33 + }
  34 +}
  35 +.votes-inline {
  36 + display: inline-block;
  37 + margin: 0 8px;
  38 + .progress {
  39 + display: inline-block;
  40 + padding: 0 0 2px;
  41 + width: 45px;
  42 + }
  43 +}
... ...
app/assets/stylesheets/themes/ui_basic.scss
... ... @@ -4,18 +4,6 @@
4 4 *
5 5 */
6 6 .ui_basic {
7   - /*
8   - * Common styles
9   - *
10   - */
11   - a {
12   - color: $link_color;
13   - &:hover {
14   - text-decoration:none;
15   - color: $blue_link;
16   - }
17   - }
18   -
19 7 .app_logo {
20 8 .separator {
21 9 margin-left: 0;
... ...
app/assets/stylesheets/themes/ui_mars.scss
... ... @@ -47,17 +47,17 @@
47 47 a {
48 48 h1 {
49 49 background: url('logo_white.png') no-repeat 0px 2px;
50   - color:#eee;
  50 + color: #eee;
51 51 text-shadow: 0 1px 1px #111;
52 52 }
53 53 }
54 54 .separator {
55   - display:none;
  55 + display: none;
56 56 }
57 57  
58 58 }
59 59 .project_name {
60   - color:#eee;
  60 + color: #eee;
61 61 text-shadow: 0 1px 1px #111;
62 62 }
63 63 }
... ...
app/contexts/notes/load_context.rb
... ... @@ -19,8 +19,6 @@ module Notes
19 19 when "wall"
20 20 # this is the only case, where the order is DESC
21 21 project.common_notes.order("created_at DESC, id DESC").limit(50)
22   - when "wiki"
23   - project.wiki_notes.limit(20)
24 22 end
25 23  
26 24 @notes = if after_id
... ...
app/contexts/project_update_context.rb 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +class ProjectUpdateContext < BaseContext
  2 + def execute(role = :default)
  3 + namespace_id = params[:project].delete(:namespace_id)
  4 +
  5 + allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin
  6 +
  7 + if allowed_transfer && namespace_id.present?
  8 + if namespace_id == Namespace.global_id
  9 + if project.namespace.present?
  10 + # Transfer to global namespace from anyone
  11 + project.transfer(nil)
  12 + end
  13 + elsif namespace_id.to_i != project.namespace_id
  14 + # Transfer to someone namespace
  15 + namespace = Namespace.find(namespace_id)
  16 + project.transfer(namespace)
  17 + end
  18 + end
  19 +
  20 + project.update_attributes(params[:project], as: role)
  21 + end
  22 +end
  23 +
... ...
app/controllers/admin/groups_controller.rb
... ... @@ -2,7 +2,7 @@ class Admin::GroupsController &lt; AdminController
2 2 before_filter :group, only: [:edit, :show, :update, :destroy, :project_update]
3 3  
4 4 def index
5   - @groups = Group.scoped
  5 + @groups = Group.order('name ASC')
6 6 @groups = @groups.search(params[:name]) if params[:name].present?
7 7 @groups = @groups.page(params[:page]).per(20)
8 8 end
... ... @@ -11,6 +11,7 @@ class Admin::GroupsController &lt; AdminController
11 11 @projects = Project.scoped
12 12 @projects = @projects.not_in_group(@group) if @group.projects.present?
13 13 @projects = @projects.all
  14 + @projects.reject!(&:empty_repo?)
14 15 end
15 16  
16 17 def new
... ... @@ -22,6 +23,7 @@ class Admin::GroupsController &lt; AdminController
22 23  
23 24 def create
24 25 @group = Group.new(params[:group])
  26 + @group.path = @group.name.dup.parameterize if @group.name
25 27 @group.owner = current_user
26 28  
27 29 if @group.save
... ... @@ -48,15 +50,17 @@ class Admin::GroupsController &lt; AdminController
48 50  
49 51 def project_update
50 52 project_ids = params[:project_ids]
51   - Project.where(id: project_ids).update_all(group_id: @group.id)
  53 +
  54 + Project.where(id: project_ids).each do |project|
  55 + project.transfer(@group)
  56 + end
52 57  
53 58 redirect_to :back, notice: 'Group was successfully updated.'
54 59 end
55 60  
56 61 def remove_project
57 62 @project = Project.find(params[:project_id])
58   - @project.group_id = nil
59   - @project.save
  63 + @project.transfer(nil)
60 64  
61 65 redirect_to :back, notice: 'Group was successfully updated.'
62 66 end
... ... @@ -70,6 +74,6 @@ class Admin::GroupsController &lt; AdminController
70 74 private
71 75  
72 76 def group
73   - @group = Group.find_by_code(params[:id])
  77 + @group = Group.find_by_path(params[:id])
74 78 end
75 79 end
... ...
app/controllers/admin/projects_controller.rb
1 1 class Admin::ProjectsController < AdminController
2   - before_filter :admin_project, only: [:edit, :show, :update, :destroy, :team_update]
  2 + before_filter :project, only: [:edit, :show, :update, :destroy, :team_update]
3 3  
4 4 def index
5   - @admin_projects = Project.scoped
6   - @admin_projects = @admin_projects.search(params[:name]) if params[:name].present?
7   - @admin_projects = @admin_projects.order("name ASC").page(params[:page]).per(20)
  5 + @projects = Project.scoped
  6 + @projects = @projects.where(namespace_id: params[:namespace_id]) if params[:namespace_id].present?
  7 + @projects = @projects.where(namespace_id: nil) if params[:namespace_id] == Namespace.global_id
  8 + @projects = @projects.search(params[:name]) if params[:name].present?
  9 + @projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
8 10 end
9 11  
10 12 def show
11   - @users = User.scoped
12   - @users = @users.not_in_project(@admin_project) if @admin_project.users.present?
  13 + @users = User.active
  14 + @users = @users.not_in_project(@project) if @project.users.present?
13 15 @users = @users.all
14 16 end
15 17  
16   - def new
17   - @admin_project = Project.new
18   - end
19   -
20 18 def edit
21 19 end
22 20  
23 21 def team_update
24   - @admin_project.add_users_ids_to_team(params[:user_ids], params[:project_access])
25   -
26   - redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.'
27   - end
28   -
29   - def create
30   - @admin_project = Project.new(params[:project])
31   - @admin_project.owner = current_user
  22 + @project.add_users_ids_to_team(params[:user_ids], params[:project_access])
32 23  
33   - if @admin_project.save
34   - redirect_to [:admin, @admin_project], notice: 'Project was successfully created.'
35   - else
36   - render action: "new"
37   - end
  24 + redirect_to [:admin, @project], notice: 'Project was successfully updated.'
38 25 end
39 26  
40 27 def update
41   - owner_id = params[:project].delete(:owner_id)
  28 + status = ProjectUpdateContext.new(project, current_user, params).execute(:admin)
42 29  
43   - if owner_id
44   - @admin_project.owner = User.find(owner_id)
45   - end
46   -
47   - if @admin_project.update_attributes(params[:project])
48   - redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.'
  30 + if status
  31 + redirect_to [:admin, @project], notice: 'Project was successfully updated.'
49 32 else
50 33 render action: "edit"
51 34 end
52 35 end
53 36  
54 37 def destroy
55   - @admin_project.destroy
  38 + @project.destroy
56 39  
57   - redirect_to admin_projects_url, notice: 'Project was successfully deleted.'
  40 + redirect_to admin_projects_path, notice: 'Project was successfully deleted.'
58 41 end
59 42  
60   - private
  43 + protected
  44 +
  45 + def project
  46 + id = params[:project_id] || params[:id]
61 47  
62   - def admin_project
63   - @admin_project = Project.find_by_code(params[:id])
  48 + @project = Project.find_with_namespace(id)
  49 + @project || render_404
64 50 end
65 51 end
... ...
app/controllers/admin/users_controller.rb
... ... @@ -3,7 +3,7 @@ class Admin::UsersController &lt; AdminController
3 3 @admin_users = User.scoped
4 4 @admin_users = @admin_users.filter(params[:filter])
5 5 @admin_users = @admin_users.search(params[:name]) if params[:name].present?
6   - @admin_users = @admin_users.order("updated_at DESC").page(params[:page])
  6 + @admin_users = @admin_users.order("name ASC").page(params[:page])
7 7 end
8 8  
9 9 def show
... ... @@ -30,7 +30,7 @@ class Admin::UsersController &lt; AdminController
30 30  
31 31  
32 32 def new
33   - @admin_user = User.new({ projects_limit: Gitlab.config.default_projects_limit }, as: :admin)
  33 + @admin_user = User.new({ projects_limit: Gitlab.config.gitlab.default_projects_limit }, as: :admin)
34 34 end
35 35  
36 36 def edit
... ...
app/controllers/application_controller.rb
... ... @@ -2,6 +2,7 @@ class ApplicationController &lt; ActionController::Base
2 2 before_filter :authenticate_user!
3 3 before_filter :reject_blocked!
4 4 before_filter :set_current_user_for_observers
  5 + before_filter :add_abilities
5 6 before_filter :dev_tools if Rails.env == 'development'
6 7  
7 8 protect_from_forgery
... ... @@ -34,7 +35,7 @@ class ApplicationController &lt; ActionController::Base
34 35 def reject_blocked!
35 36 if current_user && current_user.blocked
36 37 sign_out current_user
37   - flash[:alert] = "Your account was blocked"
  38 + flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
38 39 redirect_to new_user_session_path
39 40 end
40 41 end
... ... @@ -42,7 +43,7 @@ class ApplicationController &lt; ActionController::Base
42 43 def after_sign_in_path_for resource
43 44 if resource.is_a?(User) && resource.respond_to?(:blocked) && resource.blocked
44 45 sign_out resource
45   - flash[:alert] = "Your account was blocked"
  46 + flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
46 47 new_user_session_path
47 48 else
48 49 super
... ... @@ -63,11 +64,19 @@ class ApplicationController &lt; ActionController::Base
63 64 end
64 65  
65 66 def project
66   - @project ||= current_user.projects.find_by_code(params[:project_id] || params[:id])
67   - @project || render_404
  67 + id = params[:project_id] || params[:id]
  68 +
  69 + @project = Project.find_with_namespace(id)
  70 +
  71 + if @project and can?(current_user, :read_project, @project)
  72 + @project
  73 + else
  74 + @project = nil
  75 + render_404
  76 + end
68 77 end
69 78  
70   - def add_project_abilities
  79 + def add_abilities
71 80 abilities << Ability
72 81 end
73 82  
... ... @@ -103,6 +112,10 @@ class ApplicationController &lt; ActionController::Base
103 112 render file: Rails.root.join("public", "404"), layout: false, status: "404"
104 113 end
105 114  
  115 + def render_403
  116 + render file: Rails.root.join("public", "403"), layout: false, status: "403"
  117 + end
  118 +
106 119 def require_non_empty_project
107 120 redirect_to @project if @project.empty_repo?
108 121 end
... ...
app/controllers/commit_controller.rb
... ... @@ -26,7 +26,8 @@ class CommitController &lt; ProjectResourceController
26 26 end
27 27 end
28 28  
29   - format.patch
  29 + format.diff { render text: @commit.to_diff }
  30 + format.patch { render text: @commit.to_patch }
30 31 end
31 32 end
32 33 end
... ...
app/controllers/dashboard_controller.rb
1 1 class DashboardController < ApplicationController
2 2 respond_to :html
3 3  
  4 + before_filter :projects
4 5 before_filter :event_filter, only: :index
5 6  
6 7 def index
7   - @groups = Group.where(id: current_user.projects.pluck(:group_id))
8   - @projects = current_user.projects_sorted_by_activity
  8 + @groups = current_user.authorized_groups
  9 +
  10 + @has_authorized_projects = @projects.count > 0
  11 +
  12 + @projects = case params[:scope]
  13 + when 'personal' then
  14 + @projects.personal(current_user)
  15 + when 'joined' then
  16 + @projects.joined(current_user)
  17 + else
  18 + @projects
  19 + end
  20 +
9 21 @projects = @projects.page(params[:page]).per(30)
10 22  
11 23 @events = Event.in_projects(current_user.project_ids)
... ... @@ -23,15 +35,16 @@ class DashboardController &lt; ApplicationController
23 35  
24 36 # Get authored or assigned open merge requests
25 37 def merge_requests
26   - @projects = current_user.projects.all
27   - @merge_requests = current_user.cared_merge_requests.recent.page(params[:page]).per(20)
  38 + @merge_requests = current_user.cared_merge_requests
  39 + @merge_requests = dashboard_filter(@merge_requests)
  40 + @merge_requests = @merge_requests.recent.page(params[:page]).per(20)
28 41 end
29 42  
30 43 # Get only assigned issues
31 44 def issues
32   - @projects = current_user.projects.all
33   - @user = current_user
34   - @issues = current_user.assigned_issues.opened.recent.page(params[:page]).per(20)
  45 + @issues = current_user.assigned_issues
  46 + @issues = dashboard_filter(@issues)
  47 + @issues = @issues.recent.page(params[:page]).per(20)
35 48 @issues = @issues.includes(:author, :project)
36 49  
37 50 respond_to do |format|
... ... @@ -40,7 +53,32 @@ class DashboardController &lt; ApplicationController
40 53 end
41 54 end
42 55  
  56 + protected
  57 +
  58 + def projects
  59 + @projects = current_user.authorized_projects.sorted_by_activity
  60 + end
  61 +
43 62 def event_filter
44 63 @event_filter ||= EventFilter.new(params[:event_filter])
45 64 end
  65 +
  66 + def dashboard_filter items
  67 + if params[:project_id]
  68 + items = items.where(project_id: params[:project_id])
  69 + end
  70 +
  71 + if params[:search].present?
  72 + items = items.search(params[:search])
  73 + end
  74 +
  75 + case params[:status]
  76 + when 'closed'
  77 + items.closed
  78 + when 'all'
  79 + items
  80 + else
  81 + items.opened
  82 + end
  83 + end
46 84 end
... ...
app/controllers/groups_controller.rb
... ... @@ -5,6 +5,9 @@ class GroupsController &lt; ApplicationController
5 5 before_filter :group
6 6 before_filter :projects
7 7  
  8 + # Authorize
  9 + before_filter :authorize_read_group!
  10 +
8 11 def show
9 12 @events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0)
10 13 @last_push = current_user.recent_push
... ... @@ -18,7 +21,7 @@ class GroupsController &lt; ApplicationController
18 21  
19 22 # Get authored or assigned open merge requests
20 23 def merge_requests
21   - @merge_requests = current_user.cared_merge_requests
  24 + @merge_requests = current_user.cared_merge_requests.opened
22 25 @merge_requests = @merge_requests.of_group(@group).recent.page(params[:page]).per(20)
23 26 end
24 27  
... ... @@ -44,20 +47,33 @@ class GroupsController &lt; ApplicationController
44 47 end
45 48  
46 49 def people
47   - @users = group.users.all
  50 + @project = group.projects.find(params[:project_id]) if params[:project_id]
  51 + @users = @project ? @project.users : group.users
  52 + @users.sort_by!(&:name)
  53 +
  54 + if @project
  55 + @team_member = @project.users_projects.new
  56 + end
48 57 end
49 58  
50 59 protected
51 60  
52 61 def group
53   - @group ||= Group.find_by_code(params[:id])
  62 + @group ||= Group.find_by_path(params[:id])
54 63 end
55 64  
56 65 def projects
57   - @projects ||= current_user.projects_sorted_by_activity.where(group_id: @group.id)
  66 + @projects ||= group.projects.authorized_for(current_user).sorted_by_activity
58 67 end
59 68  
60 69 def project_ids
61 70 projects.map(&:id)
62 71 end
  72 +
  73 + # Dont allow unauthorized access to group
  74 + def authorize_read_group!
  75 + unless projects.present? or can?(current_user, :manage_group, @group)
  76 + return render_404
  77 + end
  78 + end
63 79 end
... ...
app/controllers/issues_controller.rb
1 1 class IssuesController < ProjectResourceController
2 2 before_filter :module_enabled
3   - before_filter :issue, only: [:edit, :update, :destroy, :show]
  3 + before_filter :issue, only: [:edit, :update, :show]
4 4  
5 5 # Allow read any issue
6 6 before_filter :authorize_read_issue!
... ... @@ -11,9 +11,6 @@ class IssuesController &lt; ProjectResourceController
11 11 # Allow modify issue
12 12 before_filter :authorize_modify_issue!, only: [:edit, :update]
13 13  
14   - # Allow destroy issue
15   - before_filter :authorize_admin_issue!, only: [:destroy]
16   -
17 14 respond_to :js, :html
18 15  
19 16 def index
... ... @@ -77,15 +74,6 @@ class IssuesController &lt; ProjectResourceController
77 74 end
78 75 end
79 76  
80   - def destroy
81   - @issue.destroy
82   -
83   - respond_to do |format|
84   - format.html { redirect_to project_issues_path }
85   - format.js { render nothing: true }
86   - end
87   - end
88   -
89 77 def sort
90 78 return render_404 unless can?(current_user, :admin_issue, @project)
91 79  
... ...
app/controllers/merge_requests_controller.rb
1 1 class MergeRequestsController < ProjectResourceController
2 2 before_filter :module_enabled
3   - before_filter :merge_request, only: [:edit, :update, :destroy, :show, :commits, :diffs, :automerge, :automerge_check, :raw]
4   - before_filter :validates_merge_request, only: [:show, :diffs, :raw]
  3 + before_filter :merge_request, only: [:edit, :update, :show, :commits, :diffs, :automerge, :automerge_check, :ci_status]
  4 + before_filter :validates_merge_request, only: [:show, :diffs]
5 5 before_filter :define_show_vars, only: [:show, :diffs]
6 6  
7 7 # Allow read any merge_request
... ... @@ -13,10 +13,6 @@ class MergeRequestsController &lt; ProjectResourceController
13 13 # Allow modify merge_request
14 14 before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
15 15  
16   - # Allow destroy merge_request
17   - before_filter :authorize_admin_merge_request!, only: [:destroy]
18   -
19   -
20 16 def index
21 17 @merge_requests = MergeRequestsLoadContext.new(project, current_user, params).execute
22 18 end
... ... @@ -25,11 +21,10 @@ class MergeRequestsController &lt; ProjectResourceController
25 21 respond_to do |format|
26 22 format.html
27 23 format.js
28   - end
29   - end
30 24  
31   - def raw
32   - send_file @merge_request.to_raw
  25 + format.diff { render text: @merge_request.to_diff }
  26 + format.patch { render text: @merge_request.to_patch }
  27 + end
33 28 end
34 29  
35 30 def diffs
... ... @@ -87,14 +82,6 @@ class MergeRequestsController &lt; ProjectResourceController
87 82 end
88 83 end
89 84  
90   - def destroy
91   - @merge_request.destroy
92   -
93   - respond_to do |format|
94   - format.html { redirect_to project_merge_requests_url(@project) }
95   - end
96   - end
97   -
98 85 def branch_from
99 86 @commit = project.commit(params[:ref])
100 87 @commit = CommitDecorator.decorate(@commit)
... ... @@ -105,6 +92,13 @@ class MergeRequestsController &lt; ProjectResourceController
105 92 @commit = CommitDecorator.decorate(@commit)
106 93 end
107 94  
  95 + def ci_status
  96 + status = project.gitlab_ci_service.commit_status(merge_request.last_commit.sha)
  97 + response = { status: status }
  98 +
  99 + render json: response
  100 + end
  101 +
108 102 protected
109 103  
110 104 def merge_request
... ...
app/controllers/milestones_controller.rb
... ... @@ -12,11 +12,12 @@ class MilestonesController &lt; ProjectResourceController
12 12  
13 13 def index
14 14 @milestones = case params[:f]
15   - when 'all'; @project.milestones
16   - else @project.milestones.active
  15 + when 'all'; @project.milestones.order("closed, due_date DESC")
  16 + when 'closed'; @project.milestones.closed.order("due_date DESC")
  17 + else @project.milestones.active.order("due_date ASC")
17 18 end
18 19  
19   - @milestones = @milestones.includes(:project).order("due_date")
  20 + @milestones = @milestones.includes(:project)
20 21 @milestones = @milestones.page(params[:page]).per(20)
21 22 end
22 23  
... ... @@ -42,6 +43,7 @@ class MilestonesController &lt; ProjectResourceController
42 43  
43 44 def create
44 45 @milestone = @project.milestones.new(params[:milestone])
  46 + @milestone.author_id_of_changes = current_user.id
45 47  
46 48 if @milestone.save
47 49 redirect_to project_milestone_path(@project, @milestone)
... ... @@ -51,7 +53,7 @@ class MilestonesController &lt; ProjectResourceController
51 53 end
52 54  
53 55 def update
54   - @milestone.update_attributes(params[:milestone])
  56 + @milestone.update_attributes(params[:milestone].merge(author_id_of_changes: current_user.id))
55 57  
56 58 respond_to do |format|
57 59 format.js
... ...
app/controllers/omniauth_callbacks_controller.rb
1 1 class OmniauthCallbacksController < Devise::OmniauthCallbacksController
2   - Gitlab.config.omniauth_providers.each do |provider|
  2 + Gitlab.config.omniauth.providers.each do |provider|
3 3 define_method provider['name'] do
4 4 handle_omniauth
5 5 end
... ...
app/controllers/profile_controller.rb
... ... @@ -1,47 +0,0 @@
1   -class ProfileController < ApplicationController
2   - before_filter :user
3   -
4   - def show
5   - end
6   -
7   - def design
8   - end
9   -
10   - def update
11   - @user.update_attributes(params[:user])
12   -
13   - respond_to do |format|
14   - format.html { redirect_to :back }
15   - format.js
16   - end
17   - end
18   -
19   - def token
20   - end
21   -
22   - def password_update
23   - params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
24   -
25   - if @user.update_attributes(params[:user])
26   - flash[:notice] = "Password was successfully updated. Please login with it"
27   - redirect_to new_user_session_path
28   - else
29   - render 'account'
30   - end
31   - end
32   -
33   - def reset_private_token
34   - current_user.reset_authentication_token!
35   - redirect_to profile_account_path
36   - end
37   -
38   - def history
39   - @events = current_user.recent_events.page(params[:page]).per(20)
40   - end
41   -
42   - private
43   -
44   - def user
45   - @user = current_user
46   - end
47   -end
app/controllers/profiles_controller.rb 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +class ProfilesController < ApplicationController
  2 + before_filter :user
  3 + layout 'profile'
  4 +
  5 + def show
  6 + end
  7 +
  8 + def design
  9 + end
  10 +
  11 + def account
  12 + end
  13 +
  14 + def update
  15 + if @user.update_attributes(params[:user])
  16 + flash[:notice] = "Profile was successfully updated"
  17 + else
  18 + flash[:alert] = "Failed to update profile"
  19 + end
  20 +
  21 + respond_to do |format|
  22 + format.html { redirect_to :back }
  23 + format.js
  24 + end
  25 + end
  26 +
  27 + def token
  28 + end
  29 +
  30 + def update_password
  31 + params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
  32 +
  33 + if @user.update_attributes(params[:user])
  34 + flash[:notice] = "Password was successfully updated. Please login with it"
  35 + redirect_to new_user_session_path
  36 + else
  37 + render 'account'
  38 + end
  39 + end
  40 +
  41 + def reset_private_token
  42 + if current_user.reset_authentication_token!
  43 + flash[:notice] = "Token was successfully updated"
  44 + end
  45 +
  46 + redirect_to account_profile_path
  47 + end
  48 +
  49 + def history
  50 + @events = current_user.recent_events.page(params[:page]).per(20)
  51 + end
  52 +
  53 + def update_username
  54 + @user.update_attributes(username: params[:user][:username])
  55 +
  56 + respond_to do |format|
  57 + format.js
  58 + end
  59 + end
  60 +
  61 + private
  62 +
  63 + def user
  64 + @user = current_user
  65 + end
  66 +end
... ...
app/controllers/project_resource_controller.rb
1 1 class ProjectResourceController < ApplicationController
2 2 before_filter :project
3   - # Authorize
4   - before_filter :add_project_abilities
5 3 end
... ...
app/controllers/projects_controller.rb
... ... @@ -34,8 +34,11 @@ class ProjectsController &lt; ProjectResourceController
34 34 end
35 35  
36 36 def update
  37 + status = ProjectUpdateContext.new(project, current_user, params).execute
  38 +
37 39 respond_to do |format|
38   - if project.update_attributes(params[:project])
  40 + if status
  41 + flash[:notice] = 'Project was successfully updated.'
39 42 format.html { redirect_to edit_project_path(project), notice: 'Project was successfully updated.' }
40 43 format.js
41 44 else
... ... @@ -43,6 +46,10 @@ class ProjectsController &lt; ProjectResourceController
43 46 format.js
44 47 end
45 48 end
  49 +
  50 + rescue Project::TransferError => ex
  51 + @error = ex
  52 + render :update_failed
46 53 end
47 54  
48 55 def show
... ... @@ -51,12 +58,12 @@ class ProjectsController &lt; ProjectResourceController
51 58  
52 59 respond_to do |format|
53 60 format.html do
54   - unless @project.empty_repo?
55   - @last_push = current_user.recent_push(@project.id)
56   - render :show
57   - else
58   - render "projects/empty"
59   - end
  61 + unless @project.empty_repo?
  62 + @last_push = current_user.recent_push(@project.id)
  63 + render :show
  64 + else
  65 + render "projects/empty"
  66 + end
60 67 end
61 68 format.js
62 69 end
... ... @@ -80,12 +87,18 @@ class ProjectsController &lt; ProjectResourceController
80 87 end
81 88  
82 89 def graph
83   - graph = Gitlab::Graph::JsonBuilder.new(project)
84   -
85   - @days_json, @commits_json = graph.days_json, graph.commits_json
  90 + respond_to do |format|
  91 + format.html
  92 + format.json do
  93 + graph = Gitlab::Graph::JsonBuilder.new(project)
  94 + render :json => graph.to_json
  95 + end
  96 + end
86 97 end
87 98  
88 99 def destroy
  100 + return access_denied! unless can?(current_user, :remove_project, project)
  101 +
89 102 # Disable the UsersProject update_repository call, otherwise it will be
90 103 # called once for every person removed from the project
91 104 UsersProject.skip_callback(:destroy, :after, :update_repository)
... ...
app/controllers/snippets_controller.rb
... ... @@ -16,7 +16,7 @@ class SnippetsController &lt; ProjectResourceController
16 16 respond_to :html
17 17  
18 18 def index
19   - @snippets = @project.snippets
  19 + @snippets = @project.snippets.fresh
20 20 end
21 21  
22 22 def new
... ... @@ -60,7 +60,7 @@ class SnippetsController &lt; ProjectResourceController
60 60 redirect_to project_snippets_path(@project)
61 61 end
62 62  
63   - def raw
  63 + def raw
64 64 send_data(
65 65 @snippet.content,
66 66 type: "text/plain",
... ...
app/controllers/team_members_controller.rb
... ... @@ -21,7 +21,11 @@ class TeamMembersController &lt; ProjectResourceController
21 21 params[:project_access]
22 22 )
23 23  
24   - redirect_to project_team_index_path(@project)
  24 + if params[:redirect_to]
  25 + redirect_to params[:redirect_to]
  26 + else
  27 + redirect_to project_team_index_path(@project)
  28 + end
25 29 end
26 30  
27 31 def update
... ...
app/decorators/commit_decorator.rb
... ... @@ -76,7 +76,7 @@ class CommitDecorator &lt; ApplicationDecorator
76 76 source_name = send "#{options[:source]}_name".to_sym
77 77 source_email = send "#{options[:source]}_email".to_sym
78 78 text = if options[:avatar]
79   - avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size]
  79 + avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: ""
80 80 %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
81 81 else
82 82 source_name
... ...
app/helpers/application_helper.rb
1 1 require 'digest/md5'
  2 +require 'uri'
2 3  
3 4 module ApplicationHelper
4 5  
... ... @@ -30,13 +31,15 @@ module ApplicationHelper
30 31 args.any? { |v| v.to_s.downcase == action_name }
31 32 end
32 33  
33   - def gravatar_icon(user_email = '', size = 40)
34   - if Gitlab.config.disable_gravatar? || user_email.blank?
  34 + def gravatar_icon(user_email = '', size = nil)
  35 + size = 40 if size.nil? || size <= 0
  36 +
  37 + if !Gitlab.config.gravatar.enabled || user_email.blank?
35 38 'no_avatar.png'
36 39 else
37   - gravatar_prefix = request.ssl? ? "https://secure" : "http://www"
  40 + gravatar_url = request.ssl? ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
38 41 user_email.strip!
39   - "#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=mm"
  42 + sprintf(gravatar_url, {:hash => Digest::MD5.hexdigest(user_email.downcase), :email => URI.escape(user_email), :size => size})
40 43 end
41 44 end
42 45  
... ... @@ -45,7 +48,7 @@ module ApplicationHelper
45 48 end
46 49  
47 50 def web_app_url
48   - "#{request_protocol}://#{Gitlab.config.web_host}/"
  51 + "#{request_protocol}://#{Gitlab.config.gitlab.host}/"
49 52 end
50 53  
51 54 def last_commit(project)
... ... @@ -75,7 +78,7 @@ module ApplicationHelper
75 78 end
76 79  
77 80 def search_autocomplete_source
78   - projects = current_user.projects.map{ |p| { label: p.name, url: project_path(p) } }
  81 + projects = current_user.projects.map{ |p| { label: p.name_with_namespace, url: project_path(p) } }
79 82  
80 83 default_nav = [
81 84 { label: "My Profile", url: profile_path },
... ... @@ -92,6 +95,7 @@ module ApplicationHelper
92 95 { label: "API Help", url: help_api_path },
93 96 { label: "Markdown Help", url: help_markdown_path },
94 97 { label: "SSH Keys Help", url: help_ssh_path },
  98 + { label: "Gitlab Rake Tasks Help", url: help_raketasks_path },
95 99 ]
96 100  
97 101 project_nav = []
... ... @@ -126,6 +130,10 @@ module ApplicationHelper
126 130 Gitlab::Theme.css_class_by_id(current_user.try(:theme_id))
127 131 end
128 132  
  133 + def user_color_scheme_class
  134 + current_user.dark_scheme ? :black : :white
  135 + end
  136 +
129 137 def show_last_push_widget?(event)
130 138 event &&
131 139 event.last_push_to_non_root? &&
... ...
app/helpers/dashboard_helper.rb 0 → 100644
... ... @@ -0,0 +1,32 @@
  1 +module DashboardHelper
  2 + def dashboard_filter_path(entity, options={})
  3 + exist_opts = {
  4 + status: params[:status],
  5 + project_id: params[:project_id],
  6 + }
  7 +
  8 + options = exist_opts.merge(options)
  9 +
  10 + case entity
  11 + when 'issue' then
  12 + dashboard_issues_path(options)
  13 + when 'merge_request'
  14 + dashboard_merge_requests_path(options)
  15 + end
  16 + end
  17 +
  18 + def entities_per_project project, entity
  19 + items = project.items_for(entity)
  20 +
  21 + items = case params[:status]
  22 + when 'closed'
  23 + items.closed
  24 + when 'all'
  25 + items
  26 + else
  27 + items.opened
  28 + end
  29 +
  30 + items.where(assignee_id: current_user.id).count
  31 + end
  32 +end
... ...
app/helpers/issues_helper.rb
... ... @@ -4,28 +4,6 @@ module IssuesHelper
4 4 project_issues_path project, params
5 5 end
6 6  
7   - def link_to_issue_assignee(issue)
8   - project = issue.project
9   -
10   - tm = project.team_member_by_id(issue.assignee_id)
11   - if tm
12   - link_to issue.assignee_name, project_team_member_path(project, tm), class: "author_link"
13   - else
14   - issue.assignee_name
15   - end
16   - end
17   -
18   - def link_to_issue_author(issue)
19   - project = issue.project
20   -
21   - tm = project.team_member_by_id(issue.author_id)
22   - if tm
23   - link_to issue.author_name, project_team_member_path(project, tm), class: "author_link"
24   - else
25   - issue.author_name
26   - end
27   - end
28   -
29 7 def issue_css_classes issue
30 8 classes = "issue"
31 9 classes << " closed" if issue.closed
... ... @@ -52,4 +30,14 @@ module IssuesHelper
52 30 open: "open"
53 31 }
54 32 end
  33 +
  34 + def labels_autocomplete_source
  35 + labels = @project.issues_labels.order('count DESC')
  36 + labels = labels.map{ |l| { label: l.name, value: l.name } }
  37 + labels.to_json
  38 + end
  39 +
  40 + def issues_active_milestones
  41 + @project.milestones.active.order("id desc").all
  42 + end
55 43 end
... ...
app/helpers/merge_requests_helper.rb
1 1 module MergeRequestsHelper
2   - def link_to_merge_request_assignee(merge_request)
3   - project = merge_request.project
4   -
5   - tm = project.team_member_by_id(merge_request.assignee_id)
6   - if tm
7   - link_to merge_request.assignee_name, project_team_member_path(project, tm), class: "author_link"
8   - else
9   - merge_request.assignee_name
10   - end
11   - end
12   -
13   - def link_to_merge_request_author(merge_request)
14   - project = merge_request.project
15   -
16   - tm = project.team_member_by_id(merge_request.author_id)
17   - if tm
18   - link_to merge_request.author_name, project_team_member_path(project, tm), class: "author_link"
19   - else
20   - merge_request.author_name
21   - end
22   - end
23   -
24 2 def new_mr_path_from_push_event(event)
25 3 new_project_merge_request_path(
26 4 event.project,
... ... @@ -39,7 +17,7 @@ module MergeRequestsHelper
39 17 classes
40 18 end
41 19  
42   - def ci_status_path
43   - @project.gitlab_ci_service.commit_badge_path(@merge_request.last_commit.sha)
  20 + def ci_build_details_path merge_request
  21 + merge_request.project.gitlab_ci_service.build_page(merge_request.last_commit.sha)
44 22 end
45 23 end
... ...
app/helpers/namespaces_helper.rb 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +module NamespacesHelper
  2 + def namespaces_options(selected = :current_user, scope = :default)
  3 + groups = current_user.namespaces.select {|n| n.type == 'Group'}
  4 +
  5 + users = if scope == :all
  6 + Namespace.root
  7 + else
  8 + current_user.namespaces.reject {|n| n.type == 'Group'}
  9 + end
  10 +
  11 + global_opts = ["Global", [['/', Namespace.global_id]] ]
  12 + group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ]
  13 + users_opts = [ "Users", users.map {|u| [u.human_name, u.id]} ]
  14 +
  15 + options = []
  16 + options << global_opts if current_user.admin
  17 + options << group_opts
  18 + options << users_opts
  19 +
  20 + if selected == :current_user && current_user.namespace
  21 + selected = current_user.namespace.id
  22 + end
  23 +
  24 + grouped_options_for_select(options, selected)
  25 + end
  26 +end
... ...
app/helpers/projects_helper.rb
... ... @@ -8,11 +8,49 @@ module ProjectsHelper
8 8 end
9 9  
10 10 def link_to_project project
11   - link_to project.name, project
  11 + link_to project do
  12 + title = content_tag(:strong, project.name)
  13 +
  14 + if project.namespace
  15 + namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'tiny')
  16 + title = namespace + title
  17 + end
  18 +
  19 + title
  20 + end
  21 + end
  22 +
  23 + def link_to_member(project, author)
  24 + return "(deleted)" unless author
  25 +
  26 + # Build avatar image tag
  27 + avatar = image_tag(gravatar_icon(author.try(:email)), width: 16, class: "lil_av")
  28 +
  29 + # Build name strong tag
  30 + name = content_tag :strong, author.name, class: 'author'
  31 +
  32 + author_html = avatar + name
  33 +
  34 + tm = project.team_member_by_id(author)
  35 +
  36 + content_tag :span, class: 'member-link' do
  37 + if tm
  38 + link_to author_html, project_team_member_path(project, tm), class: "author_link"
  39 + else
  40 + author_html
  41 + end
  42 + end
12 43 end
13 44  
14 45 def tm_path team_member
15 46 project_team_member_path(@project, team_member)
16 47 end
17   -end
18 48  
  49 + def project_title project
  50 + if project.group
  51 + project.name_with_namespace
  52 + else
  53 + project.name
  54 + end
  55 + end
  56 +end
... ...
app/helpers/tab_helper.rb
... ... @@ -72,7 +72,7 @@ module TabHelper
72 72 return "active" if current_page?(controller: "projects", action: action, id: @project)
73 73 end
74 74  
75   - if ['snippets', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name
  75 + if ['snippets', 'services', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name
76 76 "active"
77 77 end
78 78 end
... ... @@ -84,4 +84,17 @@ module TabHelper
84 84 'active'
85 85 end
86 86 end
  87 +
  88 + # Use nav_tab for save controller/action but different params
  89 + def nav_tab key, value, &block
  90 + o = {}
  91 + o[:class] = ""
  92 + o[:class] << " active" if params[key] == value
  93 +
  94 + if block_given?
  95 + content_tag(:li, capture(&block), o)
  96 + else
  97 + content_tag(:li, nil, o)
  98 + end
  99 + end
87 100 end
... ...
app/mailers/notify.rb
... ... @@ -3,11 +3,11 @@ class Notify &lt; ActionMailer::Base
3 3 add_template_helper ApplicationHelper
4 4 add_template_helper GitlabMarkdownHelper
5 5  
6   - default_url_options[:host] = Gitlab.config.web_host
7   - default_url_options[:protocol] = Gitlab.config.web_protocol
8   - default_url_options[:port] = Gitlab.config.web_port if Gitlab.config.web_custom_port?
  6 + default_url_options[:host] = Gitlab.config.gitlab.host
  7 + default_url_options[:protocol] = Gitlab.config.gitlab.protocol
  8 + default_url_options[:port] = Gitlab.config.gitlab.port if Gitlab.config.gitlab_on_non_standard_port?
9 9  
10   - default from: Gitlab.config.email_from
  10 + default from: Gitlab.config.gitlab.email_from
11 11  
12 12  
13 13  
... ... @@ -31,6 +31,7 @@ class Notify &lt; ActionMailer::Base
31 31 def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
32 32 @issue = Issue.find issue_id
33 33 @issue_status = status
  34 + @project = @issue.project
34 35 @updated_by = User.find updated_by_user_id
35 36 mail(to: recipient(recipient_id),
36 37 subject: subject("changed issue ##{@issue.id}", @issue.title))
... ... @@ -89,14 +90,6 @@ class Notify &lt; ActionMailer::Base
89 90 mail(to: recipient(recipient_id), subject: subject)
90 91 end
91 92  
92   - def note_wiki_email(recipient_id, note_id)
93   - @note = Note.find(note_id)
94   - @wiki = @note.noteable
95   - @project = @note.project
96   - mail(to: recipient(recipient_id), subject: subject("note for wiki"))
97   - end
98   -
99   -
100 93  
101 94 #
102 95 # Project
... ... @@ -105,11 +98,17 @@ class Notify &lt; ActionMailer::Base
105 98 def project_access_granted_email(user_project_id)
106 99 @users_project = UsersProject.find user_project_id
107 100 @project = @users_project.project
108   - mail(to: @users_project.user.email,
  101 + mail(to: @users_project.user.email,
109 102 subject: subject("access to project was granted"))
110 103 end
111 104  
112 105  
  106 + def project_was_moved_email(user_project_id)
  107 + @users_project = UsersProject.find user_project_id
  108 + @project = @users_project.project
  109 + mail(to: @users_project.user.email,
  110 + subject: subject("project was moved"))
  111 + end
113 112  
114 113 #
115 114 # User
... ...
app/models/ability.rb
... ... @@ -7,6 +7,7 @@ class Ability
7 7 when "Note" then note_abilities(object, subject)
8 8 when "Snippet" then snippet_abilities(object, subject)
9 9 when "MergeRequest" then merge_request_abilities(object, subject)
  10 + when "Group" then group_abilities(object, subject)
10 11 else []
11 12 end
12 13 end
... ... @@ -14,7 +15,40 @@ class Ability
14 15 def project_abilities(user, project)
15 16 rules = []
16 17  
17   - rules << [
  18 + # Rules based on role in project
  19 + if project.master_access_for?(user)
  20 + rules << project_master_rules
  21 +
  22 + elsif project.dev_access_for?(user)
  23 + rules << project_dev_rules
  24 +
  25 + elsif project.report_access_for?(user)
  26 + rules << project_report_rules
  27 +
  28 + elsif project.guest_access_for?(user)
  29 + rules << project_guest_rules
  30 + end
  31 +
  32 + if project.namespace
  33 + # If user own project namespace
  34 + # (Ex. group owner or account owner)
  35 + if project.namespace.owner == user
  36 + rules << project_admin_rules
  37 + end
  38 + else
  39 + # For compatibility with global projects
  40 + # use projects.owner_id
  41 + if project.owner == user
  42 + rules << project_admin_rules
  43 + end
  44 + end
  45 +
  46 +
  47 + rules.flatten
  48 + end
  49 +
  50 + def project_guest_rules
  51 + [
18 52 :read_project,
19 53 :read_wiki,
20 54 :read_issue,
... ... @@ -26,28 +60,30 @@ class Ability
26 60 :write_project,
27 61 :write_issue,
28 62 :write_note
29   - ] if project.guest_access_for?(user)
  63 + ]
  64 + end
30 65  
31   - rules << [
  66 + def project_report_rules
  67 + project_guest_rules + [
32 68 :download_code,
33 69 :write_merge_request,
34 70 :write_snippet
35   - ] if project.report_access_for?(user)
  71 + ]
  72 + end
36 73  
37   - rules << [
  74 + def project_dev_rules
  75 + project_report_rules + [
38 76 :write_wiki,
39 77 :push_code
40   - ] if project.dev_access_for?(user)
41   -
42   - rules << [
43   - :push_code_to_protected_branches
44   - ] if project.master_access_for?(user)
  78 + ]
  79 + end
45 80  
46   - rules << [
  81 + def project_master_rules
  82 + project_dev_rules + [
  83 + :push_code_to_protected_branches,
47 84 :modify_issue,
48 85 :modify_snippet,
49 86 :modify_merge_request,
50   - :admin_project,
51 87 :admin_issue,
52 88 :admin_milestone,
53 89 :admin_snippet,
... ... @@ -55,8 +91,25 @@ class Ability
55 91 :admin_merge_request,
56 92 :admin_note,
57 93 :accept_mr,
58   - :admin_wiki
59   - ] if project.master_access_for?(user) || project.owner == user
  94 + :admin_wiki,
  95 + :admin_project
  96 + ]
  97 + end
  98 +
  99 + def project_admin_rules
  100 + project_master_rules + [
  101 + :change_namespace,
  102 + :rename_project,
  103 + :remove_project
  104 + ]
  105 + end
  106 +
  107 + def group_abilities user, group
  108 + rules = []
  109 +
  110 + rules << [
  111 + :manage_group
  112 + ] if group.owner == user
60 113  
61 114 rules.flatten
62 115 end
... ...
app/models/commit.rb
... ... @@ -87,14 +87,10 @@ class Commit
87 87 last = project.commit(from.try(:strip))
88 88  
89 89 if first && last
90   - commits = [first, last].sort_by(&:created_at)
91   - younger = commits.first
92   - older = commits.last
93   -
94   - result[:same] = (younger.id == older.id)
95   - result[:commits] = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)}
96   - result[:diffs] = project.repo.diff(younger.id, older.id) rescue []
97   - result[:commit] = Commit.new(older)
  90 + result[:same] = (first.id == last.id)
  91 + result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)}
  92 + result[:diffs] = project.repo.diff(last.id, first.id) rescue []
  93 + result[:commit] = Commit.new(first)
98 94 end
99 95  
100 96 result
... ... @@ -150,4 +146,21 @@ class Commit
150 146 def parents_count
151 147 parents && parents.count || 0
152 148 end
  149 +
  150 + # Shows the diff between the commit's parent and the commit.
  151 + #
  152 + # Cuts out the header and stats from #to_patch and returns only the diff.
  153 + def to_diff
  154 + # see Grit::Commit#show
  155 + patch = to_patch
  156 +
  157 + # discard lines before the diff
  158 + lines = patch.split("\n")
  159 + while !lines.first.start_with?("diff --git") do
  160 + lines.shift
  161 + end
  162 + lines.pop if lines.last =~ /^[\d.]+$/ # Git version
  163 + lines.pop if lines.last == "-- " # end of diff
  164 + lines.join("\n")
  165 + end
153 166 end
... ...
app/models/event.rb
... ... @@ -15,6 +15,7 @@
15 15 #
16 16  
17 17 class Event < ActiveRecord::Base
  18 + include NoteEvent
18 19 include PushEvent
19 20  
20 21 attr_accessible :project, :action, :data, :author_id, :project_id,
... ... @@ -58,12 +59,14 @@ class Event &lt; ActiveRecord::Base
58 59 end
59 60 end
60 61  
61   - # Next events currently enabled for system
62   - # - push
63   - # - new issue
64   - # - merge request
65   - def allowed?
66   - push? || issue? || merge_request? || membership_changed?
  62 + def proper?
  63 + if push?
  64 + true
  65 + elsif membership_changed?
  66 + true
  67 + else
  68 + (issue? || merge_request? || note? || milestone?) && target
  69 + end
67 70 end
68 71  
69 72 def project_name
... ... @@ -94,6 +97,14 @@ class Event &lt; ActiveRecord::Base
94 97 action == self.class::Reopened
95 98 end
96 99  
  100 + def milestone?
  101 + target_type == "Milestone"
  102 + end
  103 +
  104 + def note?
  105 + target_type == "Note"
  106 + end
  107 +
97 108 def issue?
98 109 target_type == "Issue"
99 110 end
... ...
app/models/gitlab_ci_service.rb
... ... @@ -36,4 +36,22 @@ class GitlabCiService &lt; Service
36 36 def commit_badge_path sha
37 37 project_url + "/status?sha=#{sha}"
38 38 end
  39 +
  40 + def commit_status_path sha
  41 + project_url + "/builds/#{sha}/status.json?token=#{token}"
  42 + end
  43 +
  44 + def commit_status sha
  45 + response = HTTParty.get(commit_status_path(sha))
  46 +
  47 + if response.code == 200 and response["status"]
  48 + response["status"]
  49 + else
  50 + :error
  51 + end
  52 + end
  53 +
  54 + def build_page sha
  55 + project_url + "/builds/#{sha}"
  56 + end
39 57 end
... ...
app/models/group.rb
1 1 # == Schema Information
2 2 #
3   -# Table name: groups
  3 +# Table name: namespaces
4 4 #
5 5 # id :integer not null, primary key
6 6 # name :string(255) not null
7   -# code :string(255) not null
  7 +# path :string(255) not null
8 8 # owner_id :integer not null
9 9 # created_at :datetime not null
10 10 # updated_at :datetime not null
  11 +# type :string(255)
11 12 #
12 13  
13   -class Group < ActiveRecord::Base
14   - attr_accessible :code, :name, :owner_id
15   -
16   - has_many :projects
17   - belongs_to :owner, class_name: "User"
18   -
19   - validates :name, presence: true, uniqueness: true
20   - validates :code, presence: true, uniqueness: true
21   - validates :owner, presence: true
22   -
23   - delegate :name, to: :owner, allow_nil: true, prefix: true
24   -
25   - def self.search query
26   - where("name LIKE :query OR code LIKE :query", query: "%#{query}%")
27   - end
28   -
29   - def to_param
30   - code
  14 +class Group < Namespace
  15 + def users
  16 + users = User.joins(:users_projects).where(users_projects: {project_id: project_ids})
  17 + users = users << owner
  18 + users.uniq
31 19 end
32 20  
33   - def users
34   - User.joins(:users_projects).where(users_projects: {project_id: project_ids}).uniq
  21 + def human_name
  22 + name
35 23 end
36 24 end
... ...
app/models/merge_request.rb
... ... @@ -202,20 +202,26 @@ class MergeRequest &lt; ActiveRecord::Base
202 202 false
203 203 end
204 204  
205   - def to_raw
206   - FileUtils.mkdir_p(Rails.root.join("tmp", "patches"))
207   - patch_path = Rails.root.join("tmp", "patches", "merge_request_#{self.id}.patch")
208   -
209   - from = commits.last.id
210   - to = source_branch
  205 + def mr_and_commit_notes
  206 + commit_ids = commits.map(&:id)
  207 + Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
  208 + end
211 209  
212   - project.repo.git.run('', "format-patch" , " > #{patch_path.to_s}", {}, ["#{from}..#{to}", "--stdout"])
  210 + # Returns the raw diff for this merge request
  211 + #
  212 + # see "git diff"
  213 + def to_diff
  214 + project.repo.git.native(:diff, {timeout: 30, raise: true}, "#{target_branch}...#{source_branch}")
  215 + end
213 216  
214   - patch_path
  217 + # Returns the commit as a series of email patches.
  218 + #
  219 + # see "git format-patch"
  220 + def to_patch
  221 + project.repo.git.format_patch({timeout: 30, raise: true, stdout: true}, "#{target_branch}..#{source_branch}")
215 222 end
216 223  
217   - def mr_and_commit_notes
218   - commit_ids = commits.map(&:id)
219   - Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND noteable_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
  224 + def last_commit_short_sha
  225 + @last_commit_short_sha ||= last_commit.sha[0..10]
220 226 end
221 227 end
... ...
app/models/milestone.rb
... ... @@ -13,18 +13,26 @@
13 13 #
14 14  
15 15 class Milestone < ActiveRecord::Base
16   - attr_accessible :title, :description, :due_date, :closed
  16 + attr_accessible :title, :description, :due_date, :closed, :author_id_of_changes
  17 + attr_accessor :author_id_of_changes
17 18  
18 19 belongs_to :project
19 20 has_many :issues
20 21 has_many :merge_requests
21 22  
  23 + scope :active, where(closed: false)
  24 + scope :closed, where(closed: true)
  25 +
22 26 validates :title, presence: true
23 27 validates :project, presence: true
24 28 validates :closed, inclusion: { in: [true, false] }
25 29  
26   - def self.active
27   - where("due_date > ? OR due_date IS NULL", Date.today)
  30 + def expired?
  31 + if due_date
  32 + due_date < Date.today
  33 + else
  34 + false
  35 + end
28 36 end
29 37  
30 38 def participants
... ... @@ -52,4 +60,20 @@ class Milestone &lt; ActiveRecord::Base
52 60 def expires_at
53 61 "expires at #{due_date.stamp("Aug 21, 2011")}" if due_date
54 62 end
  63 +
  64 + def can_be_closed?
  65 + open? && issues.opened.count.zero?
  66 + end
  67 +
  68 + def is_empty?
  69 + total_items_count.zero?
  70 + end
  71 +
  72 + def open?
  73 + !closed
  74 + end
  75 +
  76 + def author_id
  77 + author_id_of_changes
  78 + end
55 79 end
... ...
app/models/namespace.rb 0 → 100644
... ... @@ -0,0 +1,77 @@
  1 +# == Schema Information
  2 +#
  3 +# Table name: namespaces
  4 +#
  5 +# id :integer not null, primary key
  6 +# name :string(255) not null
  7 +# path :string(255) not null
  8 +# owner_id :integer not null
  9 +# created_at :datetime not null
  10 +# updated_at :datetime not null
  11 +# type :string(255)
  12 +#
  13 +
  14 +class Namespace < ActiveRecord::Base
  15 + attr_accessible :name, :path
  16 +
  17 + has_many :projects, dependent: :destroy
  18 + belongs_to :owner, class_name: "User"
  19 +
  20 + validates :name, presence: true, uniqueness: true
  21 + validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
  22 + format: { with: Gitlab::Regex.path_regex,
  23 + message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
  24 + validates :owner, presence: true
  25 +
  26 + delegate :name, to: :owner, allow_nil: true, prefix: true
  27 +
  28 + after_create :ensure_dir_exist
  29 + after_update :move_dir
  30 + after_destroy :rm_dir
  31 +
  32 + scope :root, where('type IS NULL')
  33 +
  34 + def self.search query
  35 + where("name LIKE :query OR path LIKE :query", query: "%#{query}%")
  36 + end
  37 +
  38 + def self.global_id
  39 + 'GLN'
  40 + end
  41 +
  42 + def to_param
  43 + path
  44 + end
  45 +
  46 + def human_name
  47 + owner_name
  48 + end
  49 +
  50 + def ensure_dir_exist
  51 + namespace_dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
  52 + system("mkdir -m 770 #{namespace_dir_path}") unless File.exists?(namespace_dir_path)
  53 + end
  54 +
  55 + def move_dir
  56 + if path_changed?
  57 + old_path = File.join(Gitlab.config.gitolite.repos_path, path_was)
  58 + new_path = File.join(Gitlab.config.gitolite.repos_path, path)
  59 + if File.exists?(new_path)
  60 + raise "Already exists"
  61 + end
  62 +
  63 + if system("mv #{old_path} #{new_path}")
  64 + send_update_instructions
  65 + end
  66 + end
  67 + end
  68 +
  69 + def rm_dir
  70 + dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
  71 + system("rm -rf #{dir_path}")
  72 + end
  73 +
  74 + def send_update_instructions
  75 + projects.each(&:send_move_instructions)
  76 + end
  77 +end
... ...
app/models/note.rb
... ... @@ -20,7 +20,7 @@ require &#39;file_size_validator&#39;
20 20 class Note < ActiveRecord::Base
21 21  
22 22 attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
23   - :attachment, :line_code
  23 + :attachment, :line_code, :commit_id
24 24  
25 25 attr_accessor :notify
26 26 attr_accessor :notify_author
... ... @@ -32,14 +32,17 @@ class Note &lt; ActiveRecord::Base
32 32 delegate :name, to: :project, prefix: true
33 33 delegate :name, :email, to: :author, prefix: true
34 34  
35   - validates :project, presence: true
36   - validates :note, presence: true, length: { within: 0..5000 }
  35 + validates :note, :project, presence: true
37 36 validates :attachment, file_size: { maximum: 10.megabytes.to_i }
38 37  
39   - mount_uploader :attachment, AttachmentUploader
  38 + validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' }
  39 + validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' }
  40 +
  41 + mount_uploader :attachment, AttachmentUploader
40 42  
41 43 # Scopes
42   - scope :common, ->{ where(noteable_id: nil) }
  44 + scope :for_commits, ->{ where(noteable_type: "Commit") }
  45 + scope :common, ->{ where(noteable_id: nil, commit_id: nil) }
43 46 scope :today, ->{ where("created_at >= :date", date: Date.today) }
44 47 scope :last_week, ->{ where("created_at >= :date", date: (Date.today - 7.days)) }
45 48 scope :since, ->(day) { where("created_at >= :date", date: (day)) }
... ... @@ -67,7 +70,7 @@ class Note &lt; ActiveRecord::Base
67 70 # override to return commits, which are not active record
68 71 def noteable
69 72 if for_commit?
70   - project.commit(noteable_id)
  73 + project.commit(commit_id)
71 74 else
72 75 super
73 76 end
... ... @@ -122,4 +125,12 @@ class Note &lt; ActiveRecord::Base
122 125 def downvote?
123 126 note.start_with?('-1') || note.start_with?(':-1:')
124 127 end
  128 +
  129 + def noteable_type_name
  130 + if noteable_type.present?
  131 + noteable_type.downcase
  132 + else
  133 + "wall"
  134 + end
  135 + end
125 136 end
... ...