diff --git a/.gitignore b/.gitignore index 74111a22..c53bac48 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,10 @@ coverage/* *.swp public/uploads/ .rvmrc +.rbenv-version .directory nohup.out +Vagrantfile +.vagrant +config/gitlab.yml +config/database.yml diff --git a/.rbenv-version b/.rbenv-version deleted file mode 100644 index 0a95b9f5..00000000 --- a/.rbenv-version +++ /dev/null @@ -1 +0,0 @@ -1.9.2-p290 diff --git a/.travis.yml b/.travis.yml index 7a450b7d..0193d007 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ branches: - 'master' rvm: 1.9.2 before_script: + - "cp config/database.yml.example config/database.yml" + - "cp config/gitlab.yml.example config/gitlab.yml" - "bundle exec rake db:create RAILS_ENV=test" - "bundle exec rake db:migrate RAILS_ENV=test" - "bundle exec rake db:seed_fu RAILS_ENV=test" diff --git a/Gemfile b/Gemfile index b80dca11..5c0b660d 100644 --- a/Gemfile +++ b/Gemfile @@ -1,10 +1,10 @@ source "http://rubygems.org" -gem "rails", "3.1.1" +gem "rails", "3.2.1" gem "sqlite3" -gem "rake", "0.9.2.2" -gem "devise", "1.5.0" +gem "rake" +gem "devise" gem "stamp" gem "kaminari" gem "haml", "3.1.4" @@ -16,7 +16,7 @@ gem "carrierwave" gem "six" gem "therubyracer" gem "faker" -gem "seed-fu", "~> 2.1.0" +gem "seed-fu" gem "pygments.rb", "0.2.4" gem "thin" gem "git" @@ -24,20 +24,23 @@ gem "acts_as_list" gem "rdiscount" gem "acts-as-taggable-on", "~> 2.1.0" gem "drapper" -gem "resque" +gem "resque", "~> 1.20.0" gem "httparty" gem "charlock_holmes" gem "foreman" +gem "omniauth-ldap" +gem 'bootstrap-sass', "1.4.4" +gem "colored" group :assets do - gem "sass-rails", "~> 3.1.0" - gem "coffee-rails", "~> 3.1.0" - gem "uglifier" + gem "sass-rails", "3.2.3" + gem "coffee-rails", "3.2.1" + gem "uglifier", "1.0.3" end group :development do gem "letter_opener" - gem "rails-footnotes", "~> 3.7.5" + gem "rails-footnotes" gem "annotate", :git => "https://github.com/ctran/annotate_models.git" end @@ -46,9 +49,7 @@ group :development, :test do gem "capybara" gem "autotest" gem "autotest-rails" - unless ENV["CI"] - gem "ruby-debug19", :require => "ruby-debug" - end + gem "pry" gem "awesome_print" gem "database_cleaner" gem "launchy" @@ -58,5 +59,5 @@ end group :test do gem "turn", :require => false gem "simplecov", :require => false - gem "shoulda", "~> 3.0.0.beta2" + gem "shoulda", "3.0.0" end diff --git a/Gemfile.lock b/Gemfile.lock index ec171d2c..09457d5b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: https://github.com/ctran/annotate_models.git - revision: fb73329243056a6d9a64878e5c543aba9b6417de + revision: a43c08f0eb4d69a48c6830630ebb60e35ccb2d2d specs: annotate (2.4.1.beta1) @@ -25,48 +25,48 @@ GEM remote: http://rubygems.org/ specs: ZenTest (4.5.0) - actionmailer (3.1.1) - actionpack (= 3.1.1) - mail (~> 2.3.0) - actionpack (3.1.1) - activemodel (= 3.1.1) - activesupport (= 3.1.1) + actionmailer (3.2.1) + actionpack (= 3.2.1) + mail (~> 2.4.0) + actionpack (3.2.1) + activemodel (= 3.2.1) + activesupport (= 3.2.1) builder (~> 3.0.0) erubis (~> 2.7.0) - i18n (~> 0.6) - rack (~> 1.3.2) + journey (~> 1.0.1) + rack (~> 1.4.0) rack-cache (~> 1.1) - rack-mount (~> 0.8.2) rack-test (~> 0.6.1) - sprockets (~> 2.0.2) - activemodel (3.1.1) - activesupport (= 3.1.1) + sprockets (~> 2.1.2) + activemodel (3.2.1) + activesupport (= 3.2.1) builder (~> 3.0.0) - i18n (~> 0.6) - activerecord (3.1.1) - activemodel (= 3.1.1) - activesupport (= 3.1.1) - arel (~> 2.2.1) + activerecord (3.2.1) + activemodel (= 3.2.1) + activesupport (= 3.2.1) + arel (~> 3.0.0) tzinfo (~> 0.3.29) - activeresource (3.1.1) - activemodel (= 3.1.1) - activesupport (= 3.1.1) - activesupport (3.1.1) + activeresource (3.2.1) + activemodel (= 3.2.1) + activesupport (= 3.2.1) + activesupport (3.2.1) + i18n (~> 0.6) multi_json (~> 1.0) acts-as-taggable-on (2.1.1) rails acts_as_list (0.1.4) addressable (2.2.6) - ansi (1.4.1) - archive-tar-minitar (0.5.2) - arel (2.2.1) + ansi (1.4.2) + arel (3.0.0) autotest (4.4.6) ZenTest (>= 4.4.1) autotest-rails (4.1.1) ZenTest (= 4.5) - awesome_print (0.4.0) + awesome_print (1.0.2) bcrypt-ruby (3.0.1) blankslate (2.1.2.4) + bootstrap-sass (1.4.4) + sass-rails (~> 3.1) builder (3.0.0) capybara (1.1.2) mime-types (>= 1.16) @@ -78,19 +78,20 @@ GEM carrierwave (0.5.8) activesupport (~> 3.0) charlock_holmes (0.6.8) - childprocess (0.2.2) + childprocess (0.3.1) ffi (~> 1.0.6) - coffee-rails (3.1.1) + coderay (1.0.5) + coffee-rails (3.2.1) coffee-script (>= 2.2.0) - railties (~> 3.1.0) + railties (~> 3.2.0.beta) coffee-script (2.2.0) coffee-script-source execjs - coffee-script-source (1.1.3) - columnize (0.3.4) + coffee-script-source (1.2.0) + colored (1.2) crack (0.3.1) - daemons (1.1.4) - database_cleaner (0.7.0) + daemons (1.1.8) + database_cleaner (0.7.1) devise (1.5.0) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.0.3) @@ -99,13 +100,13 @@ GEM drapper (0.8.4) erubis (2.7.0) eventmachine (0.12.10) - execjs (1.2.9) + execjs (1.3.0) multi_json (~> 1.0) faker (1.0.1) i18n (~> 0.4) ffi (1.0.11) - foreman (0.27.0) - term-ansicolor (~> 1.0.5) + foreman (0.39.0) + term-ansicolor (~> 1.0.7) thor (>= 0.13.6) git (1.2.5) haml (3.1.4) @@ -115,139 +116,143 @@ GEM haml (~> 3.0) railties (~> 3.0) hashery (1.4.0) + hashie (1.2.0) hike (1.2.1) httparty (0.8.1) multi_json multi_xml i18n (0.6.0) - jquery-rails (1.0.17) - railties (~> 3.0) + journey (1.0.1) + jquery-rails (2.0.0) + railties (>= 3.2.0.beta, < 5.0) thor (~> 0.14) - json (1.6.1) - json_pure (1.6.1) - kaminari (0.12.4) - rails (>= 3.0.0) + json (1.6.5) + kaminari (0.13.0) + actionpack (>= 3.0.0) + activesupport (>= 3.0.0) + railties (>= 3.0.0) launchy (2.0.5) addressable (~> 2.2.6) letter_opener (0.0.2) launchy libv8 (3.3.10.4) - linecache19 (0.5.12) - ruby_core_source (>= 0.1.4) - mail (2.3.0) + mail (2.4.1) i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) + method_source (0.7.0) mime-types (1.17.2) - multi_json (1.0.3) + multi_json (1.0.4) multi_xml (0.4.1) + net-ldap (0.2.2) nokogiri (1.5.0) - orm_adapter (0.0.5) + omniauth (1.0.2) + hashie (~> 1.2) + rack + omniauth-ldap (1.0.2) + net-ldap (~> 0.2.2) + omniauth (~> 1.0) + pyu-ruby-sasl (~> 0.0.3.1) + rubyntlm (~> 0.1.1) + orm_adapter (0.0.6) polyglot (0.3.3) posix-spawn (0.3.6) + pry (0.9.8.2) + coderay (~> 1.0.5) + method_source (~> 0.7) + slop (>= 2.4.4, < 3) pygments.rb (0.2.4) rubypython (~> 0.5.3) - rack (1.3.5) + pyu-ruby-sasl (0.0.3.3) + rack (1.4.1) rack-cache (1.1) rack (>= 0.4) - rack-mount (0.8.3) - rack (>= 1.0.0) - rack-protection (1.1.4) + rack-protection (1.2.0) rack rack-ssl (1.3.2) rack rack-test (0.6.1) rack (>= 1.0) - rails (3.1.1) - actionmailer (= 3.1.1) - actionpack (= 3.1.1) - activerecord (= 3.1.1) - activeresource (= 3.1.1) - activesupport (= 3.1.1) + rails (3.2.1) + actionmailer (= 3.2.1) + actionpack (= 3.2.1) + activerecord (= 3.2.1) + activeresource (= 3.2.1) + activesupport (= 3.2.1) bundler (~> 1.0) - railties (= 3.1.1) + railties (= 3.2.1) rails-footnotes (3.7.5) rails (>= 3.0.0) - railties (3.1.1) - actionpack (= 3.1.1) - activesupport (= 3.1.1) + railties (3.2.1) + actionpack (= 3.2.1) + activesupport (= 3.2.1) rack-ssl (~> 1.3.2) rake (>= 0.8.7) rdoc (~> 3.4) thor (~> 0.14.6) rake (0.9.2.2) rdiscount (1.6.8) - rdoc (3.11) + rdoc (3.12) json (~> 1.4) redis (2.2.2) redis-namespace (1.0.3) redis (< 3.0.0) - resque (1.19.0) + resque (1.20.0) multi_json (~> 1.0) redis-namespace (~> 1.0.2) sinatra (>= 0.9.2) vegas (~> 0.1.2) - rspec (2.7.0) - rspec-core (~> 2.7.0) - rspec-expectations (~> 2.7.0) - rspec-mocks (~> 2.7.0) - rspec-core (2.7.1) - rspec-expectations (2.7.0) + rspec (2.8.0) + rspec-core (~> 2.8.0) + rspec-expectations (~> 2.8.0) + rspec-mocks (~> 2.8.0) + rspec-core (2.8.0) + rspec-expectations (2.8.0) diff-lcs (~> 1.1.2) - rspec-mocks (2.7.0) - rspec-rails (2.7.0) - actionpack (~> 3.0) - activesupport (~> 3.0) - railties (~> 3.0) - rspec (~> 2.7.0) - ruby-debug-base19 (0.11.25) - columnize (>= 0.3.1) - linecache19 (>= 0.5.11) - ruby_core_source (>= 0.1.4) - ruby-debug19 (0.11.6) - columnize (>= 0.3.1) - linecache19 (>= 0.5.11) - ruby-debug-base19 (>= 0.11.19) - ruby_core_source (0.1.5) - archive-tar-minitar (>= 0.5.2) + rspec-mocks (2.8.0) + rspec-rails (2.8.1) + actionpack (>= 3.0) + activesupport (>= 3.0) + railties (>= 3.0) + rspec (~> 2.8.0) + rubyntlm (0.1.1) rubypython (0.5.3) blankslate (>= 2.1.2.3) ffi (~> 1.0.7) - rubyzip (0.9.4) - sass (3.1.10) - sass-rails (3.1.4) - actionpack (~> 3.1.0) - railties (~> 3.1.0) - sass (>= 3.1.4) - sprockets (~> 2.0.0) - tilt (~> 1.3.2) - seed-fu (2.1.0) - activerecord (~> 3.1.0) - activesupport (~> 3.1.0) - selenium-webdriver (2.12.2) - childprocess (>= 0.2.1) + rubyzip (0.9.6.1) + sass (3.1.15) + sass-rails (3.2.3) + railties (~> 3.2.0.beta) + sass (>= 3.1.10) + tilt (~> 1.3) + seed-fu (2.2.0) + activerecord (~> 3.1) + activesupport (~> 3.1) + selenium-webdriver (2.19.0) + childprocess (>= 0.2.5) ffi (~> 1.0.9) - json_pure + multi_json (~> 1.0.4) rubyzip - shoulda (3.0.0.beta2) - shoulda-context (~> 1.0.0.beta1) - shoulda-matchers (~> 1.0.0.beta1) + shoulda (3.0.0) + shoulda-context (~> 1.0.0) + shoulda-matchers (~> 1.0.0) shoulda-context (1.0.0) shoulda-matchers (1.0.0) simplecov (0.5.4) multi_json (~> 1.0.3) simplecov-html (~> 0.5.3) simplecov-html (0.5.3) - sinatra (1.3.1) - rack (~> 1.3, >= 1.3.4) - rack-protection (~> 1.1, >= 1.1.2) + sinatra (1.3.2) + rack (~> 1.3, >= 1.3.6) + rack-protection (~> 1.2) tilt (~> 1.3, >= 1.3.3) six (0.2.0) - sprockets (2.0.3) + slop (2.4.4) + sprockets (2.1.2) hike (~> 1.2) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sqlite3 (1.3.4) + sqlite3 (1.3.5) stamp (0.1.6) term-ansicolor (1.0.7) therubyracer (0.9.9) @@ -261,17 +266,17 @@ GEM treetop (1.4.10) polyglot polyglot (>= 0.3.1) - turn (0.8.3) + turn (0.9.2) ansi tzinfo (0.3.31) - uglifier (1.1.0) + uglifier (1.0.3) execjs (>= 0.3.0) multi_json (>= 1.0.2) - vegas (0.1.8) + vegas (0.1.11) rack (>= 1.0.0) warden (1.1.0) rack (>= 1.0) - webmock (1.7.8) + webmock (1.7.10) addressable (~> 2.2, > 2.2.5) crack (>= 0.1.7) xpath (0.1.4) @@ -287,12 +292,14 @@ DEPENDENCIES autotest autotest-rails awesome_print + bootstrap-sass (= 1.4.4) capybara carrierwave charlock_holmes - coffee-rails (~> 3.1.0) + coffee-rails (= 3.2.1) + colored database_cleaner - devise (= 1.5.0) + devise drapper faker foreman @@ -306,17 +313,18 @@ DEPENDENCIES kaminari launchy letter_opener + omniauth-ldap + pry pygments.rb (= 0.2.4) - rails (= 3.1.1) - rails-footnotes (~> 3.7.5) - rake (= 0.9.2.2) + rails (= 3.2.1) + rails-footnotes + rake rdiscount - resque + resque (~> 1.20.0) rspec-rails - ruby-debug19 - sass-rails (~> 3.1.0) - seed-fu (~> 2.1.0) - shoulda (~> 3.0.0.beta2) + sass-rails (= 3.2.3) + seed-fu + shoulda (= 3.0.0) simplecov six sqlite3 @@ -324,5 +332,5 @@ DEPENDENCIES therubyracer thin turn - uglifier + uglifier (= 1.0.3) webmock diff --git a/Procfile.production b/Procfile.production index 68e8556e..f1126486 100644 --- a/Procfile.production +++ b/Procfile.production @@ -1,2 +1,2 @@ web: bundle exec rails s -p $PORT -e production -worker: bundle exec rake environment resque:work RAILS_ENV=production QUEUE=* VVERBOSE=1 +worker: bundle exec rake environment resque:work RAILS_ENV=production QUEUE=* diff --git a/VERSION b/VERSION index 7ec1d6db..ccbccc3d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.1.0 +2.2.0 diff --git a/app/assets/images/Gear-UI.PNG b/app/assets/images/Gear-UI.PNG deleted file mode 100644 index 7720f0eb..00000000 Binary files a/app/assets/images/Gear-UI.PNG and /dev/null differ diff --git a/app/assets/images/Home-UI.PNG b/app/assets/images/Home-UI.PNG deleted file mode 100644 index f739af3c..00000000 Binary files a/app/assets/images/Home-UI.PNG and /dev/null differ diff --git a/app/assets/images/Info-UI.PNG b/app/assets/images/Info-UI.PNG index 92795486..7f48ed8d 100644 Binary files a/app/assets/images/Info-UI.PNG and b/app/assets/images/Info-UI.PNG differ diff --git a/app/assets/images/admin.PNG b/app/assets/images/admin.PNG new file mode 100644 index 00000000..73ff1dfb Binary files /dev/null and b/app/assets/images/admin.PNG differ diff --git a/app/assets/images/blueprint_add.png b/app/assets/images/blueprint_add.png index e63641d0..0f01128d 100644 Binary files a/app/assets/images/blueprint_add.png and b/app/assets/images/blueprint_add.png differ diff --git a/app/assets/images/blueprint_delete.png b/app/assets/images/blueprint_delete.png index f171846b..b4d360f3 100644 Binary files a/app/assets/images/blueprint_delete.png and b/app/assets/images/blueprint_delete.png differ diff --git a/app/assets/images/comment_add.png b/app/assets/images/comment_add.png new file mode 100644 index 00000000..010da964 Binary files /dev/null and b/app/assets/images/comment_add.png differ diff --git a/app/assets/images/help_commit.png b/app/assets/images/help_commit.png deleted file mode 100644 index e0a49b71..00000000 Binary files a/app/assets/images/help_commit.png and /dev/null differ diff --git a/app/assets/images/help_merge_request.png b/app/assets/images/help_merge_request.png deleted file mode 100644 index a6b5d3df..00000000 Binary files a/app/assets/images/help_merge_request.png and /dev/null differ diff --git a/app/assets/images/home_icon.PNG b/app/assets/images/home_icon.PNG new file mode 100644 index 00000000..b1d60d59 Binary files /dev/null and b/app/assets/images/home_icon.PNG differ diff --git a/app/assets/images/logo_tr.png b/app/assets/images/logo_tr.png new file mode 100644 index 00000000..7a934bbb Binary files /dev/null and b/app/assets/images/logo_tr.png differ diff --git a/app/assets/images/submodule.png b/app/assets/images/submodule.png new file mode 100644 index 00000000..62a88cc6 Binary files /dev/null and b/app/assets/images/submodule.png differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 5782f0af..b3142feb 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -10,6 +10,8 @@ //= require jquery.ui.selectmenu //= require jquery.tagify //= require jquery.cookie +//= require jquery.endless-scroll +//= require bootstrap-modal //= require modernizr //= require chosen //= require raphael @@ -21,9 +23,6 @@ $(document).ready(function(){ $(this).select(); }); - $('select#branch').selectmenu({style:'popup', width:200}); - $('select#tag').selectmenu({style:'popup', width:200}); - $(".account-box").mouseenter(showMenu); $(".account-box").mouseleave(resetMenu); @@ -43,6 +42,9 @@ $(document).ready(function(){ } }); + /** + * Focus search field by pressing 's' key + */ $(document).keypress(function(e) { if( $(e.target).is(":input") ) return; switch(e.which) { @@ -50,27 +52,12 @@ $(document).ready(function(){ e.preventDefault(); } }); - }); function focusSearch() { $("#search").focus(); } -function taggifyForm(){ - var tag_field = $('#tag_field').tagify(); - - tag_field.tagify('inputField').autocomplete({ - source: '/tags.json' - }); - - $('form').submit( function() { - var tag_field = $('#tag_field') - tag_field.val( tag_field.tagify('serialize') ); - return true; - }); -} - function updatePage(data){ $.ajax({type: "GET", url: location.href, data: data, dataType: "script"}); } @@ -82,5 +69,3 @@ function showMenu() { function resetMenu() { $(this).removeClass("hover"); } - - diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js index bb06df55..b31fe485 100644 --- a/app/assets/javascripts/commits.js +++ b/app/assets/javascripts/commits.js @@ -2,6 +2,7 @@ var CommitsList = { ref:null, limit:0, offset:0, + disable:false, init: function(ref, limit) { @@ -36,15 +37,21 @@ var CommitsList = { $("#commits_list").append(html); if(count > 0) { this.offset += count; - this.initLoadMore(); + } else { + this.disable = true; } }, initLoadMore: function() { - $(window).bind('scroll', function(){ - if($(window).scrollTop() == $(document).height() - $(window).height()){ - $(window).unbind('scroll'); + $(document).endlessScroll({ + bottomPixels: 400, + fireDelay: 1000, + fireOnce:true, + ceaseFire: function() { + return CommitsList.disable; + }, + callback: function(i) { CommitsList.getOld(); } }); diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js index ef70a99d..ded66b1c 100644 --- a/app/assets/javascripts/issues.js +++ b/app/assets/javascripts/issues.js @@ -1,16 +1,18 @@ function switchToNewIssue(form){ - $("#issues-table-holder").hide("slide", { direction: "left" }, 150, function(){ - $(".project-content").append(form); + $(".issues_content").hide("fade", { direction: "left" }, 150, function(){ + $(".issues_content").after(form); $('select#issue_assignee_id').chosen(); - $("#new_issue_dialog").show("slide", { direction: "right" }, 150); + $("#new_issue_dialog").show("fade", { direction: "right" }, 150); + $('.top-tabs .add_new').hide(); }); } function switchToEditIssue(form){ - $("#issues-table-holder").hide("slide", { direction: "left" }, 150, function(){ - $(".project-content").append(form); + $(".issues_content").hide("fade", { direction: "left" }, 150, function(){ + $(".issues_content").after(form); $('select#issue_assignee_id').chosen(); - $("#edit_issue_dialog").show("slide", { direction: "right" }, 150); + $("#edit_issue_dialog").show("fade", { direction: "right" }, 150); + $('.add_new').hide(); }); } @@ -23,10 +25,11 @@ function switchFromEditIssue(){ } function backToIssues(){ - $("#edit_issue_dialog, #new_issue_dialog").hide("slide", { direction: "right" }, 150, function(){ - $("#issues-table-holder").show("slide", { direction: "left" }, 150, function() { + $("#edit_issue_dialog, #new_issue_dialog").hide("fade", { direction: "right" }, 150, function(){ + $(".issues_content").show("fade", { direction: "left" }, 150, function() { $("#edit_issue_dialog").remove(); $("#new_issue_dialog").remove(); + $('.add_new').show(); }); }); } diff --git a/app/assets/javascripts/merge_requests.js b/app/assets/javascripts/merge_requests.js index 0d2f5355..1c262afc 100644 --- a/app/assets/javascripts/merge_requests.js +++ b/app/assets/javascripts/merge_requests.js @@ -4,46 +4,27 @@ var MergeRequest = { init: function() { - $(".merge-tabs a").live("click", function() { - $(".merge-tabs a").removeClass("active"); - $(this).addClass("active"); + $(".tabs a").live("click", function() { + $(".tabs a").parent().removeClass("active"); + $(this).parent().addClass("active"); }); - $(".merge-tabs a.merge-notes-tab").live("click", function() { - $(".merge-request-commits, .merge-request-diffs").hide(); + $(".tabs a.merge-notes-tab").live("click", function(e) { + $(".merge-request-diffs").hide(); $(".merge-request-notes").show(); + e.preventDefault(); }); - $(".merge-tabs a.merge-commits-tab").live("click", function() { - if(!MergeRequest.commits_loaded) { - MergeRequest.loadCommits(); - } - $(".merge-request-notes, .merge-request-diffs").hide(); - $(".merge-request-commits").show(); - }); - - $(".merge-tabs a.merge-diffs-tab").live("click", function() { + $(".tabs a.merge-diffs-tab").live("click", function(e) { if(!MergeRequest.diffs_loaded) { MergeRequest.loadDiff(); } - $(".merge-request-notes, .merge-request-commits").hide(); + $(".merge-request-notes").hide(); $(".merge-request-diffs").show(); + e.preventDefault(); }); }, - loadCommits: - function() { - $(".dashboard-loader").show(); - $.ajax({ - type: "GET", - url: $(".merge-commits-tab").attr("data-url"), - complete: function(){ - MergeRequest.commits_loaded = true; - $(".merge-request-notes, .merge-request-diffs").hide(); - $(".dashboard-loader").hide()}, - dataType: "script"}); - }, - loadDiff: function() { $(".dashboard-loader").show(); @@ -52,7 +33,7 @@ var MergeRequest = { url: $(".merge-diffs-tab").attr("data-url"), complete: function(){ MergeRequest.diffs_loaded = true; - $(".merge-request-notes, .merge-request-commits").hide(); + $(".merge-request-notes").hide(); $(".dashboard-loader").hide()}, dataType: "script"}); } diff --git a/app/assets/javascripts/note.js b/app/assets/javascripts/note.js index c791623b..41759671 100644 --- a/app/assets/javascripts/note.js +++ b/app/assets/javascripts/note.js @@ -1,49 +1,66 @@ var NoteList = { +notes_path: null, +target_params: null, +target_id: 0, +target_type: null, first_id: 0, last_id: 0, -resource_name: null, +disable:false, init: - function(resource_name, first_id, last_id) { - this.resource_name = resource_name; - this.first_id = first_id; - this.last_id = last_id; + function(tid, tt, path) { + this.notes_path = path + ".js"; + this.target_id = tid; + this.target_type = tt; + this.target_params = "&target_type=" + this.target_type + "&target_id=" + this.target_id; + + // get notes + this.getContent(); + + // get new notes every n seconds this.initRefresh(); - this.initLoadMore(); + + $('.delete-note').live('ajax:success', function() { + $(this).closest('li').fadeOut(); }); + + $("#new_note").live("ajax:before", function(){ + $("#submit_note").attr("disabled", "disabled"); + }) + + $("#new_note").live("ajax:complete", function(){ + $("#submit_note").removeAttr("disabled"); + }) + + $("#note_note").live("click", function(){ + $(this).css("height", "100px"); + $('.attach_holder').show(); + }); + }, -getOld: + +/** + * Load new notes to fresh list called 'new_notes_list': + * - Replace 'new_notes_list' with new list every n seconds + * - Append new notes to this list after submit + */ + +initRefresh: function() { - $('.loading').show(); - $.ajax({ - type: "GET", - url: location.href, - data: "first_id=" + this.first_id, - complete: function(){ $('.loading').hide()}, - dataType: "script"}); - }, - -append: - function(id, html) { - this.first_id = id; - $("#notes-list").append(html); - this.initLoadMore(); + // init timer + var intNew = setInterval("NoteList.getNew()", 10000); }, replace: - function(fid, lid, html) { - this.first_id = fid; - this.last_id = lid; - $("#notes-list").html(html); - this.initLoadMore(); + function(html) { + $("#new_notes_list").html(html); }, prepend: function(id, html) { if(id != this.last_id) { - this.last_id = id; - $("#notes-list").prepend(html); + $("#new_notes_list").prepend(html); } }, @@ -52,8 +69,8 @@ getNew: // refersh notes list $.ajax({ type: "GET", - url: location.href, - data: "last_id=" + this.last_id, + url: this.notes_path, + data: "last_id=" + this.last_id + this.target_params, dataType: "script"}); }, @@ -62,25 +79,85 @@ refresh: // refersh notes list $.ajax({ type: "GET", - url: location.href, - data: "first_id=" + this.first_id + "&last_id=" + this.last_id, + url: this.notes_path, + data: "first_id=" + this.first_id + "&last_id=" + this.last_id + this.target_params, dataType: "script"}); }, -initRefresh: - function() { - // init timer - var intNew = setInterval("NoteList.getNew()", 15000); - var intRefresh = setInterval("NoteList.refresh()", 90000); + +/** + * Init load of notes: + * 1. Get content with ajax call + * 2. Set content of notes list with loaded one + */ + + +getContent: + function() { + $.ajax({ + type: "GET", + url: this.notes_path, + data: "?" + this.target_params, + complete: function(){ $('.status').removeClass("loading")}, + beforeSend: function() { $('.status').addClass("loading") }, + dataType: "script"}); }, +setContent: + function(fid, lid, html) { + this.last_id = lid; + this.first_id = fid; + $("#notes-list").html(html); + + // Init infinite scrolling + this.initLoadMore(); + }, + + +/** + * Paging for old notes when scroll to bottom: + * 1. Init scroll events with 'initLoadMore' + * 2. Load onlder notes with 'getOld' method + * 3. append old notes to bottom of list with 'append' + * + */ + + +getOld: + function() { + $('.loading').show(); + $.ajax({ + type: "GET", + url: this.notes_path, + data: "first_id=" + this.first_id + this.target_params, + complete: function(){ $('.status').removeClass("loading")}, + beforeSend: function() { $('.status').addClass("loading") }, + dataType: "script"}); + }, + +append: + function(id, html) { + if(this.first_id == id) { + this.disable = true; + } else { + this.first_id = id; + $("#notes-list").append(html); + } + }, + + initLoadMore: function() { - $(window).bind('scroll', function(){ - if($(window).scrollTop() == $(document).height() - $(window).height()){ - $(window).unbind('scroll'); + $(document).endlessScroll({ + bottomPixels: 400, + fireDelay: 1000, + fireOnce:true, + ceaseFire: function() { + return NoteList.disable; + }, + callback: function(i) { NoteList.getOld(); } - }); + }); } } diff --git a/app/assets/javascripts/projects.js b/app/assets/javascripts/pager.js similarity index 60% rename from app/assets/javascripts/projects.js rename to app/assets/javascripts/pager.js index 90de73a1..d42ae1e0 100644 --- a/app/assets/javascripts/projects.js +++ b/app/assets/javascripts/pager.js @@ -1,12 +1,14 @@ -var ProjectsList = { +var Pager = { limit:0, offset:0, + disable:false, init: function(limit) { this.limit=limit; this.offset=limit; this.initLoadMore(); + $('.loading').show(); }, getOld: @@ -22,21 +24,27 @@ var ProjectsList = { append: function(count, html) { - $(".tile").append(html); + $(".content_list").append(html); if(count > 0) { this.offset += count; - this.initLoadMore(); + } else { + this.disable = true; } }, initLoadMore: function() { - $(window).bind('scroll', function(){ - if($(window).scrollTop() == $(document).height() - $(window).height()){ - $(window).unbind('scroll'); + $(document).endlessScroll({ + bottomPixels: 400, + fireDelay: 1000, + fireOnce:true, + ceaseFire: function() { + return Pager.disable; + }, + callback: function(i) { $('.loading').show(); - ProjectsList.getOld(); + Pager.getOld(); } - }); + }); } } diff --git a/app/assets/javascripts/team.js b/app/assets/javascripts/team.js index e079a9e4..f4b04354 100644 --- a/app/assets/javascripts/team.js +++ b/app/assets/javascripts/team.js @@ -1,7 +1,7 @@ function backToMembers(){ - $("#team_member_new").hide("slide", { direction: "right" }, 150, function(){ + $("#new_team_member").hide("slide", { direction: "right" }, 150, function(){ $("#team-table").show("slide", { direction: "left" }, 150, function() { - $("#team_member_new").remove(); + $("#new_team_member").remove(); $(".add_new").show(); }); }); diff --git a/app/assets/javascripts/tree.js b/app/assets/javascripts/tree.js index 2e9bcc82..1c62751a 100644 --- a/app/assets/javascripts/tree.js +++ b/app/assets/javascripts/tree.js @@ -5,21 +5,24 @@ var Tree = { init: function() { - (new Image).src = "ajax-loader-facebook.gif"; - - $('#tree-slider td.tree-item-file-name a, #tree-breadcrumbs a').live("click", function() { - history.pushState({ path: this.path }, '', this.href) + $('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live("click", function() { $("#tree-content-holder").hide("slide", { direction: "left" }, 150) }) - $("#tree-slider tr.tree-item").live('click', function(e){ + $('.project-refs-form').live({ + "ajax:beforeSend": function() { + $("#tree-content-holder").hide("slide", { direction: "left" }, 150); + } + }) + + $("#tree-slider .tree-item").live('click', function(e){ if(e.target.nodeName != "A") { - link = $(this).find("td.tree-item-file-name a"); + link = $(this).find(".tree-item-file-name a"); link.trigger("click"); } }); - $('#tree-slider td.tree-item-file-name a, #tree-breadcrumbs a').live({ + $('#tree-slider .tree-item-file-name a, .breadcrumb a, .project-refs-form').live({ "ajax:beforeSend": function() { $('.tree_progress').addClass("loading"); }, "ajax:complete": function() { $('.tree_progress').removeClass("loading"); } }); diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 5a1fb42f..3d809b56 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -7,5 +7,5 @@ *= require jquery-ui/jquery.tagify *= require chosen *= require_self - *= require common + *= require main */ diff --git a/app/assets/stylesheets/commits.css.scss b/app/assets/stylesheets/commits.css.scss deleted file mode 100644 index b1fa9c18..00000000 --- a/app/assets/stylesheets/commits.css.scss +++ /dev/null @@ -1,191 +0,0 @@ -/* Commit Page */ -body.project-page.commits-page .commit-info{float: right;} -body.project-page.commits-page .commit-info data{ - padding: 4px 10px; - font-size: 11px; -} -body.project-page.commits-page .commit-info data.commit-button{ - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4)); - background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4); - background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4); - background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4); - box-shadow: 0 -1px 0 white inset; - display: block; - border: 1px solid #eee; - border-radius: 5px; - margin-bottom: 2px; - position: relative; - padding-right: 20px; -} - -body.project-page.commits-page .commit-button i{ - background: url('images.png') no-repeat -138px -27px; - width: 6px; - height: 9px; - float: right; - position: absolute; - top: 6px; - right: 5px; -} -body.project-page.commits-page .commits-date {display: block; width: 100%; margin-bottom: 20px} -body.project-page.commits-page .commits-date .data {padding: 0} -body.project-page.commits-page a.commit{padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} -body.project-page.commits-page .commits-date a.commit {padding: 10px; border-bottom: none; overflow: hidden; display: block;} -body.project-page.commits-page .commits-date a.commit:last-child{border-bottom: 0} -body.project-page.commits-page .commits-date a.commit img{float: left; margin-right: 10px;} -body.project-page.commits-page .commits-date a.commit span.commit-title{display: block;} -body.project-page.commits-page .commits-date a.commit span.commit-title{margin-bottom: 10px} -body.project-page.commits-page .commits-date a.commit span.commit-author{color: #999; font-weight: normal; font-style: italic;} -body.project-page.commits-page .commits-date a.commit span.commit-author strong{font-weight: bold; font-style: normal;} - -/* eo Commit Page */ -/** Commit diff view **/ -.diff_file { - border:1px solid #CCC; - margin-bottom:1em; - - .diff_file_header { - padding:5px 5px; - border-bottom:1px solid #CCC; - background: #eee; - } - .diff_file_content { - overflow:auto; - overflow-y:hidden; - background:#fff; - color:#333; - font-size: 12px; - font-family: 'Courier New', 'andale mono','lucida console',monospace; - } - .diff_file_content_image { - background:#eee; - text-align:center; - img { - padding:100px; - max-width:300px; - } - } -} - -.diff_file_content{ - table { - border:none; - margin:0px; - padding:0px; - } - .old_line, .new_line { - margin:0px; - padding:0px; - border:none; - background:#F7F7F7; - color:#aaa; - padding: 0px 5px; - border-right: 1px solid #ccc; - text-align:right; - min-width:35px; - max-width:35px; - width:35px; - a { - float:left; - width:35px; - font-weight:normal; - color:#aaa; - &:hover { - text-decoration:underline; - } - } - } - .line_content { - white-space:pre; - height:14px; - margin:0px; - padding:0px; - border:none; - &.new { - background: #DFD; - } - &.old { - background: #FDD; - } - } -} - -pre.commit_message { - white-space: pre-wrap; - font-family: "Helvetica", sans-serif; - color: #555; - font-weight:bold; - font-size:15px; -} - -/** COMMIT BLOCK **/ -.commit-title{display: block;} -.commit-title{margin-bottom: 10px} -.commit-author{color: #999; font-weight: normal; font-style: italic;} -.commit-author strong{font-weight: bold; font-style: normal;} - -/** bordered list **/ -ul.bordered-list { - margin:5px 0px; - padding:0px; - li { - padding: 5px 0; - border-bottom: 1px solid #EEE; - overflow: hidden; - display: block; - margin:0px; - } -} - -ul.bordered-list li:last-child { border:none } - -.line_holder { - &:hover { - td { - background: #FFFFCF !important; - } - } -} - -.per_line_form { - font-family: "Helvetica", sans-serif; - background: #2FA0BB; - - td { - padding:0; - } - - form { - margin:5px; - width: 756px; - border: 1px solid #CCC; - padding: 20px; - background: white; - } -} - - -tr.line_notes_row { - font-family: "Helvetica", sans-serif; - &:hover { - background:none; - } - td { - margin:0px; - padding:0px; - border-bottom:1px solid #DEE2E3; - - - ul { - display:block; - list-style:none; - margin:0px; - padding:0px; - - li { - border-top:1px solid #DEE2E3; - padding:10px; - } - } - } -} diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 4c6544a4..5670f1e0 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -1,55 +1,53 @@ -$text_color:#222; -$lite_text_color: #666; -$link_color:#111; -$active_link_color:#2FA0BB; -$active_bg_color:#79C3E0; -$active_bd_color: #2FA0BB; -$border_color:#CCC; -$lite_border_color:#EEE; -$app_width:980px; -$app_padding:20px; -$bg_color: #FFF; -$styled_border_color: #2FA0BB; +a { + color: $link_color; + &:hover { + text-decoration:none; + color: $style_color; + } -/** MIXINS **/ -@mixin round-borders-bottom($radius) { - border-top: 1px solid #eaeaea; - -moz-border-radius-bottomright: $radius; - -moz-border-radius-bottomleft: $radius; - border-bottom-right-radius: $radius; - border-bottom-left-radius: $radius; - -webkit-border-bottom-left-radius: $radius; - -webkit-border-bottom-right-radius: $radius; + &.btn { + color: $style_color; + } } -@mixin round-borders-top($radius) { - border-top: 1px solid #eaeaea; - -moz-border-radius-topright: $radius; - -moz-border-radius-topleft: $radius; - border-top-right-radius: $radius; - border-top-left-radius: $radius; - -webkit-border-top-left-radius: $radius; - -webkit-border-top-right-radius: $radius; +.vlink { + color: $link_color !important; } -@mixin round-borders-all($radius) { - border: 1px solid #eaeaea; - -moz-border-radius: $radius; - -webkit-border-radius: $radius; - border-radius: $radius; +.pills a:hover { + background-color:#ccc; +} + +.pills .active a { + background-color: #aaa; +} + +.label { + background-color: #474D57; +} + +.tabs > li > a, .pills > li > a { + color:$style_color; +} + +.diff_file_header a, +.file_stats a { + color:$style_color; } /** COLORS **/ .cgray { color:gray; } .cred { color:#D12F19; } .cgreen { color:#44aa22; } +.cblack { color:#111; } +.cwhite { color:#fff !important } /** COMMON STYLES **/ .left { float:left; } .right { - float:right; + float:right !important; } .width-50p{ width:50%; @@ -78,38 +76,559 @@ $styled_border_color: #2FA0BB; .no-borders { border:none; } +table.no-borders { + border:none; + tr, td { border:none } +} .no-padding { padding:0 !important; } +.underlined { + border-bottom: 1px solid $border_color; +} -/* General */ +/** LAYOUT **/ -body.collapsed { - background-color: $bg_color; +.container { + width:$min_app_width; + padding-top:0; + z-index:5; +} - #container{ - margin: auto; - margin-top:51px; - width: $app_width; - border-top: 0; - background-color: $bg_color; +.container .content { + margin:0 $app_padding; +} + +.container .sidebar { + width: 200px; + height:100%; + min-height:450px; + float:right; +} + +img.avatar { + float:left; + margin-right:15px; + width:40px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +img.lil_av { + padding-left: 5px; + position: relative; + top: 3px; +} + +.media-grid { + h3, h2 , h4 { + &.media_h { + padding-left:10px; + float:left; + } } } -a { - color: $link_color; +.wll { + background-color: #FFF; + padding: 10px 5px; + min-height: 20px; + border-bottom: 1px solid #eee; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); + cursor:pointer; + &:hover { + background:$hover; + } + &:last-child { border:none } + p { padding-top:5px; margin:0; color:$style_color;} + .author { color: #999; } + p { + color:#222; + margin-bottom: 0; + img { + position:relative; + top:3px; + } + } } -@import "style.scss"; -@import "projects.css.scss"; -@import "commits.css.scss"; -@import "notes.css.scss"; -@import "merge_requests.css.scss"; -@import "highlight.css.scss"; -@import "highlight.black.css.scss"; -@import "issues.css.scss"; -@import "commits.css.scss"; +.visible_link, +.author_link { + color: $link_color; +} +.entry { + position: relative; + padding: 7px 15px; + margin-bottom: 18px; + color: #404040; + filter:none; -@import "top_panel.scss"; -@import "dashboard.scss"; -@import "tree.scss"; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + + background:#F1F1F1; + border: 1px solid #ccc; + + + p { + color:$style_color; + margin-bottom: 0; + img { + position:relative; + top:3px; + } + } +} + +.widget { + @include shade; + padding:20px; + margin-bottom:20px; + border: 1px solid #DDD; + border-radius: 5px; + background:#fafafa; + + .link_holder { + background:#eee; + position:relative; + left:-20px; + top:20px; + padding:10px 20px; + width:100%; + border-top:1px solid #ccc; + + a { + font-size:14px; + color:#666; + } + } +} + + +.ui-box { + margin-bottom: 40px; + @include round-borders-all(4px); + @include shade; + border-color:#ddd; + + ul { + margin:0; + } + + h5, .title { + padding: 0 10px; + background:#f5f5f5; + border-bottom: 1px solid #eee; + @include round-borders-top(4px); + border-top:none; + + form { + padding-top:16px; + } + } + + .row_title { + font-weight:bold; + color:#444; + &:hover { + text-decoration:underline; + } + } + + li, .wll { + padding:10px; + &:first-child { + @include round-borders-top(4px); + border-top:none; + } + + &:last-child { + @include round-borders-bottom(4px); + border:none; + } + } + +} + +.help li { color:#111 } + +.back_link { + text-decoration:underline; + font-size:14px; + font-weight:bold; + padding:10px 0; + padding-bottom:0; +} + +.info_link { + margin-right:5px; + float:left; + + img { + width:20px; + } +} + +.borders { + border: 1px solid #ccc; + @include shade; +} + +.download_repo_link { + background: url("images.png") no-repeat 0 -48px; + padding-left:20px; +} + +.number { + border-radius: 4px; + text-shadow: none; + background: rgba(0,0,0,.12); + text-align: center; + padding: 2px 4px; + line-height:20px; + margin-left:2px; +} + +table a code { + position: relative; + top: -2px; + margin-right: 3px; +} + +.span12 hr{ + margin-top: 5px; +} + +.btn.padded { + margin-right:3px; +} + +.loading { + margin:20px auto; + background: url(ajax-loader-facebook.gif) no-repeat center center; + width:40px; + height:40px; +} + +/** FLASH message **/ +#flash_container { + height:45px; + position:fixed; + z-index:10001; + top:0px; + width:100%; + margin-bottom:15px; + overflow:hidden; + background:white; + cursor:pointer; + border-bottom:1px solid #777; + + h4 { + color:#444; + font-size:22px; + padding-top:5px; + margin:2px; + } +} + +.git_url_wrapper { + margin-right:50px +} +.file_stats { + span { + img { + width:14px; + float:left; + margin-right:6px; + padding:2px 0; + } + } +} + +.handle:hover { + cursor:move; +} + +span.update-author { + display:block; +} +span.update-author { + color:#999; + font-weight:normal; + font-style:italic; +} +span.update-author strong { + font-weight:bold; + font-style: normal; +} + +/** UPDATE ITEM **/ +span.update-author { + display:block; +} +/** END UPDATE ITEM **/ +.ajax-tab-loading { + padding:40px; + display:none; +} +.dashboard-loader { + float:left; + margin:10px; + display:none; +} +.user-mention { + color:#2FA0BB; + font-weight:bold; +} + +a.project-update.titled { + position:relative; + padding-left:35% !important; + .title-block { + padding:10px; + width:35%; + position:absolute; + left:0; + top:0; + } +} +/** + * Project graph + */ +#holder { + cursor: move; + height: 70%; + overflow: hidden; +} + + + +input.git_clone_url { + width:475px; +} + +.team_member_row { + img { + width:60px; + } +} + +.merge-request-form-holder { + select { + width:300px; + } +} + +/** Issues **/ +#issue_assignee_id { + width:300px; +} + +#new_issue_dialog textarea{ + height: 100px; +} + +.project_list_url { + width:250px; + background:#fff !important; +} + +.project_tile { + @include shade; + @include round-borders-all(4px); + margin-bottom:20px; + width:298px; + float:left; + margin-left:20px; + border: 1px solid #DDD; + padding-bottom:20px; + + .title { + background:#f5f5f5; + padding: 5px 10px 2px 20px; + border-bottom: 1px solid #DDD; + margin-bottom: 15px; + + h3 { + &:hover { + text-decoration: underline; + } + } + } + .data { + margin: 0 20px; + } + .buttons { + margin: 0 20px; + } +} + +/** + * + * COMMIT SHOw + * + */ +.diff_file { + border:1px solid #CCC; + margin-bottom:1em; + + .diff_file_header { + padding:5px 5px; + border-bottom:1px solid #CCC; + background: #eee; + } + .diff_file_content { + overflow:auto; + overflow-y:hidden; + background:#fff; + color:#333; + font-size: 12px; + font-family: 'Menlo', 'Courier New', 'andale mono','lucida console',monospace; + } + .diff_file_content_image { + background:#eee; + text-align:center; + img { + padding:100px; + max-width:300px; + } + } +} + +.diff_file_content{ + table { + border:none; + margin:0px; + padding:0px; + tr { + td { + font-size:12px; + } + } + } + .old_line, .new_line { + margin:0px; + padding:0px; + border:none; + background:#F7F7F7; + color:#aaa; + padding: 0px 5px; + border-right: 1px solid #ccc; + text-align:right; + min-width:35px; + max-width:35px; + width:35px; + moz-user-select: none; + -khtml-user-select: none; + user-select: none; + a { + float:left; + width:35px; + font-weight:normal; + color:#aaa; + &:hover { + text-decoration:underline; + } + } + } + .line_content { + white-space:pre; + height:14px; + margin:0px; + padding:0px; + border:none; + &.new { + background: #CFD; + } + &.old { + background: #FDD; + } + &.matched { + color:#ccc; + background:#fafafa; + } + } +} + +/** COMMIT BLOCK **/ +.commit-title{display: block;} +.commit-title{margin-bottom: 10px} +.commit-author, .commit-committer{display: block;color: #999; font-weight: normal; font-style: italic;} +.commit-author strong, .commit-committer strong{font-weight: bold; font-style: normal;} + +/** bordered list **/ +ul.bordered-list { + margin:5px 0px; + padding:0px; + li { + padding: 5px 0; + border-bottom: 1px solid #EEE; + overflow: hidden; + display: block; + margin:0px; + } +} + +ul.bordered-list li:last-child { border:none } + +.line_holder { + &:hover { + td { + background: #FFFFCF !important; + } + } +} + +li.commit { + .avatar { + width:24px; + top:-3px; + margin-right:10px; + margin-left:10px; + } + + code { + padding:4px; + } +} +p.time { + color: #999; + font-size: 90%; + margin: 30px 3px 3px 2px; +} + + +.dashboard_category { + margin-bottom:30px; + + .dashboard_block { + width:700px; + margin:auto; + + .wll { + border:none; + &:hover { + background:none; + } + + h4 { + color:#666; + } + } + } +} + +.event_feed { + ul { + margin-left:50px; + } +} diff --git a/app/assets/stylesheets/dashboard.scss b/app/assets/stylesheets/dashboard.scss deleted file mode 100644 index 5e38fcc6..00000000 --- a/app/assets/stylesheets/dashboard.scss +++ /dev/null @@ -1,30 +0,0 @@ -body.dashboard-page h2.icon span{ background-position: 9px -69px; } -body.dashboard-page header{margin-bottom: 0} -body.dashboard-page .news-feed{margin-left: 285px; min-height: 600px; margin-top: 20px; margin-right:2px; padding:20px;} -body.dashboard-page .dashboard-content{ position: relative; float: left; width: 100%; height: 100%; } -body.dashboard-page .news-feed h2{float: left;} - -body.dashboard-page aside{ - min-height: 820px; position: relative; top: 0; bottom: 0; right: 0; width: 260px; float: left; border-right: 1px solid $border_color; padding:20px; padding-right:0; - h4{margin: 0; border-bottom: 1px solid #ccc; padding: 20px 20px 20px 0px; font-size: 11px; font-weight: bold; text-transform: uppercase;} - h4 a.button-small{float: right; text-transform: none; border-radius: 4px; margin-right: 2%; margin-top: -4px; display: block;} - .project-list {list-style: none; margin: 0; padding: 0;} - .project-list li a {background: white; color: #{$blue_link}; display: block; border-bottom: 1px solid $lite_border_color; padding: 14px 6% 14px 0px;} - .project-list li a span.project-name{font-size: 14px; display: block; margin-bottom: 8px} - .project-list li a span.time{color: #666; font-weight: normal; font-size: 11px} - .project-list li a span.arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999} -} - -body.dashboard-page .news-feed .project-updates { - margin-bottom: 20px; display: block; width: 100%; - .data{ padding: 0} - a.project-update {padding: 10px; overflow: hidden; display: block;} - a.project-update:last-child{border-bottom: 0} - a.project-update img{float: left; margin-right: 10px;} - a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} - a.project-update span.update-title{margin-bottom: 10px} - a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;} - a.project-update span.update-author strong{font-weight: bold; font-style: normal;} -} -/* eo Dashboard Page */ - diff --git a/app/assets/stylesheets/highlight.black.css.scss b/app/assets/stylesheets/highlight.black.scss similarity index 99% rename from app/assets/stylesheets/highlight.black.css.scss rename to app/assets/stylesheets/highlight.black.scss index e094e48f..e63e08c8 100644 --- a/app/assets/stylesheets/highlight.black.css.scss +++ b/app/assets/stylesheets/highlight.black.scss @@ -1,5 +1,6 @@ .black .highlighttable { background: #333; + td.linenos { border:none; } pre { color: #eee } .highlight { background: #333; border-left:1px solid #555; } diff --git a/app/assets/stylesheets/highlight.css.scss b/app/assets/stylesheets/highlight.scss similarity index 92% rename from app/assets/stylesheets/highlight.css.scss rename to app/assets/stylesheets/highlight.scss index d65865ec..0dbfc0ed 100644 --- a/app/assets/stylesheets/highlight.css.scss +++ b/app/assets/stylesheets/highlight.scss @@ -10,13 +10,15 @@ table.highlighttable margin:0px; padding:0px; font-size:12px; - table-layout:fixed + table-layout:fixed; + background: #F7F7F7; } td.code, td.linenos{ padding:0; margin:0; + border-top:0; vertical-align:top; } @@ -24,8 +26,16 @@ td.linenos{ background:none; padding:10px 0px 0px 10px; margin-left:0px; + border-left: 1px solid #DEE2E3; + background: white; } + +.linenodiv pre, .highlight pre{ + margin:0; + padding:0; + background:none; + border:none; } .linenodiv pre { @@ -48,7 +58,7 @@ td.code .highlight { table.highlighttable pre{ padding:0; margin:0; - font-family: 'Courier New', 'andale mono','lucida console',monospace; + font-family: 'Menlo', 'Courier New', 'andale mono','lucida console',monospace; color: #333; text-align:left; } @@ -62,7 +72,7 @@ table.highlighttable pre{ padding:0; line-height:2.0; margin:0; - font-family: 'Courier New', 'andale mono','lucida console',monospace; + font-family: 'Menlo', 'Courier New', 'andale mono','lucida console',monospace; color: #333; text-align:left;} } diff --git a/app/assets/stylesheets/issues.css.scss b/app/assets/stylesheets/issues.css.scss deleted file mode 100644 index d2341edc..00000000 --- a/app/assets/stylesheets/issues.css.scss +++ /dev/null @@ -1,84 +0,0 @@ -.issue-number { - float: left; - border-radius: 5px; - text-shadow: none; - background: rgba(0, 0, 0, 0.12); - text-align: center; - padding: 14px 8px; - width: 40px; - margin-right: 10px; - color: #444; -} - -.issues_filter { - margin:10px 0; - .left { - margin-right:15px; - } -} - -.top_panel_issues{ - #issue_search_form { - margin:5px 0; - input { - border:1px solid #D3D3D3; - padding: 3px; - height: 28px; - width: 250px; - -webkit-appearance:none; - box-sizing: border-box; - -moz-box-sizing: border-box; - - &:focus { - border-color:#c2e1ef; - } - } - } -} - -/** ISSUES LIST **/ -.issue .action-links { - display:none; - a { - margin-left:10px; - } -} -.issue:hover .action-links { display:block; } -.issue-show-holder { - width:100%; - .data p { font-size:16px } -} - -#issue_assignee_id { - width:300px; -} - -.issue-form-holder .ui-box .data { - margin: 0; - padding: 0; -} - -body.project-page .merge-request-form-holder table.no-borders tr, -body.project-page .merge-request-form-holder table.no-borders td, -body.project-page .issue-form-holder table.no-borders tr, -body.project-page .issue-form-holder table.no-borders td, -body.project-page .new_snippet table tr, -body.project-page .new_snippet table td, -body.project-page .edit_snippet table tr, -body.project-page .edit_snippet table td -{ - &:hover { - background:none; - } -} - - -#issues-table { - tr { - border-top: 1px solid $lite_border_color; - &:first-child { - border:none; - } - } - -} diff --git a/app/assets/stylesheets/login.scss b/app/assets/stylesheets/login.scss new file mode 100644 index 00000000..3bba7062 --- /dev/null +++ b/app/assets/stylesheets/login.scss @@ -0,0 +1,44 @@ +/* Login Page */ +body.login-page{ + padding-top: 10%; + background:#f1f1f1; +} + +.login-box{ + width: 304px; + position: relative; + border-radius: 5px; + margin: auto; + padding: 20px; + background: white; +} + +.login-box .login-logo{ + margin: 10px 0 30px 0; + display: block; +} + +.login-box input.text{background-color: #f1f1f1; font-size: 16px; border-radius: 0; padding: 14px 10px; width: 280px} + +.login-box input.text.top{ + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + +.login-box input.text.bottom{ + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; + border-top: 0; + margin-bottom: 20px; +} + +.login-box a.forgot{float: right; padding-top: 6px} + diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss new file mode 100644 index 00000000..58818809 --- /dev/null +++ b/app/assets/stylesheets/main.scss @@ -0,0 +1,118 @@ +@import "bootstrap"; + +/** GITLAB colors **/ +$text_color:#222; +$lite_text_color: #666; +$link_color:#2A79A3; +$active_link_color:#2FA0BB; +$active_bg_color:#79C3E0; +$active_bd_color: #2FA0BB; +$border_color:#CCC; +$lite_border_color:#EEE; +$min_app_width:980px; +$max_app_width:980px; +$app_padding:20px; +$bg_color: #FFF; +$styled_border_color: #2FA0BB; +$color: "#4BB8D2"; +$blue_link: "#2fa0bb"; + + +/** Style colors **/ +$style_color: #474D57; +$hover: #FDF5D9; + + +/** MIXINS **/ +@mixin shade { + -moz-box-shadow: 0 0 3px #ddd; + -webkit-box-shadow: 0 0 3px #ddd; + box-shadow: 0 0 3px #ddd; +} + + +@mixin round-borders-bottom($radius) { + border-top: 1px solid #eaeaea; + -moz-border-radius-bottomright: $radius; + -moz-border-radius-bottomleft: $radius; + border-bottom-right-radius: $radius; + border-bottom-left-radius: $radius; + -webkit-border-bottom-left-radius: $radius; + -webkit-border-bottom-right-radius: $radius; +} + +@mixin round-borders-top($radius) { + border-top: 1px solid #eaeaea; + -moz-border-radius-topright: $radius; + -moz-border-radius-topleft: $radius; + border-top-right-radius: $radius; + border-top-left-radius: $radius; + -webkit-border-top-left-radius: $radius; + -webkit-border-top-right-radius: $radius; +} + +@mixin round-borders-all($radius) { + border: 1px solid #eaeaea; + -moz-border-radius: $radius; + -webkit-border-radius: $radius; + border-radius: $radius; +} + +/** + * This file represent some UI that can be changed + * during web app restyle or theme select. + * + * Next items should be placed there + * - link colors + * - header styles + * - main menu styles + * + */ +@import "ui_basic.scss"; + +/** + * UI mars theme + */ +@import "ui_mars.scss"; + +/** + * Most of application styles placed here. + * This file represent common UI that should not be changed between themes + * or project restyling like form width or user avatar class or commit title + * + * TODO: clean it + */ +@import "common.scss"; + +/** + * This scss file redefine chozen selectbox styles for + * project Branch/Tag select element + */ +@import "ref_select.scss"; + +/** + * Code (files list) styles. Browsing project files there + */ +@import "tree.scss"; + +/** + * This file represent notes(comments) styles + */ +@import "notes.scss"; + +/** + * Devise styles + */ +@import "login.scss"; + +/** + * CODE HIGHTLIGHT BASE + * + */ +@import "highlight.scss"; + +/** + * CODE HIGHTLIGHT DARK schema + * + */ +@import "highlight.black.scss"; diff --git a/app/assets/stylesheets/merge_requests.css.scss b/app/assets/stylesheets/merge_requests.css.scss deleted file mode 100644 index 2b60605b..00000000 --- a/app/assets/stylesheets/merge_requests.css.scss +++ /dev/null @@ -1,10 +0,0 @@ -// Place all the styles related to the MergeRequests controller here. -// They will automatically be included in application.css. -// You can use Sass (SCSS) here: http://sass-lang.com/ - - -.merge-request-form-holder { - select { - width:300px; - } -} diff --git a/app/assets/stylesheets/notes.css.scss b/app/assets/stylesheets/notes.css.scss deleted file mode 100644 index 4aba53cf..00000000 --- a/app/assets/stylesheets/notes.css.scss +++ /dev/null @@ -1,52 +0,0 @@ -/** Notes **/ - -#notes-list { - display:block; - list-style:none; - margin:0px; - padding:0px; -} - -.issue_notes { - .note_content { - float:left; - width:400px; - } -} - -/* Note textare */ -#note_note { - height:100px; - width:97%; - font-size:14px; -} - -#new_note { - #note_note { - height:25px; - } - .attach_holder { - display:none; - } -} - -#notes-list .note .delete-note { display:none; } -#notes-list .note:hover .delete-note { display:block; } - -body.project-page #notes-list .note {padding: 10px 0; border-bottom: 1px solid #eee; overflow: hidden; display: block;} -body.project-page #notes-list .note img{float: left; margin-right: 10px;} -body.project-page #notes-list .note span.note-title{display: block;} -body.project-page #notes-list .note span.note-title{margin-bottom: 10px} -body.project-page #notes-list .note span.note-author{color: #999; font-weight: normal; font-style: italic;} -body.project-page #notes-list .note span.note-author strong{font-weight: bold; font-style: normal;} - - -.note .note-title { margin-left:55px; } - -p.notify_controls input{ - margin: 5px; -} - -p.notify_controls span{ - font-weight: 700; -} diff --git a/app/assets/stylesheets/notes.scss b/app/assets/stylesheets/notes.scss new file mode 100644 index 00000000..1f05d13b --- /dev/null +++ b/app/assets/stylesheets/notes.scss @@ -0,0 +1,121 @@ +/** + * Notes + * + */ +#notes-list, +#new_notes_list { + display:block; + list-style:none; + margin:0px; + padding:0px; +} + +#new_notes_list li:last-child{ + border-bottom:1px solid #aaa; +} + +.issue_notes { + .note_content { + float:left; + width:400px; + } +} + +/* Note textare */ +#note_note { + height:100px; + width:97%; + font-size:14px; +} + +#new_note { + #note_note { + height:25px; + } + .attach_holder { + display:none; + } +} + +.note .delete-note { + display:none; + float:right; +} +.note:hover .delete-note { display:block; } +.note {padding: 10px 0; border-bottom: 1px solid #eee; overflow: hidden; display: block;} +.note img{float: left; margin-right: 10px;} +.note span.note-title{display: block;} +.note span.note-title{margin-bottom: 10px} +.note span.note-author{color: #999; font-weight: normal; font-style: italic;} +.note span.note-author strong{font-weight: bold; font-style: normal;} +.note p { color:$style_color; } +.note .note-author { color: $style_color;} + +.note .note-title { margin-left:55px; } + +p.notify_controls input{ + margin: 5px; +} + +p.notify_controls span{ + font-weight: 700; +} + +tr.line_notes_row { + border-bottom:1px solid #DDD; + &.reply { + background:#eee; + + td { + padding:7px 10px; + } + a.line_note_reply_link { + @include round-borders-all(4px); + border-color:#aaa; + background: #bbb; + padding: 3px 20px; + color: white; + } + } + ul { + margin:0; + li { + padding:0; + border:none; + } + } +} + +.line_notes_row, .per_line_form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } + +.per_line_form { + background:#f5f5f5; + form { margin: 0; } + td { + border-bottom:1px solid #ddd; + } +} + +td .line_note_link { + position:absolute; + margin-left:-70px; + margin-top:-10px; + z-index:10; + background: url("comment_add.png") no-repeat left 0; + width:32px; + height:32px; + + opacity: 0.0; + filter: alpha(opacity=0); + + &:hover { + opacity: 1.0; + filter: alpha(opacity=100); + } +} + +.diff_file_content tr.line_holder:hover > td { background: $hover !important; } +.diff_file_content tr.line_holder:hover > td .line_note_link { + opacity: 1.0; + filter: alpha(opacity=100); +} diff --git a/app/assets/stylesheets/projects.css.scss b/app/assets/stylesheets/projects.css.scss deleted file mode 100644 index c9bba0c1..00000000 --- a/app/assets/stylesheets/projects.css.scss +++ /dev/null @@ -1,572 +0,0 @@ -body.project-page h2.icon .project-name, body.project-page h2.icon d{border: 1px solid #eee; padding: 5px 30px 5px 10px; border-radius: 5px; position: relative;} -body.project-page h2.icon .project-name i.arrow{float: right; - position: absolute; - right: 10px; - top: 13px; - display: block; - background: url('images.png') no-repeat -97px -29px; - width: 4px; - height: 5px; -} - -body.project-page h2.icon span{ background-position: -78px -68px; } -body.project-page .project-container{ position: relative; float: left; width: 100%; height: 100%; padding-bottom: 10px;} -body.project-page .page-title{margin-bottom: 0} - -body.project-page .project-sidebar { - width: 110px; - left: 0; - top: 0; - height: 100%; - bottom: 0; - position: absolute; - float: left; - display: inline-block; - background: #FFF; - padding: $app_padding; - padding-right:0px; - margin: 0; - border-right: 1px solid $border_color; -} - -body.projects-page input.text.git-url { font-size: 12px; border-radius: 5px; color: #666; box-shadow: 0 1px 2px rgba(0,0,0,.2) inset; padding: 8px 0 8px 30px; margin-bottom: 20px; background: white url('images.png') no-repeat 8px -40px; width: 136px} -body.projects-page input.text.git-url {margin:10px 0 0 } -.git_url_wrapper { margin-right:50px } - -.projects_selector:hover > .project-box{ -moz-box-shadow:0px 0px 10px rgba(0, 0, 0, .1); -webkit-box-shadow:0px 0px 10px rgba(0, 0, 0, .1); box-shadow:0px 0px 10px rgba(0, 0, 0, .1); } - - -/* New project Page */ -.new-project-page .container table{background: white} -body.project-page .project-sidebar aside{width: 109px} -body.project-page .project-sidebar aside a{ - display: block; - position: relative; - padding: 15px 10px; - margin: 10px 0 0 0; - - -} -body.project-page .project-sidebar aside a span.number{float: right; border-radius: 5px; text-shadow: none; background: rgba(0,0,0,.12); text-align: center; padding: 5px 8px; position: absolute; top: 10px; right: 10px} -body.project-page .project-sidebar aside a.current { - color: white; - background: $active_bg_color; - border: 1px solid $active_bd_color; - border-radius:5px; - - - -webkit-border-top-right-radius: 0; - -webkit-border-bottom-right-radius: 0; - -moz-border-radius-topright: 0px; - -moz-border-radius-bottomright: 0px; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - margin-right: -1px; -} -body.project-page .project-content{ padding: $app_padding; display: block; margin-left: 130px; min-height: 600px} -body.project-page .project-content h2{ margin-top: 6px} -body.project-page .project-content .button.right{margin-left: 20px} -body.project-page table .commit a{color: #{$blue_link}} -body.project-page table th, body.project-page table td{ border-bottom: 1px solid #DEE2E3;} -body.project-page .fixed{position: fixed; } - - - - -/** File stat **/ -.file_stats { - span { - img { - width:14px; - float:left; - margin-right: 6px; - padding:2px 0; - } - } -} - -.round-borders { - @include round-borders-all(4px); - padding: 4px 0px; -} - -table.round-borders { - float:left; - text-align: left; -} - - - -/** PROJECTS **/ -input.ssh_project_url { - padding:5px; - margin:0px; - float:right; - width:400px; - text-align:center; -} - -#projects-list .project { - height:50px; -} - -#tree-slider .tree-item, -#projects-list .project, -#snippets-table .snippet, -#issues-table .issue{ - cursor:pointer; -} - -.clear { - clear: both; -} - - -/** Buttons **/ -.lbutton, -.lite_button { - display:block; - float:left; - margin: 0px 5px 0px 0px; - padding:5px 10px; - - font-family:"Helvetica Neue", Arial, Helvetica, sans-serif; - border:1px solid #D3D3D3; - background:white; - font-size:12px !important; - line-height:130%; - text-decoration:none; - font-weight:bold; - color:#565656; - cursor:pointer; - - &:hover { - border:1px solid #C2E1EF; - color: #0099FF; - } - - &.hm { - margin: 0px 0px; - } - - &.vm { - margin: 5px 0px; - } -} - -#user_projects_limit{ - width: 60px; -} - -.handle:hover{ - cursor: move; -} - -.project-refs-form { - span { - background: none !important; - position:static !important; - width:auto !important; - height: auto !important; - } -} - -.project-refs-select { - width:200px; -} - -.filter .left { margin-right:15px; } - -body.project-page table .commit { - a.tree-commit-link { - color:#444; - &:hover { - text-decoration:underline; - } - } -} - -/** NEW PROJECT **/ -.new-project-hodler { - .icon span { background-position: -31px -70px; } - td { border-bottom: 1px solid #DEE2E3; } -} - -/** Feed entry **/ -.commit, -.snippet, -.message { - .title { - color:#666; - a { color:#666 !important; } - p { margin-top:0px; } - } - .author { color: #999 } -} - -/** JQuery UI **/ -.ui-autocomplete { @include round-borders-all(5px); } -.ui-menu-item { cursor: pointer } -.ui-selectmenu{ - @include round-borders-all(4px); - margin-right:10px; - font-size:1.5em; - height:auto; - font-weight:bold; - .ui-selectmenu-status { - padding:3px 10px; - } -} - -/** Snippets **/ -.new_snippet textarea, -.edit_snippet textarea { - height:300px; - padding: 8px; - width: 95%; -} -.snippet .action-links { - display:none; - a { - margin-left:10px; - } -} -.snippet:hover .action-links { display:block; } - -/** ISSUES TAGS **/ -.tag { - @include round-borders-all(4px); - padding:2px 4px; - border:none; - text-shadow:none; - - &.inline { - display:inline; - } - - &.high, &.closed { - background: #D12F19; - color:white; - } - - &.today, &.open { - background: #44aa22; - color:white; - } - - &.yours { - background: #4466cc; - color:white; - } - &.normal { - background: #2c5ca6; - color:white; - } - &.notes { - background: #2c5c66; - color:white; - } - &.note { - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); - color: #777; - border: 1px solid #DEDFE1; - } - &.issue { - background: #D12F19; - color:white; - } - &.commit { - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); - color: #777; - border: 1px solid #DEDFE1; - } -} - -#holder { - background:#FAFAFA; - border: 1px solid #EEE; - cursor: move; - height: 70%; - overflow: hidden; -} - -/* Project Dashboard Page */ -html, body { height: 100%; } - -body.dashboard.project-page .news-feed h2{float: left;} -body.dashboard.project-page .news-feed .project-updates {margin-bottom: 20px; display: block; width: 100%;} -body.dashboard.project-page .news-feed .project-updates .data{ padding: 0} -body.dashboard.project-page .news-feed .project-updates a.project-update {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} -body.dashboard.project-page .news-feed .project-updates a.project-update:last-child{border-bottom: 0} -body.dashboard.project-page .news-feed .project-updates a.project-update img{float: left; margin-right: 10px;} -body.dashboard.project-page .news-feed .project-updates a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} -body.dashboard.project-page .news-feed .project-updates a.project-update span.update-title{margin-bottom: 10px} -body.dashboard.project-page .news-feed .project-updates a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;} -body.dashboard.project-page .news-feed .project-updates a.project-update span.update-author strong{font-weight: bold; font-style: normal;} -/* eo Dashboard Page */ - - -/** Merge requests */ -body.project-page .merge-request-commits {margin-bottom: 20px; display: block; width: 100%;} -body.project-page .merge-request-commits .data{ padding: 0} -body.project-page .merge-request-commits a.commit {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} -body.project-page .merge-request-commits a.commit:last-child{border-bottom: 0} -body.project-page .merge-request-commits a.commit img{float: left; margin-right: 10px;} -body.project-page .merge-request-commits a.commit span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} -body.project-page .merge-request-commits a.commit span.update-title{margin-bottom: 10px} -body.project-page .merge-request-commits a.commit span.update-author{color: #999; font-weight: normal; font-style: italic;} -body.project-page .merge-request-commits a.commit span.update-author strong{font-weight: bold; font-style: normal;} - - -/** Update entry **/ -.update-data { padding: 0 } -.update-data { width:100%; } -.update-data.ui-box .data { padding:0; } -a.update-item {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} -a.update-item:last-child{border-bottom: 0} -a.update-item img{float: left; margin-right: 10px;} -a.update-item span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} -a.update-item span.update-title{margin-bottom: 10px} -a.update-item span.update-author{color: #999; font-weight: normal; font-style: italic;} -a.update-item span.update-author strong{font-weight: bold; font-style: normal;} - - -body.project-page .team_member_new .span-6, .team_member_edit .span-6{ padding:10px 0; } - -body.projects-page input.text.git-url.project_list_url { width:165px; } - - -body.project-page table.no-borders th { - background:none; - border-bottom:1px solid #CCC; - color:#333; -} - -body.project-page table.no-borders tr, -body.project-page table.no-borders td{ - border:none; -} - -.ajax-tab-loading { - padding:40px; - display:none; -} - -#tree-content-holder { float:left; width:100%; } - -#tree-readme-holder { - float:left; - width:100%; - - .readme { - @include round-borders-all(4px); - padding: 4px 15px; - background:#F7F7F7; - } -} - - - -/* Commit Page */ -.entity-info {float: right;} -.entity-button{ - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4)); - background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4); - background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4); - background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4); - box-shadow: 0 -1px 0 white inset; - display: block; - border: 1px solid #eee; - border-radius: 5px; - margin-bottom: 2px; - position: relative; - padding: 4px 10px; - font-size: 11px; - padding-right: 20px; -} - -.entity-button i{ - background: url('images.png') no-repeat -138px -27px; - width: 6px; - height: 9px; - float: right; - position: absolute; - top: 6px; - right: 5px; -} -.box-arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999; margin: 1.5em 0;} - -h4.dash-tabs { - margin: 0; - border-bottom: 1px solid #ccc; - padding: 10px 10px; - font-size: 11px; - padding-left:20px; - font-weight: bold; text-transform: uppercase; - background: #F7F7F7; - margin-bottom:20px; - height:13px; - -} - -.dash-button { - border-right: 1px solid #ddd; - background:none; - padding: 10px 15px; - float:left; - position:relative; - top:-10px; - left:0px; - height:13px; - - &:first-child { - border-left: 1px solid #ddd; - } - &.active { - background: #eaeaea; - } -} - - -.dashboard-loader { - float:right; - margin-right:30px; - display:none; -} - - -.merge-tabs { - margin: 0; - border: 1px solid #ccc; - padding: 5px; - font-size: 12px; - background: #F7F7F7; - margin-bottom:20px; - height:26px; - - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - border-radius: 4px; - - .tab { - font-weight: bold; - border-right: 1px solid #ddd; - background:none; - padding: 10px; - min-width:60px; - float:left; - position:relative; - top:-5px; - left:-5px; - height:16px; - padding-left:34px; - - span { - width: 20px; - height: 20px; - display: inline-block; - position: absolute; - left: 8px; - top: 8px; - } - - &.active { - background: #eaeaea; - } - } -} -.merge-tabs.repository .tab span{ background: url("images.png") no-repeat -38px -77px; } -.activities-tab span { background: url("images.png") no-repeat -161px -1px; } -.stat-tab span, -.team-tab span, -.snippets-tab span { background: url("images.png") no-repeat -38px -77px; } -.files-tab span { background: url("images.png") no-repeat -112px -23px; } - -.merge-notes-tab span { background: url("images.png") no-repeat -161px -1px; } -.merge-commits-tab span { background: url("images.png") no-repeat -86px 1px; } -.merge-diffs-tab span { background: url("images.png") no-repeat -118px 1px; } -.merge-tabs .dashboard-loader { padding:8px; } - -.user-mention { - color: #2FA0BB; - font-weight: bold; -} - -.author { - color: #999; -} - - -.red-button{ - border-radius: 5px; - font-size: 12px; - font-weight: bold; - padding: 5px 17px; - border: 1px solid #999; - color: #666; - display: inline-block; - box-shadow: 0 1px 2px rgba(0,0,0,.3); - background: #D12F19; - color: white; -} - -.positive-button{ - border-radius: 5px; - font-size: 12px; - font-weight: bold; - padding: 5px 17px; - border: 1px solid #999; - color: #666; - display: inline-block; - box-shadow: 0 1px 2px rgba(0,0,0,.3); - background: #4A2; - color: white; -} - - -.dark_scheme_box { - padding:20px 0; - - label { - float:left; - box-shadow: 0 0px 5px rgba(0,0,0,.3); - - img { - } - } -} - -a.project-update.titled { - position: relative; - padding-left: 235px !important; - - .title-block { - padding: 10px; - width: 205px; - position: absolute; - left: 0; - top: 0; - } -} - -.add_new { - float: right; - background: #A6B807; - color: white; - padding: 4px 10px; - @include round-borders-all(4px); - font-size:11px; - margin: 10px 0; -} - - - -.new-project-hodler { - padding:20px; -} diff --git a/app/assets/stylesheets/projects.css.scss~ b/app/assets/stylesheets/projects.css.scss~ new file mode 100644 index 00000000..4bdf5dee --- /dev/null +++ b/app/assets/stylesheets/projects.css.scss~ @@ -0,0 +1,385 @@ +.git_url_wrapper { margin-right:50px } + +.sidebar aside a{ + display: block; + position: relative; + padding: 15px 10px; + margin: 10px 0 0 0; + + font-size:13px; + font-weight:bold; + color:#333; + + &.current { + color: white; + background: $active_bg_color; + border: 1px solid $active_bd_color; + border-radius:5px; + + -webkit-border-top-right-radius: 0; + -webkit-border-bottom-right-radius: 0; + -moz-border-radius-topright: 0px; + -moz-border-radius-bottomright: 0px; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + margin-right: -1px; + } +} + +body table .commit a{color: #{$blue_link}} +body table th, body table td{ border-bottom: 1px solid #DEE2E3;} +body .fixed{position: fixed; } + +/** File stat **/ +.file_stats { + span { + img { + width:14px; + float:left; + margin-right: 6px; + padding:2px 0; + } + } +} + +.round-borders { + @include round-borders-all(4px); + padding: 4px 0px; +} + +table.round-borders { + float:left; + text-align: left; +} + + + +/** PROJECTS **/ +input.ssh_project_url { + padding:5px; + margin:0px; + float:right; + width:400px; + text-align:center; +} + +#projects-list .project { + height:50px; +} + +#tree-slider .tree-item, +#projects-list .project, +#snippets-table .snippet, +#issues-table .issue{ + cursor:pointer; +} + +.clear { + clear: both; +} + + + +#user_projects_limit{ + width: 60px; +} + +.handle:hover{ + cursor: move; +} + +.project-refs-form { + span { + background: none !important; + position:static !important; + width:auto !important; + height: auto !important; + } +} + +.project-refs-select { + width:200px; +} + +.filter .left { margin-right:15px; } + +body table .commit { + a.tree-commit-link { + color:#444; + &:hover { + text-decoration:underline; + } + } +} + +/** NEW PROJECT **/ +.new-project-hodler { + .icon span { background-position: -31px -70px; } + td { border-bottom: 1px solid #DEE2E3; } +} + +/** Feed entry **/ +.commit, +.snippet, +.message { + .title { + color:#666; + a { color:#666 !important; } + p { margin-top:0px; } + } + .author { color: #999 } +} + +/** JQuery UI **/ +.ui-autocomplete { @include round-borders-all(5px); } +.ui-menu-item { cursor: pointer } +.ui-selectmenu{ + @include round-borders-all(4px); + margin-right:10px; + font-size:1.5em; + height:auto; + font-weight:bold; + .ui-selectmenu-status { + padding:3px 10px; + } +} + +#holder { + background:#FAFAFA; + border: 1px solid #EEE; + cursor: move; + height: 70%; + overflow: hidden; +} + +/* Project Dashboard Page */ +html, body { height: 100%; } + +.news-feed h2{float: left;} +.news-feed .project-updates {margin-bottom: 20px; display: block; width: 100%;} +.news-feed .project-updates .data{ padding: 0} +.news-feed .project-updates a.project-update {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} +.news-feed .project-updates a.project-update:last-child{border-bottom: 0} +.news-feed .project-updates a.project-update img{float: left; margin-right: 10px;} +.news-feed .project-updates a.project-update span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} +.news-feed .project-updates a.project-update span.update-title{margin-bottom: 10px} +.news-feed .project-updates a.project-update span.update-author{color: #999; font-weight: normal; font-style: italic;} +.news-feed .project-updates a.project-update span.update-author strong{font-weight: bold; font-style: normal;} +/* eo Dashboard Page */ + + +/** Update entry **/ +.update-data { padding: 0 } +.update-data { width:100%; } +.update-data.ui-box .data { padding:0; } +a.update-item {padding: 10px; border-bottom: 1px solid #eee; overflow: hidden; display: block;} +a.update-item:last-child{border-bottom: 0} +a.update-item img{float: left; margin-right: 10px;} +a.update-item span.update-title, .dashboard-page .news-feed .project-updates li a span.update-author{display: block;} +a.update-item span.update-title{margin-bottom: 10px} +a.update-item span.update-author{color: #999; font-weight: normal; font-style: italic;} +a.update-item span.update-author strong{font-weight: bold; font-style: normal;} + + +body .team_member_new .span-6, .team_member_edit .span-6{ padding:10px 0; } + +body.projects-page input.text.git-url.project_list_url { width:165px; } + + +body table.no-borders th { + background:none; + border-bottom:1px solid #CCC; + color:#333; +} + +body table.no-borders tr, +body table.no-borders td{ + border:none; +} + +.ajax-tab-loading { + padding:40px; + display:none; +} + +#tree-content-holder { float:left; width:100%; } + +#tree-readme-holder { + float:left; + width:100%; + + .readme { + @include round-borders-all(4px); + padding: 4px 15px; + background:#F7F7F7; + } +} + + + +/* Commit Page */ +.entity-info {float: right;} +.entity-button{ + background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.192, #fff), to(#f4f4f4)); + background-image: -webkit-linear-gradient(#fff 19.2%, #f4f4f4); + background-image: -moz-linear-gradient(#fff 19.2%, #f4f4f4); + background-image: -o-linear-gradient(#fff 19.2%, #f4f4f4); + box-shadow: 0 -1px 0 white inset; + display: block; + border: 1px solid #eee; + border-radius: 5px; + margin-bottom: 2px; + position: relative; + padding: 4px 10px; + font-size: 11px; + padding-right: 20px; +} + +.entity-button i{ + background: url('images.png') no-repeat -138px -27px; + width: 6px; + height: 9px; + float: right; + position: absolute; + top: 6px; + right: 5px; +} +.box-arrow{float: right; background: #E3E5EA; padding: 10px; border-radius: 5px; margin-top: 2px; text-shadow: none; color: #999; margin: 1.5em 0;} + +h4.dash-tabs { + margin: 0; + border-bottom: 1px solid #ccc; + padding: 10px 10px; + font-size: 11px; + padding-left:20px; + font-weight: bold; text-transform: uppercase; + background: #F7F7F7; + margin-bottom:20px; + height:13px; + +} + +.dash-button { + border-right: 1px solid #ddd; + background:none; + padding: 10px 15px; + float:left; + position:relative; + top:-10px; + left:0px; + height:13px; + + &:first-child { + border-left: 1px solid #ddd; + } + &.active { + background: #eaeaea; + } +} + + +.dashboard-loader { + float:right; + margin-right:30px; + display:none; +} + + +.merge-tabs { + margin: 0; + border: 1px solid #ccc; + padding: 5px; + font-size: 12px; + background: #F7F7F7; + margin-bottom:20px; + height:26px; + + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + + .tab { + font-weight: bold; + border-right: 1px solid #ddd; + background:none; + padding: 10px; + min-width:60px; + float:left; + position:relative; + top:-5px; + left:-5px; + height:16px; + padding-left:34px; + + span { + width: 20px; + height: 20px; + display: inline-block; + position: absolute; + left: 8px; + top: 8px; + } + + &.active { + background: #eaeaea; + } + } +} +.merge-tabs.repository .tab span{ background: url("images.png") no-repeat -38px -77px; } +.activities-tab span { background: url("images.png") no-repeat -161px -1px; } +.stat-tab span, +.team-tab span, +.snippets-tab span { background: url("images.png") no-repeat -38px -77px; } +.files-tab span { background: url("images.png") no-repeat -112px -23px; } + +.merge-notes-tab span { background: url("images.png") no-repeat -161px -1px; } +.merge-commits-tab span { background: url("images.png") no-repeat -86px 1px; } +.merge-diffs-tab span { background: url("images.png") no-repeat -118px 1px; } +.merge-tabs .dashboard-loader { padding:8px; } + +.user-mention { + color: #2FA0BB; + font-weight: bold; +} + +.author { + color: #999; +} + + + + +.dark_scheme_box { + padding:20px 0; + + label { + float:left; + box-shadow: 0 0px 5px rgba(0,0,0,.3); + + img { + } + } +} + +a.project-update.titled { + position: relative; + padding-left: 235px !important; + + .title-block { + padding: 10px; + width: 205px; + position: absolute; + left: 0; + top: 0; + } +} + +.add_new { + float: right; + background: #A6B807; + color: white; + padding: 4px 10px; + @include round-borders-all(4px); + font-size:11px; + margin: 10px 0; +} diff --git a/app/assets/stylesheets/ref_select.scss b/app/assets/stylesheets/ref_select.scss new file mode 100644 index 00000000..ff0ffa9f --- /dev/null +++ b/app/assets/stylesheets/ref_select.scss @@ -0,0 +1,50 @@ +/** Branch/tag selector **/ +.project-refs-form { + margin:0; + span { + background:none !important; + position:static !important; + width:auto !important; + height:auto !important; + } +} +.project-refs-select { + width:120px; +} + +.project-refs-form .chzn-container { + position: relative; + top: 0; + left: 0; + margin-right: 10px; + + .chzn-drop { + margin:7px 0; + border: 1px solid #CCC; + min-width: 300px; + + .chzn-results { + max-height:300px; + } + + .chzn-search input { + min-width:200px; + } + } + + .chzn-single { + background:#ddd; + //border:none; + //box-shadow:none; + + div { + background:transparent; + border-left:none; + } + + span { + font-weight: normal; + } + } +} + diff --git a/app/assets/stylesheets/style.scss b/app/assets/stylesheets/style.scss deleted file mode 100644 index 4bb5fef9..00000000 --- a/app/assets/stylesheets/style.scss +++ /dev/null @@ -1,802 +0,0 @@ -/* HTML5 ✰ Boilerplate - * ==|== normalize ========================================================== - */ - -article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } -audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } -audio:not([controls]) { display: none; } -[hidden] { display: none; } - -html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } -body { margin: 0; font-size: 13px; line-height: 1.231; } -body, button, input, select, textarea { - font-family: "helvetica", "arial", "freesans", "clean", sans-serif; -color: #222; } - -::-moz-selection { background: #79c3e0; color: #fff; text-shadow: none; } -::selection { background: #79c3e0; color: #fff; text-shadow: none; } - -a { color: #00e; } -a:hover { color: #06e; } -a:focus { outline: thin dotted; } -a:hover, a:active { outline: 0; } - -abbr[title] { border-bottom: 1px dotted; } -b, strong { font-weight: bold; } -blockquote { margin: 1em 40px; } -dfn { font-style: italic; } -hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } -ins { background: #ff9; color: #000; text-decoration: none; } -mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } -pre, code, kbd, samp { font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 1em; } -pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } -q { quotes: none; } -q:before, q:after { content: ""; content: none; } -small { font-size: 85%; } -sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } -sup { top: -0.5em; } -sub { bottom: -0.25em; } -ul, ol { margin: 1em 0; padding: 0 0 0 40px; } -dd { margin: 0 0 0 40px; } -nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; } -img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; } -svg:not(:root) { overflow: hidden; } -figure { margin: 0; } - -form { margin: 0; } -fieldset { border: 0; margin: 0; padding: 0; } -label { cursor: pointer; } -legend { border: 0; *margin-left: -7px; padding: 0; } -button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } -button, input { line-height: normal; *overflow: visible; } -table button, table input { *overflow: auto; } -button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; } -input[type="checkbox"], input[type="radio"] { box-sizing: border-box; } -input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } -input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } -button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } -textarea { overflow: auto; vertical-align: top; resize: vertical; } -input:valid, textarea:valid { } -input:invalid, textarea:invalid { background-color: #f0dddd; } - -table { border-collapse: collapse; border-spacing: 0; } -td { vertical-align: top; } - -/* ==|== primary styles ===================================================== - Author: Ricardo Rauch - ========================================================================== */ - -/* 960gs */ -.container_4{width:98%;margin-left:1%;margin-right:1%}.grid_1,.grid_2,.grid_3,.grid_4{display:inline;float:left;position:relative;margin-left:1%;margin-right:1%}.alpha{margin-left:0}.omega{margin-right:0}.container_4 .grid_1{width:23.0%}.container_4 .grid_2{width:48.0%}.container_4 .grid_3{width:73.0%}.container_4 .grid_4{width:98.0%}.container_4 .prefix_1{padding-left:25.0%}.container_4 .prefix_2{padding-left:50.0%}.container_4 .prefix_3{padding-left:75.0%}.container_4 .suffix_1{padding-right:25.0%}.container_4 .suffix_2{padding-right:50.0%}.container_4 .suffix_3{padding-right:75.0%}.container_4 .push_1{left:25.0%}.container_4 .push_2{left:50.0%}.container_4 .push_3{left:75.0%}.container_4 .pull_1{left:-25.0%}.container_4 .pull_2{left:-50.0%}.container_4 .pull_3{left:-75.0%}.clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}.clearfix:after{clear:both;content:' ';display:block;font-size:0;line-height:0;visibility:hidden;width:0;height:0}.clearfix{display:inline-block}* html .clearfix{height:1%}.clearfix{display:block} -/* eo 960gs*/ - -/* Vars */ -$color: "#4BB8D2"; -$blue_link: "#2fa0bb"; -/* eo Vars */ - -html{ -webkit-font-smoothing:antialiased; } -body { - font-size: 12px; - background-color: #FFFFFF; -} -a{text-decoration: none; font-weight: bold; color: #444} -a:hover{color: #555} -/* Typography */ -h1,h2,h3,h4,h5{font-weight: normal; color: #666} -h2{margin: 1.5em 0} -/* eo Typography */ - -/* Forms */ -input[type="text"]:focus, input[type="password"]:focus { outline: none; } -input.text{border: 1px solid #ccc; border-radius: 4px; display: block; padding: 10px} - -.form-row{ - padding: 0px 0px 10px 0px; -} - -.form-row label{ - font-weight:bold; - display: inline-block; - padding: 0px 0px 5px 0px; -} - -/* eo Forms */ - -/* Tables */ -table {width:100%; border: 1px solid #DEE2E3; margin-bottom: 20px} -table thead{ - -webkit-border-top-left-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topleft: 5px; - -moz-border-radius-topright: 5px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; -} -table thead th{ - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); - margin: 0; - font-weight: normal; - font-weight: bold; - text-align: left; - color: #97A0A5; -} -td, th{ padding: .9em 1em; vertical-align: middle; } - -table thead .image{width:100px} -.listed_items tr.odd:hover{background-color:#FFFFCF} -/* eo Tables */ - -/* Buttons */ -.grey-button{ - border-radius: 5px; - font-size: 12px; - font-weight: bold; - padding: 5px 17px; - border: 1px solid #999; - color: #666; - display: inline-block; - box-shadow: 0 1px 2px rgba(0,0,0,.3); - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #f7f7f7), to(#d5d5d5)); - background-image: -webkit-linear-gradient(#f7f7f7 7.6%, #d5d5d5); - background-image: -moz-linear-gradient(#f7f7f7 7.6%, #d5d5d5); - background-image: -o-linear-gradient(#f7f7f7 7.6%, #d5d5d5); -} - -a.button, input.button { - font-weight: bold; - padding: 10px 20px; - text-align: center; - display: inline-block; - border-radius: 5px; - color: #578E91; - font-size: 12px; - text-transform: uppercase; - border: 1px solid #8CE2E6; - background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #dbf5f6), to(#c5eef0)); - background-image: -webkit-linear-gradient(#dbf5f6 79.4%, #c5eef0); - background-image: -moz-linear-gradient(#dbf5f6 79.4%, #c5eef0); - background-image: -o-linear-gradient(#dbf5f6 79.4%, #c5eef0); -} - -input.button{margin-bottom: 1.5em} - -.button:hover {color: rgba(0,0,0,.8)} - -.button.green {margin-right: 0; } - -.button.yellow{ - color: #908054; - border-color: #DDCDA1; - background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #FFEFC3), to(#F3E3B7)); - background-image: -webkit-linear-gradient(#FFEFC3 79.4%, #F3E3B7); - background-image: -moz-linear-gradient(#FFEFC3 79.4%, #F3E3B7); - background-image: -o-linear-gradient(#FFEFC3 79.4%, #F3E3B7); -} - -.button.blue{ - color: #417E97; - border-color: #b2cdec; - background-image: -webkit-gradient(linear, 0 0, 0 34, color-stop(0.794, #dbe8f6), to(#c7daf1)); - background-image: -webkit-linear-gradient(#dbe8f6 79.4%, #c7daf1); - background-image: -moz-linear-gradient(#dbe8f6 79.4%, #c7daf1); - background-image: -o-linear-gradient(#dbe8f6 79.4%, #c7daf1); -} - -.button-small{ text-shadow: none; padding: 4px 10px; } -.button-green{background: #A6B807; color: white} - -/* eo Buttons */ - -/* UI Box */ -//.ui-box{border: 1px solid #DEDFE1; float: left; border-radius: 5px} -.ui-box{float: left;} -.ui-box h3{ - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); - background:none; - margin: 0; - padding: 1em; - font-size: 12px; - font-weight: normal; - font-weight: bold; - font-size: 16px; - border-bottom: 1px solid #DEDFE1; - -webkit-border-top-left-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topleft: 5px; - -moz-border-radius-topright: 5px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; -} - -.ui-box.ui-box-small h3{ - padding: 8px 10px; - font-size: 12px; -} - -.ui-box .data{padding: .5em 1em} - -.ui-box .buttons{ - padding: 1em; - border-top:1px solid $lite_border_color; -} - -.ui-box .buttons .button{padding: 8px 9px; font-size: 11px} - -.ui-box.hover:hover{box-shadow: 0 0 10px rgba(0,0,0,.1); border: 1px solid #ccc; - - -webkit-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); - -moz-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); - -o-transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); - transition: all 200ms cubic-bezier(0.470, 0.000, 0.745, 0.715); -} - -/* eo UI Box */ - -/* Login Page */ -body.login-page{background-color: #f1f1f1; padding-top: 10%} - -.login-box{ - width: 304px; - position: relative; - border-radius: 5px; - margin: auto; - padding: 20px; - background: white; - box-shadow: rgba(0, 0, 0, 0.07) 0 1px 0,white 0 2px 0,rgba(0, 0, 0, 0.07) 0 3px 0,white 0 4px 0, rgba(0, 0, 0, 0.07) 0 5px 0; -} - -.login-box .login-logo{ - margin: 10px 0 30px 0; - display: block; -} - -.login-box input.text{background-color: #f1f1f1; font-size: 16px; border-radius: 0; padding: 14px 10px; width: 280px} - -.login-box input.text.top{ - -webkit-border-top-left-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topleft: 5px; - -moz-border-radius-topright: 5px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; -} - -.login-box input.text.bottom{ - -webkit-border-bottom-right-radius: 5px; - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomright: 5px; - -moz-border-radius-bottomleft: 5px; - border-bottom-right-radius: 5px; - border-bottom-left-radius: 5px; - border-top: 0; - margin-bottom: 20px; -} - -.login-box a.forgot{float: right; padding-top: 6px} - -/* Icons */ -.directory, .file{ - display: inline-block; - margin-right: 10px; - width: 14px; -} - -.directory{ - background: url('images.png') no-repeat -73px -26px; - height: 11px; - margin-bottom: -1px; -} - -.file{ - background: url('images.png') no-repeat -114px -24px; - height: 16px; - margin-bottom: -3px; -} - -/* eo Icons*/ - -/* Errors */ -#error_explanation{background: #ffe5eb; padding: 20px; margin-bottom: 20px; border-radius: 5px} -#error_explanation h2{margin: 0; margin-bottom: 20px; color: red} -#error_explanation ul li{margin-bottom: 10px} -#error_explanation ul li:last-child{margin-bottom: 0} -.field_with_errors { - input[type="text"], - input[type="password"], - textarea - { - border: 1px solid #D30 !important; - } -} -/* eo Errors */ - -/* Notices */ -#notice{background: #dfffe1; padding: 20px; margin-bottom: 20px; border-radius: 5px; color: green; font-size: 1.3em;} -/* eo Notices */ - -/* InfoBlock */ -#infoblock{ - background: #eeeeee; - padding: 20px; - margin-bottom: 20px; - border-radius: 5px; -} -/* eo InfoBlock */ - -/* Header */ -header{ - background: #474D57 url('bg-header.png') repeat-x bottom; - z-index: 10000; - height: 44px; - padding: 10px 2% 6px 2%; -} -header a:hover{color: #f1f1f1} -header h1{ - width: 65px; -} -header h1.logo{margin: 0; padding: 0} -header h1.logo a{ - background: url('images.png') no-repeat -3px -7px; - width: 65px; - height: 26px; - margin: 5px 0; - padding: 0; - display: block; - float: left; - text-indent: -1000em; -} - -header nav{border-radius: 4px; box-shadow: 0 1px 2px black; width: 294px; margin: auto; - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595d63), to(#31363e)); - background-image: -webkit-linear-gradient(#595d63 6.6%, #31363e); - background-image: -moz-linear-gradient(#595d63 6.6%, #31363e); - background-image: -o-linear-gradient(#595d63 6.6%, #31363e); - margin-top: 2px; - height:30px -} -header nav.shorter_nav{ - width: 207px; -} -header nav a{padding: 8px 12px 8px 34px; display: inline-block; color: #D6DADF; border-right: 1px solid #31363E; position: relative; box-shadow: 1px 0 0 rgba(255,255,255,.1); margin: 0} -header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;} -header nav a:last-child {border: 0; box-shadow: none} -header nav a:hover, header nav a.current{ - background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #595d63), to(#2c2f35)); - background-image: -webkit-linear-gradient(#595d63 6.6%, #2c2f35); - background-image: -moz-linear-gradient(#595d63 6.6%, #202227); - background-image: -o-linear-gradient(#595d63 6.6%, #202227); -} - -header nav a:active{ - box-shadow: 0 1px 4px rgba(0,0,0,.8) inset; -} - -header nav a.dashboard { - -webkit-border-top-left-radius: 4px; - -webkit-border-bottom-left-radius: 4px; - -moz-border-radius-topleft: 4px; - -moz-border-radius-bottomleft: 4px; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} - -header nav a.last_elem{ - -webkit-border-top-right-radius: 4px; - -webkit-border-bottom-right-radius: 4px; - -moz-border-radius-topright: 4px; - -moz-border-radius-bottomright: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} - -header .search{ display: inline-block; float: right; margin-right: 90px} - -header nav a span{width: 20px; height: 20px; display: inline-block; background: red; position: absolute; left: 8px; top: 6px;} - -header nav a.dashboard span{background: url('images.png') no-repeat -161px 0;} -header nav a.admin span{background: url('images.png') no-repeat -184px 0;} -header nav a.project span{background: url('images.png') no-repeat -209px -1px; top: 7px} -header nav a.issues span{background: url('images.png') no-repeat -209px -1px; top: 7px} - -header .login-top{float: right; width: 180px; - background-image: -webkit-gradient(linear, 0 0, 0 62, color-stop(0.032, #464c56), to(#363c45)); - background-image: -webkit-linear-gradient(#464c56 3.2%, #363c45); - background-image: -moz-linear-gradient(#464c56 3.2%, #363c45); - background-image: -o-linear-gradient(#464c56 3.2%, #363c45); - padding: 0 10px; - height: 44px; -} -header .login-top a{display: block;} -header .login-top a.pic{float: left; margin-right: 10px; - img{ height: 36px; width: 36px; border: 1px solid black} -} -header .login-top a.username{margin-bottom: 5px} -header .login-top a.logout{color: #ccc} -header{margin-bottom: 0; clear: both; position:relative;} - -.page-title{background-color: #f1f1f1;display: block; float: left; clear: both; width: 98%; padding: 1% 1%; border-bottom: 1px solid #ccc; box-shadow: 0 -1px 0 white inset; margin-bottom: 1.5em} -.page-title h1{font-size: 20px; width: 400px; margin: 0; padding-top: 8px } -.page-title a.grey-button{float: right;} -.right{float: right;} - -/* Account box */ -header .account-box{ - position: absolute; - right: 0; - top: 8px; - z-index: 10000; - width: 128px; - font-size: 11px; - float: right; - display: block; - cursor: pointer;} -header .account-box img{ - border-radius: 4px; - right: 20px; - position: absolute; - width: 33px; height: 33px; - display: block; top:0;} -header .account-box img:after{ - content: " "; - display: block; - position: absolute; - top: 0; - right: 0; -left: 0; - bottom: 0; -float: right; - border-radius: 5px; - border: 1px solid rgba(255, 255, 255, .1); - border-bottom: 0; - background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, .15)), to(rgba(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, .1)), color-stop(0.501, rgba(255, 255, 255, 0)), color-stop(1, rgba(255, 255, 255, 0))); - background: -moz-linear-gradient(top, rgba(255, 255, 255, .15), rgba(0, 0, 0, .25)), -moz-linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, .1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0)); - background: linear-gradient(top, rgba(255, 255, 255, .15), rgba(0, 0, 0, .25)), linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, .1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0)); - -webkit-background-origin: border-box; - -moz-background-origin: border; - background-origin: border-box; -} - -.account-box.hover{height: 138px;} - -.account-box:hover > .account-links{display: block;} -header .account-links{ - background: #79C3E0; display: none; border-radius: 5px; width: 100px; margin-top: 0; float: right; box-shadow: 0 1px 1px rgba(0,0,0,.2); position:relative;} -header .account-links:before { - content: "."; - width:0; - height:0; - position:absolute; - border:5px solid transparent; - border-color:rgba(255,255,255,0); - border-bottom-color:#fafafa; - text-indent:-9999px; - top:-10px; - line-height:0; - right:10px; - z-index:10; -} - -/* Inspired by http://maxvoltar.com/temp/nowplaying/ */ -header .account-links{background: white; display: none; z-index: 100000; border-radius: 5px; width: 100px; position: absolute; right: 20px; top: 46px; margin-top: 0; float: right; box-shadow: 0 1px 1px rgba(0,0,0,.2); } -header .account-links a{color: #666; padding: 6px 10px; display: block; text-shadow: none; border-bottom: 1px solid #eee} -header .account-links a:hover{ - background: #3aacec; - background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#39acec), to(#279ada), color-stop(.05, #4cbefe)); - background: -moz-linear-gradient(top, #39acec, #4cbefe 5%, #279ada); - background: linear-gradient(top, #39acec, #4cbefe 5%, #279ada); - color: #fff; - text-shadow: #1488c8 0 -1px 0; -} -.account-box.hover .arrow-up{top: 41px; right: 6px; position: absolute} -header .account-links a:first-child{ - -webkit-border-top-left-radius: 5px; - -webkit-border-top-right-radius: 5px; - -moz-border-radius-topleft: 5px; - -moz-border-radius-topright: 5px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; -} - -header .account-links a:last-child{ - -webkit-border-bottom-right-radius: 5px; - -webkit-border-bottom-left-radius: 5px; - -moz-border-radius-bottomright: 5px; - -moz-border-radius-bottomleft: 5px; - border-bottom-right-radius: 5px; - border-bottom-left-radius: 5px; - border-bottom: 0; -} - -.big-message{ - background-image: -webkit-gradient(linear, 0 48, 0 0, color-stop(0.041, #eccb40), to(#ffee4d)); - background-image: -webkit-linear-gradient(90deg, #eccb40 4.1%, #ffee4d); - background-image: -moz-linear-gradient(90deg, #eccb40 4.1%, #ffee4d); - background-image: -o-linear-gradient(90deg, #eccb40 4.1%, #ffee4d); - text-align: center; - font-weight: bold; - padding: 10px 20px; - text-shadow: 0 1px 0 rgba(255,255,255,.3); - color: #333; - color: rgba(0,0,0,.7); - font-size: 14px; - box-shadow: 0 1px 2px rgba(0,0,0,.7); - z-index: 100000; - margin-bottom: 2px; -} - -.big-message a{color: #000; text-decoration: underline;} - -.big-message.error{ - background-color: #722523; - background-image: -webkit-gradient(linear, 0 49, 0 0, color-stop(0.04, #722523), to(#ad4846)); - background-image: -webkit-linear-gradient(90deg, #9b403f 4%, #c16765); - background-image: -moz-linear-gradient(90deg, #722523 4%, #ad4846); - background-image: -o-linear-gradient(90deg, #722523 4%, #ad4846); - color: #2E0D0C; -} - -.big-message.success{ - background-color: #7a9339; - background-image: -webkit-gradient(linear, 0 48, 0 0, color-stop(0.062, #7a9339), to(#93ae46)); - background-image: -webkit-linear-gradient(90deg, #7a9339 6.2%, #93ae46); - background-image: -moz-linear-gradient(90deg, #7a9339 6.2%, #93ae46); - background-image: -o-linear-gradient(90deg, #7a9339 6.2%, #93ae46) -} - -.big-message.success{ - background-color: #7a9339; - background-image: -webkit-gradient(linear, 0 48, 0 0, color-stop(0.062, #7a9339), to(#93ae46)); - background-image: -webkit-linear-gradient(90deg, #7a9339 6.2%, #93ae46); - background-image: -moz-linear-gradient(90deg, #7a9339 6.2%, #93ae46); - background-image: -o-linear-gradient(90deg, #7a9339 6.2%, #93ae46) -} - -.big-message.notice{ - background-image: -webkit-gradient(linear, 0 49, 0 0, color-stop(0.061, #447790), color-stop(0.897, #5da2bf)); - background-image: -webkit-linear-gradient(90deg, #447790 6.1%, #5da2bf 89.7%); - background-image: -moz-linear-gradient(90deg, #447790 6.1%, #5da2bf 89.7%); - background-image: -o-linear-gradient(90deg, #447790 6.1%, #5da2bf 89.7%) -} - -/* eo Account Box */ -input.search-input{ - float: left; - text-shadow: none; - width: 116px; - background-image: url('icon-search.png') ; - background-repeat: no-repeat; - background-position: 10px; - border-radius: 4px; - border: 1px solid #AAA; - background-color: #FFF; - padding: 5px; - padding-left: 26px; - margin-top: 2px; - margin-right: 10px; -} -/*input.search-input:focus{ background-color: white; width: 216px;}*/ -input.search-input::-webkit-input-placeholder {color: #666} -/* eo Header */ - -h2.icon{position: relative; padding-left: 40px; float: left; } -/*h2 a{font-weight: normal;}*/ -h2.icon span{background: #E3E5EA url('images.png'); height: 32px; width: 32px; left: 0; top: -5px; border-radius: 4px; display: inline-block; position: absolute} - -/* Dashboard Page */ -html, body { height: 100%; } - - - - -.grey-button.right{margin-top: 20px} - -/* Project Page */ -/* eo New Project Page */ - - -/* eo Project Page */ - -/* Projects Page */ -body.projects-page h2.icon span{background-position: -31px -70px;} -body.projects-page .project-box.ui-box .data .repository {margin-bottom: 20px} -body.projects-page .project-box.ui-box .data .title span{ font-weight: bold;} -body.projects-page .project-box{width: 100%; margin-bottom: 3em} -body.projects-page .browse-code{margin-right: 10px} -/* eo Projects Page */ - -/* ==|== non-semantic helper classes ======================================== */ -.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; } -.ir br { display: none; } -.hidden { display: none !important; visibility: hidden; } -.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } -.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } -.invisible { visibility: hidden; } -.clearfix:before, .clearfix:after { content: ""; display: table; } -.clearfix:after { clear: both; } -.clearfix { zoom: 1; } - -/* ==|== media queries ====================================================== */ - -@media only screen and (min-width: 480px) { - -} - -@media only screen and (min-width: 768px) { - -} - -/* ==|== print styles ======================================================= */ - -@media print { - * { background: transparent !important; color: black !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } - a, a:visited { text-decoration: underline; } - a[href]:after { content: " (" attr(href) ")"; } - abbr[title]:after { content: " (" attr(title) ")"; } - .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } - pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } - thead { display: table-header-group; } - tr, img { page-break-inside: avoid; } - img { max-width: 100% !important; } - @page { margin: 0.5cm; } - p, h2, h3 { orphans: 3; widows: 3; } - h2, h3 { page-break-after: avoid; } -} - -body, button, input, select, textarea { - font-family: "helvetica", "arial", "freesans", "clean", sans-serif; -} - -/** FORM INPUTS **/ -.new_merge_request, -.edit_merge_request, -.user_new, -.new_key, -.new_issue, -.new_note, -.edit_user, -.edit_issue, -.new_project, -.new_snippet, -.edit_snippet, -.edit_project { - input[type='text'], - input[type='email'], - input[type='password'], - textarea { - width:400px; - padding:8px; - font-size:14px; - @include round-borders-all(4px); - } -} - -.text_field { - width:400px; - padding:8px; - font-size:14px; - @include round-borders-all(4px); -} - -.input_button { - padding:8px; - font-size:14px; - cursor:pointer; - background-color: #F5F5F5; - border-color: #EEEEEE #DEDEDE #DEDEDE #EEEEEE; - border-right: 1px solid #DEDEDE; - border-style: solid; - border-width: 1px; -} - -/** FLASH **/ -#flash_container { - height:45px; - position:fixed; - z-index:10001; - top:0px; - width:100%; - margin-bottom:15px; - overflow:hidden; - background:white; - cursor:pointer; - border-bottom:1px solid #777; - - h4 { - color:#444; - font-size:22px; - padding-top:5px; - margin:2px; - } -} - - -.errors_holder { - background:#D30; - color:#fff; - @include round-borders-all(4px); - border:1px solid #a30; - padding:5px; - list-style:none; - font-weight: bold; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - - li { - padding:10px; - } -} - -.notice_holder { - background:#DDF4FB; - color:#444; - border:1px solid #C6EDF9; - @include round-borders-all(4px); - padding:5px; - list-style:none; - font-weight: bold; - text-shadow: 0 -1px 0 rgba(255, 255, 255, 0.25); - - li { - padding:10px; - } -} - -.alert_holder { - background:#FDF5D9; - color:#444; - border:1px solid #FCEEC1; - @include round-borders-all(4px); - padding:5px; - list-style:none; - font-weight: bold; - text-shadow: 0 -1px 0 rgba(255, 255, 255, 0.25); - - li { - padding:10px; - } -} - -.help_content { - margin:20px; - margin-top:71px; - - h2 { - margin:0; - padding:0; - } - - .menu { - float:left; - width:20%; - - .active { - color: $active_bd_color; - } - } - - .content { - float:right; - width:78%; - } - - .bash { - @include round-borders-all(4px); - background:#eee; - padding:5px; - //overflow-x:scroll; - pre{ - padding:0; - line-height:2.0; - margin:0; - font-family: 'Courier New', 'andale mono','lucida console',monospace; - color: #333; - text-align:left; - } - } -} diff --git a/app/assets/stylesheets/tags.css.css b/app/assets/stylesheets/tags.css.css deleted file mode 100644 index 829d2c78..00000000 --- a/app/assets/stylesheets/tags.css.css +++ /dev/null @@ -1,42 +0,0 @@ -.tags-list { - padding : 0px 10px 10px 10px; - -} - -.tags-list a { - display: inline-block; - padding: 8px 11px 8px 11px; - margin: 1px 5px 0px 0px; - border-radius: 4px; - border: 1px solid #72bbdf; - background-color: #72bbdf; - color: #0f326d; - font-weight: bold; - font-size: 14px; -} - -.small-tags a{ - font-size: 9px; - - display: inline-block; - padding: 2px 3px 1px 3px; - margin: 0px 3px 0px 0px; - border-radius: 2px; - background-color: #72bbdf; - color: #FFF; - text-shadow: none; - font-weight: bold; -} - -.medium-tags a{ - font-size: 12px; - - display: inline-block; - padding: 3px 4px 2px 4px; - margin: 0px 7px 8px 0px; - border-radius: 3px; - background-color: #72bbdf; - color: #FFF; - text-shadow: none; - font-weight: bold; -} diff --git a/app/assets/stylesheets/top_panel.scss b/app/assets/stylesheets/top_panel.scss deleted file mode 100644 index 57c1e077..00000000 --- a/app/assets/stylesheets/top_panel.scss +++ /dev/null @@ -1,146 +0,0 @@ -.main_links { - width:130px; - float:left; - - a { - float:left; - } -} - -.dashboard_links { - padding:7px; - float:left; - a { - margin: 0 14px; - float: left; - font-size: 14px; - - &.active { - color:$active_link_color; - } - &:hover { - color:$active_link_color; - } - } -} - -.top-tabs { - margin: 0; - padding: 5px; - font-size: 14px; - padding-bottom:10px; - margin-bottom:20px; - height:26px; - border-bottom:1px solid #ccc; - - .tab { - font-weight: bold; - background:none; - padding: 10px; - float:left; - padding-left:0px; - padding-right:40px; - - &.active { - color: $active_link_color; - } - } -} - -body header { - position:absolute; - width:100%; - padding:0; - margin:0; - top:0; - left:0; - background: #999; /* for non-css3 browsers */ - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFF', endColorstr='#EAEAEA'); /* for IE */ - background: -webkit-gradient(linear, left top, left bottom, from(#FFFFFF), to(#EAEAEA)); /* for webkit browsers */ - background: -moz-linear-gradient(top, #FFFFFF, #EAEAEA); /* for firefox 3.6+ */ - background: -o-linear-gradient(top, #FFFFFF, #EAEAEA); /* for firefox 3.6+ */ - border-bottom: 1px solid #ccc; - - height:50px; - - .wrapper { - margin:auto; - width:$app_width; - position:relative; - - .top_panel_content { - padding:10px $app_padding; - } - } - - .project_name { - float:left; - width:235px; - margin-right:30px; - font-size:16px; - font-weight:bold; - padding:8px; - color:#333; - } - - .git_url_wrapper { - padding:0px; - margin:0px; - float:left; - - .git-url { - padding:0px; - margin:0px; - font-size: 12px; - - margin-right:10px; - border-radius: 4px; - -moz-border-radius: 4px; - - - color: #666; - border: 1px solid #AAA; - padding: 0 10px 0 30px; - background: transparent url('images.png') no-repeat 8px -42px; - width: 160px; - height:26px; - } - } -} - -.top_panel_holder .chzn-container { - position:relative; - - .chzn-drop { - margin:7px 0; - border: 1px solid #CCC; - min-width: 300px; - - .chzn-results { - max-height:300px; - } - } - - .chzn-single { - background:transparent; - -moz-border-radius: 4px; - border-radius: 4px; - - div { - background:transparent; - border-left:none; - } - - span { - font-weight: normal; - } - } -} - -.rss-icon { - margin:0 15px; - padding:3px; - border:1px solid #AAA; - border-radius:3px; - float:left; -} diff --git a/app/assets/stylesheets/tree.scss b/app/assets/stylesheets/tree.scss index 57070871..59299254 100644 --- a/app/assets/stylesheets/tree.scss +++ b/app/assets/stylesheets/tree.scss @@ -1,121 +1,178 @@ -#tree-breadcrumbs { - div { - margin:0; - margin-bottom:20px; +#tree-holder { + #tree-content-holder { float:left; - font-size:14px; + width:100%; } -} - -.tree_progress { - float:left; - width:16px; - height:16px; - margin:2px 6px; - &.loading { - background-position: 0px 0px; - background: url("ajax-loader-facebook.gif") no-repeat; - } -} - - -/** FILE CONTENT VIEW **/ -.view_file_content{ - .old_line, .new_line { - background:#ECECEC; - color:#777; - width:15px; + #tree-readme-holder { float:left; - padding: 0px 10px; - border-right: 1px solid #ccc; + width:100%; + .readme { + @include round-borders-all(4px); + padding:4px 15px; + background: #F7F7F7; + } } - .old_line{ + + .tree_progress { display:none; + margin:20px; + &.loading { + display:block; + } } -} -.view_file .view_file_header, -.diff_file .diff_file_header { - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #fefefe), to(#F6F7F8)); - background-image: -webkit-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -moz-linear-gradient(#fefefe 7.6%, #F6F7F8); - background-image: -o-linear-gradient(#fefefe 7.6%, #F6F7F8); + + /** FILE CONTENT VIEW **/ + .view_file_content{ + .old_line, .new_line { + background:#ECECEC; + color:#777; + width:15px; + float:left; + padding: 0px 10px; + border-right: 1px solid #ccc; + } + .old_line{ + display:none; + } + } + + .view_file .view_file_header, + .diff_file .diff_file_header { + background:#f5f5f5; margin: 0; font-weight: normal; font-weight: bold; text-align: left; color: #666; - border-bottom: 1px solid #DEE2E3; + border-bottom: 1px solid #ccc; padding: 7px 10px; .mode_text, .file_icon { - margin-right:15px; - padding-right:15px; - border-right:1px solid $lite_border_color; - float:left; color:#aaa; } - - .file_icon { - padding-left:15px; - } -} - -.view_file { - border:1px solid #CCC; - margin-bottom:1em; - - .view_file_content { - background:#fff; - color:#514721; - font-size: 11px; } - .view_file_content_image { - background:#eee; - text-align:center; - img { - padding:100px; - max-width:300px; + + .view_file { + border:1px solid #CCC; + margin-bottom:1em; + + .view_file_content { + background:#fff; + color:#514721; + font-size: 11px; + } + .view_file_content_image { + background:#eee; + text-align:center; + img { + padding:100px; + max-width:300px; + } } } -} -td.code { - width: 100%; - .highlight { - margin-left: 55px; - overflow:auto; - overflow-y:hidden; - border-left: 1px solid #DEE2E3; - background: white; - } -} -.highlight pre { - white-space: pre; - word-wrap:normal; -} - -table.highlighttable { - border: none; - background: #F7F7F7; -} -body.project-page table.highlighttable td { border: none } -table.highlighttable tr:hover { background:none;} - -table.highlighttable pre{ - line-height:16px !important; - font-size:12px !important; -} - -table.highlighttable .linenodiv pre { - text-align: right; - padding-right: 4px; - color:#888; -} - -.tree-item { - &:hover { - background: #FFFFCF; + td.code { + width: 100%; + .highlight { + margin-left: 55px; + overflow:auto; + overflow-y:hidden; + } + } + .highlight pre { + white-space: pre; + word-wrap:normal; + } + + table.highlighttable { + border: none; + } + body.project-page table.highlighttable td { border: none } + table.highlighttable tr:hover { background:none;} + + table.highlighttable pre{ + line-height:16px !important; + font-size:12px !important; + } + + table.highlighttable .linenodiv pre { + text-align: right; + padding-right: 4px; + color:#888; + } + + .tree-item { + &:hover { + background: $hover; + cursor:pointer; + } + + + .tree-item-file-name { + font-weight:bold; + a { + color:$style_color; + } + + img { + position: relative; + top: 2px; + } + } + } + + ul.breadcrumb { + background:white; + border:none; + + a { + color:#666; + font-weight:bold; + font-size:14px; + } + } + + #tree-slider { + @include shade; + + td { + padding:7px; + border-color:#f1f1f1; + } + + th { + background:#f5f5f5; + } + } + + .tree-commit-link { + color:#333; + } + + #tree-content-holder .view_file{ + @include shade; + } + + #tree-readme-holder .readme { + @include shade; + margin-bottom:20px; + } + + a.tree-commit-link { + color: #666; + &:hover { + text-decoration: underline; + } + } + + .arrow { + background: url("images.png") no-repeat -85px -77px; + width: 19px; + height: 16px; + float: left; + position: relative; + left: -10px; } } diff --git a/app/assets/stylesheets/ui_basic.scss b/app/assets/stylesheets/ui_basic.scss new file mode 100644 index 00000000..b01e4d16 --- /dev/null +++ b/app/assets/stylesheets/ui_basic.scss @@ -0,0 +1,309 @@ +/** + * This file represent some UI that can be changed + * during web app restyle or theme select. + * + * Next items should be placed there + * - link colors + * - header styles + * - main menu styles + * + */ +.ui_basic { + /* + * Common styles + * + */ + a { + color: $link_color; + &:hover { + text-decoration:none; + color: $style_color; + } + } + + + /* + * Application Header + * + */ + header { + width:100%; + padding:0; + margin:0; + top:1px; + left:0; + background: #F1F1F1; /* for non-css3 browsers */ + border-bottom: 1px solid #ccc; + box-shadow: 0 -1px 0 white inset; + -moz-box-shadow: 0 -1px 0 white inset; + -webkit-box-shadow: 0 -1px 0 white inset; + z-index:10; + height:60px; + + .app_logo { + width:230px; + float:left; + + a { + float:left; + + h1 { + float:left; + margin-left:5px; + font-size:20px; + line-height:34px; + font-weight:bold; + color:#aaa; + text-shadow: 0 1px 1px #FFF; + } + + &.home { + img { + float: left; + position: relative; + top: -9px; + width:46px; + + } + } + &.admin_link { + width:16px; + height:16px; + padding: 5px; + border: 1px solid #ccc; + border-radius: 4px; + margin: 0px; + background: #eee; + margin-left:20px; + &:hover { + background:#f7f7f7; + } + img { + width:16px; + } + } + } + } + .wrapper { + margin:auto; + min-width:$min_app_width; + max-width:$max_app_width; + position:relative; + padding:15px 0; + + .top_panel_content { + margin:0 $app_padding; + } + } + + .project_name { + float:left; + width:400px; + margin:0; + margin-right:30px; + font-size:20px; + line-height:34px; + font-weight:bold; + color:$style_color; + text-shadow: 0 1px 1px #FFF; + } + + .git_url_wrapper { + padding:0px; + margin:0px; + float:left; + + .git-url { + padding:0px; + margin:0px; + font-size: 12px; + margin-right:10px; + border-radius: 4px; + -moz-border-radius: 4px; + color: #666; + border: 1px solid #AAA; + padding: 0 10px 0 30px; + background: transparent url('images.png') no-repeat 8px -42px; + width: 260px; + height:26px; + } + } + + /* Account box */ + .account-box { + position: absolute; + right: 0; + top: 13px; + z-index: 10000; + width: 128px; + font-size: 11px; + float: right; + display: block; + cursor: pointer; + img { + border-radius: 4px; + right: 20px; + position: absolute; + width: 33px; + height: 33px; + display: block; + top: 0; + &:after { + content: " "; + display: block; + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + float: right; + border-radius: 5px; + border: 1px solid rgba(255, 255, 255, 0.1); + border-bottom: 0; + 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))); + 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)); + 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)); + -webkit-background-origin: border-box; + -moz-background-origin: border; + background-origin: border-box; } } } + + .account-box { + &.hover { + height: 138px; } + &:hover > .account-links { + display: block; } } + + .account-links { + background: #79C3E0; + display: none; + border-radius: 5px; + width: 100px; + margin-top: 0; + float: right; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + position: relative; + &:before { + content: "."; + width: 0; + height: 0; + position: absolute; + border: 5px solid transparent; + border-color: rgba(255, 255, 255, 0); + border-bottom-color: #333; + text-indent: -9999px; + top: -10px; + line-height: 0; + right: 10px; + z-index: 10; } + background: #333; + display: none; + z-index: 100000; + border-radius: 5px; + width: 100px; + position: absolute; + right: 20px; + top: 46px; + margin-top: 0; + float: right; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + a { + color: #EEE; + padding: 6px 10px; + display: block; + text-shadow: none; + border-bottom: 1px solid #555; + &:hover { + background: #444; } } } + + .account-box.hover .arrow-up { + top: 41px; + right: 6px; + position: absolute; } + + .account-links a { + &:first-child { + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; } + &:last-child { + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; + border-bottom: 0; } } + + } + /* + * End of Application Header + * + */ + + /* + * Main Menu of Application + * + */ + nav.main_menu { + overflow:hidden; + border-radius: 4px; + margin: auto; + margin:30px $app_padding; + background:#eee; + border:1px solid #ccc; + height:38px; + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); + background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf); + background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); + background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); + @include shade; + .count { + color:#aaa; + margin-left:3px; + } + .label { + background:$hover; + text-shadow:none; + color:$style_color; + } + a { + font-weight:bold; + &:first-child{ + -webkit-border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-topleft: 4px; + -moz-border-radius-bottomleft: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + } + padding: 10px 25px; + display: inline-block; + color: $style_color; + border-right: 1px solid #d5d5d5; + position: relative; + box-shadow: 1px 0 0 rgba(255, 255, 255, 0.1); + margin: 0; + float:left; + text-shadow:0 1px 1px white; + &.home { + background: url(home_icon.PNG) no-repeat center center; + text-indent:-9999px; + min-width:40px; + img { + position:relative; + top:4px; + } + } + &.current { + background-color:#DDD; + } + } + } + /* + * End of Main Menu + * + */ +} diff --git a/app/assets/stylesheets/ui_mars.scss b/app/assets/stylesheets/ui_mars.scss new file mode 100644 index 00000000..b2230f5b --- /dev/null +++ b/app/assets/stylesheets/ui_mars.scss @@ -0,0 +1,337 @@ +/** + * This file represent some UI that can be changed + * during web app restyle or theme select. + * + * Next items should be placed there + * - link colors + * - header styles + * - main menu styles + * + */ +.ui_mars { + + /* + * Common styles + * + */ + a { + color: $link_color; + &:hover { + text-decoration:none; + color: $style_color; + } + } + + + /* + * Application Header + * + */ + header { + width:100%; + padding:0; + margin:0; + top:1px; + left:0; + + + background: #474D57 url('bg-header.png') repeat-x bottom; + + z-index:10; + height:60px; + + .search-input { + background-image:url("icon-search.png"); + float: right; + text-shadow: none; + width: 116px; + background-image: url("icon-search.png"); + background-repeat: no-repeat; + background-position: 10px; + border-radius: 100px; + border: 1px solid rgba(0, 0, 0, 0.7); + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.2), 0 2px 2px rgba(0, 0, 0, 0.4) inset; + background-color: #D2D5DA; + background-color: rgba(255, 255, 255, 0.5); + padding: 5px; + padding-left: 26px; + margin-right: 50px; + + &:focus { + background-color: white; + width: 166px; + } + } + .search-input::-webkit-input-placeholder { + color: #666; + } + .app_logo { + width:230px; + float:left; + position:relative; + top:-4px; + + a { + float:left; + + h1 { + + background: url('images.png') no-repeat -3px -7px; + width: 65px; + height: 26px; + margin: 5px 0; + padding: 0; + display: block; + float: left; + text-indent: -1000em; + + } + + &.home { + img { + display:none + + } + } + &.admin_link { + width:16px; + height:16px; + padding: 5px; + border: 1px solid #888; + border-radius: 4px; + margin: 0px; + background:#474D57 ; + margin-left:20px; + margin-top:4px; + &:hover { + background:#f7f7f7; + } + img { + width:16px; + } + } + } + } + .wrapper { + margin:auto; + min-width:$min_app_width; + max-width:$max_app_width; + position:relative; + padding:15px 0; + + .top_panel_content { + margin:0 $app_padding; + } + } + + .project_name { + float:left; + width:400px; + margin:0; + margin-right:30px; + font-size:20px; + line-height:34px; + font-weight:bold; + color:#fff; + text-shadow: 0 1px 1px #111; + } + + .git_url_wrapper { + padding:0px; + margin:0px; + float:left; + + .git-url { + padding:0px; + margin:0px; + font-size: 12px; + margin-right:10px; + border-radius: 4px; + -moz-border-radius: 4px; + color: #666; + border: 1px solid #AAA; + padding: 0 10px 0 30px; + background: transparent url('images.png') no-repeat 8px -42px; + width: 260px; + height:26px; + } + } + + /* Account box */ + .account-box { + position: absolute; + right: 0; + top: 13px; + z-index: 10000; + width: 128px; + font-size: 11px; + float: right; + display: block; + cursor: pointer; + img { + border-radius: 4px; + right: 20px; + position: absolute; + width: 33px; + height: 33px; + display: block; + top: 0; + &:after { + content: " "; + display: block; + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + float: right; + border-radius: 5px; + border: 1px solid rgba(255, 255, 255, 0.1); + border-bottom: 0; + 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))); + 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)); + 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)); + -webkit-background-origin: border-box; + -moz-background-origin: border; + background-origin: border-box; } } } + + .account-box { + &.hover { + height: 138px; } + &:hover > .account-links { + display: block; } } + + .account-links { + background: #79C3E0; + display: none; + border-radius: 5px; + width: 100px; + margin-top: 0; + float: right; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + position: relative; + &:before { + content: "."; + width: 0; + height: 0; + position: absolute; + border: 5px solid transparent; + border-color: rgba(255, 255, 255, 0); + border-bottom-color: #333; + text-indent: -9999px; + top: -10px; + line-height: 0; + right: 10px; + z-index: 10; } + background: #333; + display: none; + z-index: 100000; + border-radius: 5px; + width: 100px; + position: absolute; + right: 20px; + top: 46px; + margin-top: 0; + float: right; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); + a { + color: #EEE; + padding: 6px 10px; + display: block; + text-shadow: none; + border-bottom: 1px solid #555; + &:hover { + background: #444; } } } + + .account-box.hover .arrow-up { + top: 41px; + right: 6px; + position: absolute; } + + .account-links a { + &:first-child { + -webkit-border-top-left-radius: 5px; + -webkit-border-top-right-radius: 5px; + -moz-border-radius-topleft: 5px; + -moz-border-radius-topright: 5px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; } + &:last-child { + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; + border-bottom: 0; } } + + } + /* + * End of Application Header + * + */ + + /* + * Main Menu of Application + * + */ + nav.main_menu { + overflow:hidden; + border-radius: 4px; + margin: auto; + margin:30px $app_padding; + background:#eee; + border:1px solid #ccc; + height:38px; + background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); + background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf); + background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf); + background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf); + @include shade; + .count { + color:#aaa; + margin-left:3px; + } + .label { + background:$hover; + text-shadow:none; + color:$style_color; + } + a { + font-weight:bold; + &:first-child{ + -webkit-border-top-left-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-topleft: 4px; + -moz-border-radius-bottomleft: 4px; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + } + padding: 10px 25px; + display: inline-block; + color: $style_color; + border-right: 1px solid #d5d5d5; + position: relative; + box-shadow: 1px 0 0 rgba(255, 255, 255, 0.1); + margin: 0; + float:left; + text-shadow:0 1px 1px white; + &.home { + background: url(home_icon.PNG) no-repeat center center; + text-indent:-9999px; + min-width:40px; + img { + position:relative; + top:4px; + } + } + &.current { + background-color:#DDD; + } + } + } + /* + * End of Main Menu + * + */ +} diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index 813e135b..868bec7c 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -52,6 +52,12 @@ class Admin::ProjectsController < ApplicationController def update @admin_project = Project.find_by_code(params[:id]) + owner_id = params[:project].delete(:owner_id) + + if owner_id + @admin_project.owner = User.find(owner_id) + end + if @admin_project.update_attributes(params[:project]) redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.' else diff --git a/app/controllers/admin/team_members_controller.rb b/app/controllers/admin/team_members_controller.rb index d04d32a6..57803b01 100644 --- a/app/controllers/admin/team_members_controller.rb +++ b/app/controllers/admin/team_members_controller.rb @@ -3,39 +3,15 @@ class Admin::TeamMembersController < ApplicationController before_filter :authenticate_user! before_filter :authenticate_admin! - def index - @admin_team_members = UsersProject.page(params[:page]).per(100).order("project_id DESC") - end - - def show - @admin_team_member = UsersProject.find(params[:id]) - end - - def new - @admin_team_member = UsersProject.new(params[:team_member]) - end - def edit @admin_team_member = UsersProject.find(params[:id]) end - def create - @admin_team_member = UsersProject.new(params[:team_member]) - @admin_team_member.project_id = params[:team_member][:project_id] - - if @admin_team_member.save - redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully created.' - else - render action: "new" - end - end - def update @admin_team_member = UsersProject.find(params[:id]) - @admin_team_member.project_id = params[:team_member][:project_id] if @admin_team_member.update_attributes(params[:team_member]) - redirect_to admin_team_member_path(@admin_team_member), notice: 'UsersProject was successfully updated.' + redirect_to [:admin, @admin_team_member.project], notice: 'Project Access was successfully updated.' else render action: "edit" end @@ -45,6 +21,6 @@ class Admin::TeamMembersController < ApplicationController @admin_team_member = UsersProject.find(params[:id]) @admin_team_member.destroy - redirect_to admin_team_members_url + redirect_to :back end end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 85a95de5..21643145 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -9,8 +9,28 @@ class Admin::UsersController < ApplicationController def show @admin_user = User.find(params[:id]) + + @projects = if @admin_user.projects.empty? + Project + else + Project.without_user(@admin_user) + end.all end + def team_update + @admin_user = User.find(params[:id]) + + UsersProject.user_bulk_import( + @admin_user, + params[:project_ids], + params[:project_access], + params[:repo_access] + ) + + redirect_to [:admin, @admin_user], notice: 'Teams were successfully updated.' + end + + def new @admin_user = User.new(:projects_limit => 10) end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 00ab93a1..ff00208c 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,7 +5,11 @@ class ApplicationController < ActionController::Base helper_method :abilities, :can? rescue_from Gitlabhq::Gitolite::AccessDenied do |exception| - render :file => File.join(Rails.root, "public", "githost_error"), :layout => false + render "errors/gitolite", :layout => "error" + end + + rescue_from ActiveRecord::RecordNotFound do |exception| + render "errors/not_found", :layout => "error", :status => 404 end layout :layout_by_resource @@ -33,7 +37,8 @@ class ApplicationController < ActionController::Base end def project - @project ||= Project.find_by_code(params[:project_id]) + @project ||= current_user.projects.find_by_code(params[:project_id]) + @project || render_404 end def add_project_abilities @@ -45,11 +50,23 @@ class ApplicationController < ActionController::Base end def authorize_project!(action) - return render_404 unless can?(current_user, action, project) + return access_denied! unless can?(current_user, action, project) + end + + def authorize_code_access! + return access_denied! unless can?(current_user, :download_code, project) end def access_denied! - render_404 + render "errors/access_denied", :layout => "error", :status => 404 + end + + def not_found! + render "errors/not_found", :layout => "error", :status => 404 + end + + def git_not_found! + render "errors/git_not_found", :layout => "error", :status => 404 end def method_missing(method_sym, *arguments, &block) @@ -78,21 +95,13 @@ class ApplicationController < ActionController::Base redirect_to @project unless @project.repo_exists? && @project.has_commits? end - def respond_with_notes - if params[:last_id] && params[:first_id] - @notes = @notes.where("id >= ?", params[:first_id]) - elsif params[:last_id] - @notes = @notes.where("id > ?", params[:last_id]) - elsif params[:first_id] - @notes = @notes.where("id < ?", params[:first_id]) - else - nil - end - end - def no_cache_headers response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" response.headers["Pragma"] = "no-cache" response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" end + + def render_full_content + @full_content = true + end end diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb index a938461f..0d36957c 100644 --- a/app/controllers/commits_controller.rb +++ b/app/controllers/commits_controller.rb @@ -7,12 +7,14 @@ class CommitsController < ApplicationController # Authorize before_filter :add_project_abilities before_filter :authorize_read_project! + before_filter :authorize_code_access! before_filter :require_non_empty_project before_filter :load_refs, :only => :index # load @branch, @tag & @ref + before_filter :render_full_content def index @repo = project.repo - @limit, @offset = (params[:limit] || 20), (params[:offset] || 0) + @limit, @offset = (params[:limit] || 40), (params[:offset] || 0) @commits = @project.commits(@ref, params[:path], @limit, @offset) respond_to do |format| @@ -24,14 +26,31 @@ class CommitsController < ApplicationController def show @commit = project.commit(params[:id]) - @notes = project.commit_notes(@commit).fresh.limit(20) + + git_not_found! and return unless @commit + @note = @project.build_commit_note(@commit) - + @comments_allowed = true @line_notes = project.commit_line_notes(@commit) + end - respond_to do |format| - format.html - format.js { respond_with_notes } + def compare + first = project.commit(params[:to]) + last = project.commit(params[:from]) + + @diffs = [] + @commits = [] + @line_notes = [] + + if first && last + commits = [first, last].sort_by(&:created_at) + younger = commits.first + older = commits.last + + + @commits = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)} + @diffs = project.repo.diff(younger.id, older.id) rescue [] + @commit = Commit.new(older) end end end diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 6a8fd1c3..fe9604ec 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -3,7 +3,16 @@ class DashboardController < ApplicationController def index @projects = current_user.projects.all + @active_projects = @projects.select(&:repo_exists?).select(&:last_activity_date_cached).sort_by(&:last_activity_date_cached).reverse + + @merge_requests = MergeRequest.where("author_id = :id or assignee_id = :id", :id => current_user.id).opened.order("created_at DESC").limit(10) + + @user = current_user + @issues = current_user.assigned_issues.opened.order("created_at DESC").limit(10) + @issues = @issues.includes(:author, :project) + + @events = Event.where(:project_id => @projects.map(&:id)).recent.limit(20) end # Get authored or assigned open merge requests diff --git a/app/controllers/errors_controller.rb b/app/controllers/errors_controller.rb index 3ef7aa46..9f60c645 100644 --- a/app/controllers/errors_controller.rb +++ b/app/controllers/errors_controller.rb @@ -1,5 +1,7 @@ class ErrorsController < ApplicationController + layout "error" + def githost - render :file => File.join(Rails.root, "public", "githost_error"), :layout => false + render "errors/gitolite" end end diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index 7c10d2a8..4e3be259 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -1,6 +1,7 @@ class IssuesController < ApplicationController before_filter :authenticate_user! before_filter :project + before_filter :module_enabled before_filter :issue, :only => [:edit, :update, :destroy, :show] layout "project" @@ -48,7 +49,6 @@ class IssuesController < ApplicationController end def show - @notes = @issue.notes.inc_author.order("created_at DESC").limit(20) @note = @project.notes.new(:noteable => @issue) @commits = if @issue.branch_name && @project.repo.heads.map(&:name).include?(@issue.branch_name) @@ -60,7 +60,7 @@ class IssuesController < ApplicationController respond_to do |format| format.html - format.js { respond_with_notes } + format.js end end @@ -69,7 +69,10 @@ class IssuesController < ApplicationController @issue.author = current_user @issue.save - respond_with(@issue) + respond_to do |format| + format.html { redirect_to project_issue_path(@project, @issue) } + format.js + end end def update @@ -125,11 +128,14 @@ class IssuesController < ApplicationController end def authorize_modify_issue! - can?(current_user, :modify_issue, @issue) || - @issue.assignee == current_user + return render_404 unless can?(current_user, :modify_issue, @issue) end def authorize_admin_issue! - can?(current_user, :admin_issue, @issue) + return render_404 unless can?(current_user, :admin_issue, @issue) + end + + def module_enabled + return render_404 unless @project.issues_enabled end end diff --git a/app/controllers/keys_controller.rb b/app/controllers/keys_controller.rb index 33c6958d..ce49e3e7 100644 --- a/app/controllers/keys_controller.rb +++ b/app/controllers/keys_controller.rb @@ -1,6 +1,6 @@ class KeysController < ApplicationController layout "profile" - respond_to :js + respond_to :js, :html def index @keys = current_user.keys.all diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb index 3456a0a7..cfb9e6dc 100644 --- a/app/controllers/merge_requests_controller.rb +++ b/app/controllers/merge_requests_controller.rb @@ -1,6 +1,7 @@ class MergeRequestsController < ApplicationController before_filter :authenticate_user! before_filter :project + before_filter :module_enabled before_filter :merge_request, :only => [:edit, :update, :destroy, :show, :commits, :diffs] layout "project" @@ -23,7 +24,9 @@ class MergeRequestsController < ApplicationController @merge_requests = @project.merge_requests @merge_requests = case params[:f].to_i + when 1 then @merge_requests when 2 then @merge_requests.closed + when 2 then @merge_requests.opened.assigned(current_user) else @merge_requests.opened end @@ -33,26 +36,31 @@ class MergeRequestsController < ApplicationController def show unless @project.repo.heads.map(&:name).include?(@merge_request.target_branch) && @project.repo.heads.map(&:name).include?(@merge_request.source_branch) - head(404)and return + git_not_found! and return end - @notes = @merge_request.notes.inc_author.order("created_at DESC").limit(20) @note = @project.notes.new(:noteable => @merge_request) + @commits = @project.repo. + commits_between(@merge_request.target_branch, @merge_request.source_branch). + map {|c| Commit.new(c)}. + sort_by(&:created_at). + reverse + + render_full_content + respond_to do |format| format.html - format.js { respond_with_notes } + format.js end end - def commits - @commits = @project.repo.commits_between(@merge_request.target_branch, @merge_request.source_branch).map {|c| Commit.new(c)} - end - def diffs @diffs = @merge_request.diffs @commit = @merge_request.last_commit - @line_notes = [] + + @comments_allowed = true + @line_notes = @merge_request.notes.where("line_code is not null") end def new @@ -105,11 +113,14 @@ class MergeRequestsController < ApplicationController end def authorize_modify_merge_request! - can?(current_user, :modify_merge_request, @merge_request) || - @merge_request.assignee == current_user + return render_404 unless can?(current_user, :modify_merge_request, @merge_request) end def authorize_admin_merge_request! - can?(current_user, :admin_merge_request, @merge_request) + return render_404 unless can?(current_user, :admin_merge_request, @merge_request) + end + + def module_enabled + return render_404 unless @project.merge_requests_enabled end end diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 19c85717..a2638d95 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -9,6 +9,11 @@ class NotesController < ApplicationController respond_to :js + def index + notes + respond_with(@notes) + end + def create @note = @project.notes.new(params[:note]) @note.author = current_user @@ -24,9 +29,7 @@ class NotesController < ApplicationController def destroy @note = @project.notes.find(params[:id]) - return access_denied! unless can?(current_user, :admin_note, @note) - @note.destroy respond_to do |format| @@ -34,4 +37,28 @@ class NotesController < ApplicationController end end + protected + + def notes + @notes = case params[:target_type] + when "commit" + then project.commit_notes(project.commit((params[:target_id]))).fresh.limit(20) + when "snippet" + then project.snippets.find(params[:target_id]).notes + when "wall" + then project.common_notes.order("created_at DESC").fresh.limit(50) + when "issue" + then project.issues.find(params[:target_id]).notes.inc_author.order("created_at DESC").limit(20) + when "merge_request" + then project.merge_requests.find(params[:target_id]).notes.inc_author.order("created_at DESC").limit(20) + end + + @notes = if params[:last_id] + @notes.where("id > ?", params[:last_id]) + elsif params[:first_id] + @notes.where("id < ?", params[:first_id]) + else + @notes + end + end end diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb new file mode 100644 index 00000000..629b6819 --- /dev/null +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -0,0 +1,13 @@ +class OmniauthCallbacksController < Devise::OmniauthCallbacksController + + def ldap + # We only find ourselves here if the authentication to LDAP was successful. + info = request.env["omniauth.auth"]["info"] + @user = User.find_for_ldap_auth(info) + if @user.persisted? + @user.remember_me = true + end + sign_in_and_redirect @user + end + +end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6bd72a86..26eabe5f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -28,7 +28,7 @@ class ProjectsController < ApplicationController Project.transaction do @project.save! - @project.users_projects.create!(:repo_access => Repository::REPO_RW , :project_access => Project::PROJECT_RWA, :user => current_user) + @project.users_projects.create!(:project_access => UsersProject::MASTER, :user => current_user) # when project saved no team member exist so # project repository should be updated after first user add @@ -57,7 +57,7 @@ class ProjectsController < ApplicationController def update respond_to do |format| if project.update_attributes(params[:project]) - format.html { redirect_to info_project_path(project), :notice => 'Project was successfully updated.' } + format.html { redirect_to edit_project_path(project), :notice => 'Project was successfully updated.' } format.js else format.html { render action: "edit" } @@ -68,33 +68,29 @@ class ProjectsController < ApplicationController def show return render "projects/empty" unless @project.repo_exists? && @project.has_commits? - limit = (params[:limit] || 20).to_i - @activities = @project.activities(limit)#updates_wo_repo(limit) + limit = (params[:limit] || 10).to_i + @activities = @project.activities(limit) end def files @notes = @project.notes.where("attachment != 'NULL'").order("created_at DESC").limit(100) end - def info - end - # # Wall # def wall + return render_404 unless @project.wall_enabled @note = Note.new - @notes = @project.common_notes.order("created_at DESC") - @notes = @notes.fresh.limit(20) respond_to do |format| format.html - format.js { respond_with_notes } end end def graph + render_full_content @days_json, @commits_json = GraphCommit.to_graph(project) end @@ -114,6 +110,7 @@ class ProjectsController < ApplicationController def project @project ||= Project.find_by_code(params[:id]) + @project || render_404 end def determine_layout diff --git a/app/controllers/protected_branches_controller.rb b/app/controllers/protected_branches_controller.rb new file mode 100644 index 00000000..0b86f525 --- /dev/null +++ b/app/controllers/protected_branches_controller.rb @@ -0,0 +1,32 @@ +class ProtectedBranchesController < ApplicationController + before_filter :project + + # Authorize + before_filter :add_project_abilities + before_filter :authorize_read_project! + before_filter :require_non_empty_project + + before_filter :authorize_admin_project!, :only => [:destroy, :create] + before_filter :render_full_content + + layout "project" + + def index + @branches = @project.protected_branches.all + @protected_branch = @project.protected_branches.new + end + + def create + @project.protected_branches.create(params[:protected_branch]) + redirect_to project_protected_branches_path(@project) + end + + def destroy + @project.protected_branches.find(params[:id]).destroy + + respond_to do |format| + format.html { redirect_to project_protected_branches_path } + format.js { render :nothing => true } + end + end +end diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb index d2be5ad5..b8ab1bce 100644 --- a/app/controllers/refs_controller.rb +++ b/app/controllers/refs_controller.rb @@ -4,20 +4,32 @@ class RefsController < ApplicationController # Authorize before_filter :add_project_abilities before_filter :authorize_read_project! + before_filter :authorize_code_access! before_filter :require_non_empty_project before_filter :ref before_filter :define_tree_vars, :only => [:tree, :blob] + before_filter :render_full_content + layout "project" def switch - new_path = if params[:destination] == "tree" - tree_project_ref_path(@project, params[:ref]) - else - project_commits_path(@project, :ref => params[:ref]) - end + respond_to do |format| + format.html do + new_path = if params[:destination] == "tree" + tree_project_ref_path(@project, params[:ref]) + else + project_commits_path(@project, :ref => params[:ref]) + end - redirect_to new_path + redirect_to new_path + end + format.js do + @ref = params[:ref] + define_tree_vars + render "tree" + end + end end # @@ -37,7 +49,12 @@ class RefsController < ApplicationController def blob if @tree.is_blob? - send_data(@tree.data, :type => @tree.mime_type, :disposition => 'inline', :filename => @tree.name) + send_data( + @tree.data, + :type => @tree.text? ? "text/plain" : @tree.mime_type, + :disposition => 'inline', + :filename => @tree.name + ) else head(404) end @@ -48,6 +65,8 @@ class RefsController < ApplicationController protected def define_tree_vars + params[:path] = nil if params[:path].blank? + @repo = project.repo @commit = project.commit(@ref) @tree = Tree.new(@commit.tree, project, @ref, params[:path]) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 1e715931..036eb371 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -4,7 +4,9 @@ class RepositoriesController < ApplicationController # Authorize before_filter :add_project_abilities before_filter :authorize_read_project! + before_filter :authorize_code_access! before_filter :require_non_empty_project + before_filter :render_full_content layout "project" @@ -19,4 +21,28 @@ class RepositoriesController < ApplicationController def tags @tags = @project.repo.tags.sort_by(&:name).reverse end + + def archive + unless can?(current_user, :download_code, @project) + render_404 and return + end + + ref = params[:ref] || @project.root_ref + commit = @project.commit(ref) + render_404 and return unless commit + + # Build file path + file_name = @project.code + "-" + commit.id.to_s + ".tar.gz" + storage_path = File.join(Rails.root, "tmp", "repositories", @project.code) + file_path = File.join(storage_path, file_name) + + # Create file if not exists + unless File.exists?(file_path) + FileUtils.mkdir_p storage_path + file = @project.repo.archive_to_file(ref, nil, file_path) + end + + # Send file to user + send_file file_path + end end diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb index 45b3f529..bfcfda0f 100644 --- a/app/controllers/snippets_controller.rb +++ b/app/controllers/snippets_controller.rb @@ -1,6 +1,7 @@ class SnippetsController < ApplicationController before_filter :authenticate_user! before_filter :project + before_filter :snippet, :only => [:show, :edit, :destroy, :update] layout "project" # Authorize @@ -41,11 +42,9 @@ class SnippetsController < ApplicationController end def edit - @snippet = @project.snippets.find(params[:id]) end def update - @snippet = @project.snippets.find(params[:id]) @snippet.update_attributes(params[:snippet]) if @snippet.valid? @@ -56,14 +55,11 @@ class SnippetsController < ApplicationController end def show - @snippet = @project.snippets.find(params[:id]) - @notes = @snippet.notes @note = @project.notes.new(:noteable => @snippet) + render_full_content end def destroy - @snippet = @project.snippets.find(params[:id]) - return access_denied! unless can?(current_user, :admin_snippet, @snippet) @snippet.destroy @@ -72,12 +68,15 @@ class SnippetsController < ApplicationController end protected + def snippet + @snippet ||= @project.snippets.find(params[:id]) + end def authorize_modify_snippet! - can?(current_user, :modify_snippet, @snippet) + return render_404 unless can?(current_user, :modify_snippet, @snippet) end def authorize_admin_snippet! - can?(current_user, :admin_snippet, @snippet) + return render_404 unless can?(current_user, :admin_snippet, @snippet) end end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb deleted file mode 100644 index 938beb64..00000000 --- a/app/controllers/tags_controller.rb +++ /dev/null @@ -1,11 +0,0 @@ -class TagsController < ApplicationController - def index - @tags = Project.tag_counts.order('count DESC') - @tags = @tags.where('name like ?', "%#{params[:term]}%") unless params[:term].blank? - - respond_to do |format| - format.html - format.json { render json: @tags.limit(8).map {|t| t.name}} - end - end -end diff --git a/app/controllers/team_members_controller.rb b/app/controllers/team_members_controller.rb index c05602f9..ab51c19e 100644 --- a/app/controllers/team_members_controller.rb +++ b/app/controllers/team_members_controller.rb @@ -40,7 +40,7 @@ class TeamMembersController < ApplicationController @team_member.destroy respond_to do |format| - format.html { redirect_to root_path } + format.html { redirect_to team_project_path(@project) } format.js { render :nothing => true } end end diff --git a/app/controllers/wikis_controller.rb b/app/controllers/wikis_controller.rb new file mode 100644 index 00000000..9bcd20c3 --- /dev/null +++ b/app/controllers/wikis_controller.rb @@ -0,0 +1,59 @@ +class WikisController < ApplicationController + before_filter :project + before_filter :add_project_abilities + before_filter :authorize_read_wiki! + before_filter :authorize_write_wiki!, :only => [:edit, :create, :history] + before_filter :authorize_admin_wiki!, :only => :destroy + layout "project" + + def show + if params[:old_page_id] + @wiki = @project.wikis.find(params[:old_page_id]) + else + @wiki = @project.wikis.where(:slug => params[:id]).order("created_at").last + end + + unless @wiki + return render_404 unless can?(current_user, :write_wiki, @project) + end + + respond_to do |format| + if @wiki + format.html + else + @wiki = @project.wikis.new(:slug => params[:id]) + format.html { render "edit" } + end + end + end + + def edit + @wiki = @project.wikis.where(:slug => params[:id]).order("created_at").last + @wiki = Wiki.regenerate_from @wiki + end + + def create + @wiki = @project.wikis.new(params[:wiki]) + @wiki.user = current_user + + respond_to do |format| + if @wiki.save + format.html { redirect_to [@project, @wiki], notice: 'Wiki was successfully updated.' } + else + format.html { render action: "edit" } + end + end + end + + def history + @wikis = @project.wikis.where(:slug => params[:id]).order("created_at") + end + + def destroy + @wikis = @project.wikis.where(:slug => params[:id]).delete_all + + respond_to do |format| + format.html { redirect_to project_wiki_path(@project, :index), notice: "Page was successfully deleted" } + end + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9f0f1e68..12fe333a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -3,7 +3,8 @@ module ApplicationHelper def gravatar_icon(user_email, size = 40) gravatar_host = request.ssl? ? "https://secure.gravatar.com" : "http://www.gravatar.com" - "#{gravatar_host}/avatar/#{Digest::MD5.hexdigest(user_email)}?s=#{size}&d=identicon" + user_email.strip! + "#{gravatar_host}/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=identicon" end def fixed_mode? @@ -52,6 +53,13 @@ module ApplicationHelper [ "Tag", @project.tags ] ] + # If reference is commit id - + # we should add it to branch/tag selectbox + if(@ref && !options.flatten.include?(@ref) && + @ref =~ /^[0-9a-zA-Z]{6,52}$/) + options << ["Commit", [@ref]] + end + grouped_options_for_select(options, @ref || @project.default_branch) end @@ -71,11 +79,11 @@ module ApplicationHelper if @project && !@project.new_record? project_nav = [ - { :label => "#{@project.code} / Issues", :url => project_issues_path(@project) }, - { :label => "#{@project.code} / Wall", :url => wall_project_path(@project) }, - { :label => "#{@project.code} / Tree", :url => tree_project_ref_path(@project, @project.root_ref) }, - { :label => "#{@project.code} / Commits", :url => project_commits_path(@project) }, - { :label => "#{@project.code} / Team", :url => team_project_path(@project) } + { :label => "#{@project.name} / Issues", :url => project_issues_path(@project) }, + { :label => "#{@project.name} / Wall", :url => wall_project_path(@project) }, + { :label => "#{@project.name} / Tree", :url => tree_project_ref_path(@project, @project.root_ref) }, + { :label => "#{@project.name} / Commits", :url => project_commits_path(@project) }, + { :label => "#{@project.name} / Team", :url => team_project_path(@project) } ] end @@ -83,14 +91,26 @@ module ApplicationHelper end def project_layout - @project && !@project.new_record? + layout == "project" + end + + def admin_layout + layout == "admin" end def profile_layout - controller.controller_name == "dashboard" || current_page?(projects_path) || controller.controller_name == "profile" || controller.controller_name == "keys" + layout == "profile" end def help_layout controller.controller_name == "help" end + + def ldap_enable? + Devise.omniauth_providers.include?(:ldap) + end + + def layout + controller.send :_layout + end end diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb index 4607e9da..d097c271 100644 --- a/app/helpers/commits_helper.rb +++ b/app/helpers/commits_helper.rb @@ -7,16 +7,6 @@ module CommitsHelper end - def diff_line_class(line) - if line[0] == "+" - "new" - elsif line[0] == "-" - "old" - else - nil - end - end - def more_commits_link offset = params[:offset] || 0 limit = params[:limit] || 100 @@ -42,11 +32,58 @@ module CommitsHelper preserve out end - def build_line_code(line, index, line_new, line_old) - if diff_line_class(line) == "new" - "NEW_#{index}_#{line_new}" + def diff_line_class(line) + if line[0] == "+" + "new" + elsif line[0] == "-" + "old" else - "OLD_#{index}_#{line_old}" + nil + end + end + + def build_line_code(line, index, line_new, line_old) + "#{index}_#{line_old}_#{line_new}" + end + + def each_diff_line(diff_arr, index) + line_old = 1 + line_new = 1 + type = nil + + lines_arr = diff_arr + lines_arr.each do |line| + next if line.match(/^\-\-\- \/dev\/null/) + next if line.match(/^\+\+\+ \/dev\/null/) + next if line.match(/^\-\-\- a/) + next if line.match(/^\+\+\+ b/) + + full_line = html_escape(line.gsub(/\n/, '')).force_encoding("UTF-8") + + if line.match(/^@@ -/) + type = "match" + + line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0 + line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0 + + next if line_old == 1 && line_new == 1 + yield(line, type, nil, nil, nil) + next + else + type = diff_line_class(line) + line_code = build_line_code(line, index, line_new, line_old) + yield(full_line, type, line_code, line_new, line_old) + end + + + if line[0] == "+" + line_new += 1 + elsif line[0] == "-" + line_old += 1 + else + line_new += 1 + line_old += 1 + end end end end diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb index 5cf10278..55ed901c 100644 --- a/app/helpers/dashboard_helper.rb +++ b/app/helpers/dashboard_helper.rb @@ -3,6 +3,7 @@ module DashboardHelper case object.class.name.to_s when "Issue" then project_issue_path(project, project.issues.find(object.id)) when "Commit" then project_commit_path(project, project.repo.commits(object.id).first) + when "MergeRequest" then project_merge_request_path(project, object.id) when "Note" then note = object @@ -26,6 +27,7 @@ module DashboardHelper when "Note" then markdown(object.note) when "Issue" then object.title when "Commit" then object.safe_message + when "MergeRequest" then object.title else return "Project Wall" end diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index d09fad5f..d902be0e 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -9,4 +9,26 @@ module IssuesHelper params[:f] ||= cookies['issue_filter'] project_issues_path project, params end + + def link_to_issue_assignee(issue) + project = issue.project + + tm = project.team_member_by_id(issue.assignee_id) + if tm + link_to issue.assignee_name, project_team_member_path(project, tm), :class => "author_link" + else + issue.assignee_name + end + end + + def link_to_issue_author(issue) + project = issue.project + + tm = project.team_member_by_id(issue.author_id) + if tm + link_to issue.author_name, project_team_member_path(project, tm), :class => "author_link" + else + issue.author_name + end + end end diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index fac9870f..afdf65bd 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -1,2 +1,23 @@ module MergeRequestsHelper + def link_to_merge_request_assignee(merge_request) + project = merge_request.project + + tm = project.team_member_by_id(merge_request.assignee_id) + if tm + link_to merge_request.assignee_name, project_team_member_path(project, tm), :class => "author_link" + else + merge_request.assignee_name + end + end + + def link_to_merge_request_author(merge_request) + project = merge_request.project + + tm = project.team_member_by_id(merge_request.author_id) + if tm + link_to merge_request.author_name, project_team_member_path(project, tm), :class => "author_link" + else + merge_request.author_name + end + end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 817ab475..16e3d9d0 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -17,11 +17,13 @@ module ProjectsHelper end def project_tab_class - [:show, :files, :team, :edit, :update, :info].each do |action| + [:show, :files, :team, :edit, :update].each do |action| return "current" if current_page?(:controller => "projects", :action => action, :id => @project) end if controller.controller_name == "snippets" || + controller.controller_name == "hooks" || + controller.controller_name == "deploy_keys" || controller.controller_name == "team_members" "current" end @@ -33,9 +35,26 @@ module ProjectsHelper end def repository_tab_class - if controller.controller_name == "repositories" || - controller.controller_name == "hooks" - "current" + #if controller.controller_name == "repositories" || + #controller.controller_name == "hooks" || + #controller.controller_name == "deploy_keys" + #"current" + #end + end + + def commit_tab_class + if controller.controller_name == "commits" || + controller.controller_name == "repositories" || + controller.controller_name == "protected_branches" + "current" + end + end + + def branches_tab_class + if current_page?(branches_project_repository_path(@project)) || + controller.controller_name == "protected_branches" || + current_page?(project_repository_path(@project)) + 'active' end end end diff --git a/app/helpers/wikis_helper.rb b/app/helpers/wikis_helper.rb new file mode 100644 index 00000000..0c24f57a --- /dev/null +++ b/app/helpers/wikis_helper.rb @@ -0,0 +1,5 @@ +module WikisHelper + def markdown_to_html(text) + RDiscount.new(text).to_html.html_safe + end +end diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb index 6f408125..50ccb991 100644 --- a/app/mailers/notify.rb +++ b/app/mailers/notify.rb @@ -27,8 +27,7 @@ class Notify < ActionMailer::Base @user = user @note = note @project = note.project - @commit = @project.repo.commits(note.noteable_id).first - return unless ( note.notify or ( note.notify_author and @commit.author.email == @user.email ) ) + @commit = @note.target mail(:to => @user.email, :subject => "gitlab | note for commit | #{@note.project.name} ") end diff --git a/app/models/ability.rb b/app/models/ability.rb index a02f44a4..e97b662b 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -5,6 +5,7 @@ class Ability when "Issue" then issue_abilities(object, subject) when "Note" then note_abilities(object, subject) when "Snippet" then snippet_abilities(object, subject) + when "MergeRequest" then merge_request_abilities(object, subject) else [] end end @@ -14,31 +15,40 @@ class Ability rules << [ :read_project, + :read_wiki, :read_issue, :read_snippet, :read_team_member, :read_merge_request, - :read_note - ] if project.allow_read_for?(user) - - rules << [ + :read_note, :write_project, :write_issue, - :write_snippet, - :write_merge_request, :write_note - ] if project.allow_write_for?(user) + ] if project.guest_access_for?(user) + + rules << [ + :download_code, + :write_merge_request, + :write_snippet + ] if project.report_access_for?(user) + + rules << [ + :write_wiki + ] if project.dev_access_for?(user) rules << [ :modify_issue, :modify_snippet, + :modify_merge_request, :admin_project, :admin_issue, :admin_snippet, :admin_team_member, :admin_merge_request, - :admin_note - ] if project.allow_admin_for?(user) + :admin_note, + :admin_wiki + ] if project.master_access_for?(user) || project.owner == user + rules.flatten end @@ -53,6 +63,12 @@ class Ability :"modify_#{name}", :"admin_#{name}" ] + elsif subject.respond_to?(:assignee) && subject.assignee == user + [ + :"read_#{name}", + :"write_#{name}", + :"modify_#{name}", + ] else subject.respond_to?(:project) ? project_abilities(user, subject.project) : [] diff --git a/app/models/activity_observer.rb b/app/models/activity_observer.rb new file mode 100644 index 00000000..46564161 --- /dev/null +++ b/app/models/activity_observer.rb @@ -0,0 +1,12 @@ +class ActivityObserver < ActiveRecord::Observer + observe :issue, :merge_request, :note + + def after_create(record) + Event.create( + :project => record.project, + :target_id => record.id, + :target_type => record.class.name, + :action => Event.determine_action(record) + ) + end +end diff --git a/app/models/commit.rb b/app/models/commit.rb index 695dfa52..a59e8803 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -1,14 +1,18 @@ class Commit + include ActiveModel::Conversion + extend ActiveModel::Naming attr_accessor :commit attr_accessor :head attr_accessor :refs delegate :message, + :authored_date, :committed_date, :parents, :sha, :date, + :committer, :author, :message, :diffs, @@ -16,6 +20,10 @@ class Commit :id, :to => :commit + def persisted? + false + end + def initialize(raw_commit, head = nil) @commit = raw_commit @head = head @@ -34,10 +42,22 @@ class Commit end def author_name - author.name + author.name.force_encoding("UTF-8") + end + + def committer_name + committer.name + end + + def committer_email + committer.email end def prev_commit parents.first end + + def prev_commit_id + prev_commit.id + end end diff --git a/app/models/event.rb b/app/models/event.rb new file mode 100644 index 00000000..e1732f00 --- /dev/null +++ b/app/models/event.rb @@ -0,0 +1,70 @@ +class Event < ActiveRecord::Base + Created = 1 + Updated = 2 + Closed = 3 + Reopened = 4 + Pushed = 5 + Commented = 6 + + belongs_to :project + belongs_to :target, :polymorphic => true + + serialize :data + + scope :recent, order("created_at DESC") + + def self.determine_action(record) + if [Issue, MergeRequest].include? record.class + Event::Created + elsif record.kind_of? Note + Event::Commented + end + end + + def push? + action == self.class::Pushed + end + + def new_branch? + data[:before] =~ /^00000/ + end + + def commit_from + data[:before] + end + + def commit_to + data[:after] + end + + def branch_name + @branch_name ||= data[:ref].gsub("refs/heads/", "") + end + + def pusher + User.find_by_id(data[:user_id]) + end + + def commits + @commits ||= data[:commits].map do |commit| + project.commit(commit[:id]) + end + end + + delegate :id, :name, :email, :to => :pusher, :prefix => true, :allow_nil => true +end +# == Schema Information +# +# Table name: events +# +# id :integer not null, primary key +# target_type :string(255) +# target_id :integer +# title :string(255) +# data :text +# project_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# action :integer +# + diff --git a/app/models/key.rb b/app/models/key.rb index fb59d759..4114e526 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -14,6 +14,7 @@ class Key < ActiveRecord::Base before_save :set_identifier after_save :update_repository after_destroy :repository_delete_key + delegate :name, :email, :to => :user, :prefix => true def set_identifier if is_deploy_key diff --git a/app/models/mailer_observer.rb b/app/models/mailer_observer.rb index 2bf383e5..f84cbdea 100644 --- a/app/models/mailer_observer.rb +++ b/app/models/mailer_observer.rb @@ -27,20 +27,25 @@ class MailerObserver < ActiveRecord::Observer end def new_note(note) - return unless note.notify or note.notify_author - note.project.users.reject { |u| u.id == current_user.id } .each do |u| - case note.noteable_type - when "Commit" then - Notify.note_commit_email(u, note).deliver - when "Issue" then - Notify.note_issue_email(u, note).deliver - when "MergeRequest" then - Notify.note_merge_request_email(u, note).deliver - when "Snippet" - true - else - Notify.note_wall_email(u, note).deliver + # Notify whole team except author of note + if note.notify + note.project.users.reject { |u| u.id == current_user.id } .each do |u| + case note.noteable_type + when "Commit" then + Notify.note_commit_email(u, note).deliver + when "Issue" then + Notify.note_issue_email(u, note).deliver + when "MergeRequest" then + Notify.note_merge_request_email(u, note).deliver + when "Snippet" + true + else + Notify.note_wall_email(u, note).deliver + end end + # Notify only author of resource + elsif note.notify_author + Notify.note_commit_email(note.commit_author, note).deliver end end diff --git a/app/models/note.rb b/app/models/note.rb index f499b62d..581f7833 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -58,21 +58,34 @@ class Note < ActiveRecord::Base nil end - def line_file_id - @line_file_id ||= line_code.split("_")[1].to_i if line_code + # Check if we can notify commit author + # with email about our comment + # + # If commit author email exist in project + # and commit author is not passed user we can + # send email to him + # + # params: + # user - current user + # + # return: + # Boolean + # + def notify_only_author?(user) + commit? && commit_author && + commit_author.email != user.email end - def line_type_id - @line_type_id ||= line_code.split("_").first if line_code + def commit? + noteable_type == "Commit" end - def line_number - @line_number ||= line_code.split("_").last.to_i if line_code - end - - def for_line?(file_id, old_line, new_line) - line_file_id == file_id && - ((line_type_id == "NEW" && line_number == new_line) || (line_type_id == "OLD" && line_number == old_line )) + def commit_author + @commit_author ||= + project.users.find_by_email(target.author_email) || + project.users.find_by_name(target.author_name) + rescue + nil end end # == Schema Information diff --git a/app/models/project.rb b/app/models/project.rb index e1c66c95..c9b6f73b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1,13 +1,9 @@ require "grit" class Project < ActiveRecord::Base - PROJECT_N = 0 - PROJECT_R = 1 - PROJECT_RW = 2 - PROJECT_RWA = 3 - belongs_to :owner, :class_name => "User" + has_many :events, :dependent => :destroy has_many :merge_requests, :dependent => :destroy has_many :issues, :dependent => :destroy, :order => "position" has_many :users_projects, :dependent => :destroy @@ -16,6 +12,8 @@ class Project < ActiveRecord::Base has_many :snippets, :dependent => :destroy has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key" has_many :web_hooks, :dependent => :destroy + has_many :protected_branches, :dependent => :destroy + has_many :wikis, :dependent => :destroy acts_as_taggable @@ -53,18 +51,14 @@ class Project < ActiveRecord::Base attr_protected :private_flag, :owner_id scope :public_only, where(:private_flag => false) + scope :without_user, lambda { |user| where("id not in (:ids)", :ids => user.projects.map(&:id) ) } def self.active joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC") end def self.access_options - { - "Denied" => PROJECT_N, - "Read" => PROJECT_R, - "Report" => PROJECT_RW, - "Admin" => PROJECT_RWA - } + UsersProject.access_roles end def repository @@ -96,21 +90,35 @@ class Project < ActiveRecord::Base [GIT_HOST['host'], code].join("/") end - def execute_web_hooks(oldrev, newrev, ref) + def observe_push(oldrev, newrev, ref, author_key_id) + data = web_hook_data(oldrev, newrev, ref, author_key_id) + + Event.create( + :project => self, + :action => Event::Pushed, + :data => data + ) + end + + def execute_web_hooks(oldrev, newrev, ref, author_key_id) ref_parts = ref.split('/') # Return if this is not a push to a branch (e.g. new commits) return if ref_parts[1] !~ /heads/ || oldrev == "00000000000000000000000000000000" - data = web_hook_data(oldrev, newrev, ref) + data = web_hook_data(oldrev, newrev, ref, author_key_id) + web_hooks.each { |web_hook| web_hook.execute(data) } end - def web_hook_data(oldrev, newrev, ref) + def web_hook_data(oldrev, newrev, ref, author_key_id) + key = Key.find_by_identifier(author_key_id) data = { before: oldrev, after: newrev, ref: ref, + user_id: key.user.id, + user_name: key.user_name, repository: { name: name, url: web_url, @@ -137,6 +145,15 @@ class Project < ActiveRecord::Base data end + def open_branches + if protected_branches.empty? + self.repo.heads + else + pnames = protected_branches.map(&:name) + self.repo.heads.reject { |h| pnames.include?(h.name) } + end.sort_by(&:name) + end + def team_member_by_name_or_email(email = nil, name = nil) user = users.where("email like ? or name like ?", email, name).first users_projects.find_by_user_id(user.id) if user @@ -182,11 +199,11 @@ class Project < ActiveRecord::Base # Should be rewrited for new access rights def add_access(user, *access) access = if access.include?(:admin) - { :project_access => PROJECT_RWA } + { :project_access => UsersProject::MASTER } elsif access.include?(:write) - { :project_access => PROJECT_RW } + { :project_access => UsersProject::DEVELOPER } else - { :project_access => PROJECT_R } + { :project_access => UsersProject::REPORTER } end opts = { :user => user } opts.merge!(access) @@ -199,38 +216,52 @@ class Project < ActiveRecord::Base def repository_readers keys = Key.joins({:user => :users_projects}). - where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_R) + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::REPORTER) keys.map(&:identifier) + deploy_keys.map(&:identifier) end def repository_writers keys = Key.joins({:user => :users_projects}). - where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_RW) + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::DEVELOPER) + keys.map(&:identifier) + end + + def repository_masters + keys = Key.joins({:user => :users_projects}). + where("users_projects.project_id = ? AND users_projects.project_access = ?", id, UsersProject::MASTER) keys.map(&:identifier) end def readers - @readers ||= users_projects.includes(:user).where(:project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).map(&:user) + @readers ||= users_projects.includes(:user).map(&:user) end def writers - @writers ||= users_projects.includes(:user).where(:project_access => [PROJECT_RW, PROJECT_RWA]).map(&:user) + @writers ||= users_projects.includes(:user).map(&:user) end def admins - @admins ||= users_projects.includes(:user).where(:project_access => PROJECT_RWA).map(&:user) + @admins ||= users_projects.includes(:user).where(:project_access => UsersProject::MASTER).map(&:user) end def allow_read_for?(user) - !users_projects.where(:user_id => user.id, :project_access => [PROJECT_R, PROJECT_RW, PROJECT_RWA]).empty? + !users_projects.where(:user_id => user.id).empty? end - def allow_write_for?(user) - !users_projects.where(:user_id => user.id, :project_access => [PROJECT_RW, PROJECT_RWA]).empty? + def guest_access_for?(user) + !users_projects.where(:user_id => user.id).empty? end - def allow_admin_for?(user) - !users_projects.where(:user_id => user.id, :project_access => [PROJECT_RWA]).empty? || owner_id == user.id + def report_access_for?(user) + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty? + end + + def dev_access_for?(user) + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty? + end + + def master_access_for?(user) + !users_projects.where(:user_id => user.id, :project_access => [UsersProject::MASTER]).empty? || owner_id == user.id end def root_ref @@ -335,15 +366,19 @@ end # # Table name: projects # -# id :integer not null, primary key -# name :string(255) -# path :string(255) -# description :text -# created_at :datetime -# updated_at :datetime -# private_flag :boolean default(TRUE), not null -# code :string(255) -# owner_id :integer -# default_branch :string(255) default("master"), not null +# id :integer not null, primary key +# name :string(255) +# path :string(255) +# description :text +# created_at :datetime +# updated_at :datetime +# private_flag :boolean default(TRUE), not null +# code :string(255) +# owner_id :integer +# default_branch :string(255) default("master"), not null +# issues_enabled :boolean default(TRUE), not null +# wall_enabled :boolean default(TRUE), not null +# merge_requests_enabled :boolean default(TRUE), not null +# wiki_enabled :boolean default(TRUE), not null # diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb new file mode 100644 index 00000000..9c2d391d --- /dev/null +++ b/app/models/protected_branch.rb @@ -0,0 +1,29 @@ +class ProtectedBranch < ActiveRecord::Base + belongs_to :project + validates_presence_of :project_id + validates_presence_of :name + + after_save :update_repository + after_destroy :update_repository + + def update_repository + Gitlabhq::GitHost.system.new.configure do |c| + c.update_project(project.path, project) + end + end + + def commit + project.commit(self.name) + end +end +# == Schema Information +# +# Table name: protected_branches +# +# id :integer not null, primary key +# project_id :integer not null +# name :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# + diff --git a/app/models/repository.rb b/app/models/repository.rb index f4fdfe54..1e78e588 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -1,10 +1,6 @@ require File.join(Rails.root, "lib", "gitlabhq", "git_host") class Repository - REPO_N = 0 - REPO_R = 1 - REPO_RW = 2 - attr_accessor :project def self.default_ref @@ -12,11 +8,7 @@ class Repository end def self.access_options - { - "Denied" => REPO_N, - "Pull" => REPO_R, - "Pull & Push" => REPO_RW - } + {} end def initialize(project) @@ -56,7 +48,7 @@ class Repository end def path_to_repo - GIT_HOST["base_path"] + path + ".git" + File.join(GIT_HOST["base_path"], "#{path}.git") end def update_repository diff --git a/app/models/user.rb b/app/models/user.rb index a13a6f77..942f3337 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,7 +2,7 @@ class User < ActiveRecord::Base # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :token_authenticatable, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :trackable, :validatable, :omniauthable # Setup accessible (or protected) attributes for your model attr_accessible :email, :password, :password_confirmation, :remember_me, @@ -62,6 +62,30 @@ class User < ActiveRecord::Base def last_activity_project projects.first end + + def self.generate_random_password + (0...8).map{ ('a'..'z').to_a[rand(26)] }.join + end + + def first_name + name.split(" ").first unless name.blank? + end + + def self.find_for_ldap_auth(omniauth_info) + name = omniauth_info.name + email = omniauth_info.email + + if @user = User.find_by_email(email) + @user + else + password = generate_random_password + @user = User.create(:name => name, + :email => email, + :password => password, + :password_confirmation => password + ) + end + end end # == Schema Information # diff --git a/app/models/users_project.rb b/app/models/users_project.rb index b98aa1fd..726a85ae 100644 --- a/app/models/users_project.rb +++ b/app/models/users_project.rb @@ -1,4 +1,9 @@ class UsersProject < ActiveRecord::Base + GUEST = 10 + REPORTER = 20 + DEVELOPER = 30 + MASTER = 40 + belongs_to :user belongs_to :project @@ -17,7 +22,6 @@ class UsersProject < ActiveRecord::Base UsersProject.transaction do user_ids.each do |user_id| users_project = UsersProject.new( - :repo_access => repo_access, :project_access => project_access, :user_id => user_id ) @@ -27,11 +31,45 @@ class UsersProject < ActiveRecord::Base end end + def self.user_bulk_import(user, project_ids, project_access, repo_access) + UsersProject.transaction do + project_ids.each do |project_id| + users_project = UsersProject.new( + :project_access => project_access, + ) + users_project.project_id = project_id + users_project.user_id = user.id + users_project.save + end + end + end + + def self.access_roles + { + "Guest" => GUEST, + "Reporter" => REPORTER, + "Developer" => DEVELOPER, + "Master" => MASTER + } + end + + def role_access + project_access + end + def update_repository Gitlabhq::GitHost.system.new.configure do |c| c.update_project(project.path, project) end end + + def project_access_human + Project.access_options.key(self.project_access) + end + + def repo_access_human + "" + end end # == Schema Information # @@ -42,7 +80,6 @@ end # project_id :integer not null # created_at :datetime # updated_at :datetime -# repo_access :integer default(0), not null # project_access :integer default(0), not null # diff --git a/app/models/wiki.rb b/app/models/wiki.rb new file mode 100644 index 00000000..ad3e4a38 --- /dev/null +++ b/app/models/wiki.rb @@ -0,0 +1,47 @@ +class Wiki < ActiveRecord::Base + belongs_to :project + belongs_to :user + + validates :content, :title, :user_id, :presence => true + validates :title, :length => 1..250 + + before_update :set_slug + + + def to_param + slug + end + + protected + + def set_slug + self.slug = self.title.parameterize + end + + class << self + def regenerate_from wiki + regenerated_field = [:slug, :content, :title] + + new_wiki = Wiki.new + regenerated_field.each do |field| + new_wiki.send("#{field}=", wiki.send(field)) + end + new_wiki + end + + end +end +# == Schema Information +# +# Table name: wikis +# +# id :integer not null, primary key +# title :string(255) +# content :text +# project_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# slug :string(255) +# user_id :integer +# + diff --git a/app/views/admin/projects/_form.html.haml b/app/views/admin/projects/_form.html.haml index ea42ed22..4f6bc692 100644 --- a/app/views/admin/projects/_form.html.haml +++ b/app/views/admin/projects/_form.html.haml @@ -1,39 +1,66 @@ = form_for [:admin, @admin_project] do |f| -if @admin_project.errors.any? - #error_explanation - %h2= "#{pluralize(@admin_project.errors.count, "error")} prohibited this admin_project from being saved:" + .alert-message.block-message.error %ul - @admin_project.errors.full_messages.each do |msg| %li= msg - .form-row + .clearfix = f.label :name - %br - = f.text_field :name - .form-row - = f.label :code - %br - = f.text_field :code - .form-row - = f.label :path - %br - = f.text_field :path + .input= f.text_field :name + .clearfix + = f.label :path do + Path + .input + .input-prepend + %span.add-on= "git@#{GIT_HOST["host"]}:" + = f.text_field :path, :placeholder => "example_project", :disabled => !@admin_project.new_record? + .clearfix + = f.label :code do + Code + .input + .input-prepend + %span.add-on= "http://#{GIT_HOST["host"]}/" + = f.text_field :code, :placeholder => "example" - .form-row - = f.label :tag_list - %br - = f.text_area :tag_list, :placeholder => "project tags", :style => "height:50px", :id => :tag_field + - unless @admin_project.new_record? + .clearfix + = f.label :owner_id + .input= f.select :owner_id, User.all.map { |user| [user.name, user.id] } - .form-row + - unless @admin_project.heads.empty? + .clearfix + = f.label :default_branch, "Default Branch" + .input= f.select(:default_branch, @admin_project.heads.map(&:name), {}, :style => "width:210px;") + + .well + %h5 Features + + .clearfix + = f.label :issues_enabled, "Issues" + .input= f.check_box :issues_enabled + + .clearfix + = f.label :merge_requests_enabled, "Merge Requests" + .input= f.check_box :merge_requests_enabled + + .clearfix + = f.label :wall_enabled, "Wall" + .input= f.check_box :wall_enabled + + .clearfix = f.label :description - %br - = f.text_area :description + .input= f.text_area :description, :class => "xxlarge" .clear %br .actions - = f.submit 'Save', :class => "grey-button" + = f.submit 'Save', :class => "btn primary" + = link_to 'Cancel', [:admin, @admin_project], :class => "btn" + = link_to 'Destroy', [:admin, @admin_project], :confirm => 'Are you sure?', :method => :delete, :class => "btn danger right" :javascript $(function(){ taggifyForm(); + $('#project_owner_id').chosen(); + $('#project_default_branch').chosen(); }) diff --git a/app/views/admin/projects/edit.html.haml b/app/views/admin/projects/edit.html.haml index a6062be4..b8d6f689 100644 --- a/app/views/admin/projects/edit.html.haml +++ b/app/views/admin/projects/edit.html.haml @@ -1,7 +1,3 @@ -%h2= @admin_project.name +%h3= @admin_project.name +%hr = render 'form' - -%br -= link_to 'Back', admin_projects_path, :class => "" -| -= link_to 'Show', [:admin, @admin_project], :class => "" diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index f57b98d0..7cda5220 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -1,7 +1,10 @@ -%table +%h3 + Projects + = link_to 'New Project', new_admin_project_path, :class => "btn small right" +%hr +%table.zebra-striped %thead %th Name - %th Code %th Path %th Team Members %th Last Commit @@ -11,12 +14,9 @@ - @admin_projects.each do |project| %tr %td= link_to project.name, [:admin, project] - %td= project.code %td= project.path %td= project.users_projects.count %td= last_commit(project) - %td= link_to 'Edit', edit_admin_project_path(project), :id => "edit_#{dom_id(project)}" - %td= link_to 'Destroy', [:admin, project], :confirm => 'Are you sure?', :method => :delete - + %td= link_to 'Edit', edit_admin_project_path(project), :id => "edit_#{dom_id(project)}", :class => "btn small" + %td= link_to 'Destroy', [:admin, project], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger" = paginate @admin_projects -= link_to 'New Project', new_admin_project_path, :class => "grey-button" diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index cc83add6..5142dac5 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -1,10 +1,10 @@ -- unless notice.nil? - %p#notice= notice +%h3 + = @admin_project.name + = link_to 'Edit', edit_admin_project_path(@admin_project), :class => "btn right small" +%hr -%h2= @admin_project.name - -%table.round-borders +%table.zebra-striped %tr %td %b @@ -29,14 +29,32 @@ Description: %td = @admin_project.description - %tr - %td{:colspan => 2} - = link_to 'Edit', edit_admin_project_path(@admin_project), :class => "grey-button" .span-14 - %h2 Team + %h3 + Team + %small + ( #{@admin_project.users_projects.count} ) + + %hr + + %table.zebra-striped + %thead + %tr + %th Name + %th Project Access + %th Repository Access + %th + + - @admin_project.users_projects.each do |tm| + %tr + %td + = link_to tm.user_name, admin_users_path(tm.user) + %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled + %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small" + %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn danger small" = form_tag team_update_admin_project_path(@admin_project), :class => "bulk_import", :method => :put do %table @@ -49,29 +67,9 @@ %tr %td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), :multiple => true %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select" - %td= select_tag :repo_access, options_for_select(Repository.access_options), :class => "repo-access-select" - %tr - %td{ :colspan => 3 } - = submit_tag 'Add', :class => "positive-button" - - %table.round-borders - %thead - %tr - %th Name - %th Added - %th Project Access - %th Repository Access - %th - - - @admin_project.users_projects.each do |tm| - %tr - %td - = link_to tm.user_name, admin_team_member_path(tm) - %td= time_ago_in_words(tm.updated_at) + " ago" - %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled - %td= select_tag :tm_repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled - %td= link_to 'Destroy', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete + .actions + = submit_tag 'Add', :class => "btn primary" :css form select { diff --git a/app/views/admin/team_members/_form.html.haml b/app/views/admin/team_members/_form.html.haml index f8e7f104..0bf9020f 100644 --- a/app/views/admin/team_members/_form.html.haml +++ b/app/views/admin/team_members/_form.html.haml @@ -1,33 +1,19 @@ -= form_for @admin_team_member, :as => :team_member, :url => @admin_team_member.new_record? ? admin_team_members_path(@admin_team_member) : admin_team_member_path(@admin_team_member) do |f| += form_for @admin_team_member, :as => :team_member, :url => admin_team_member_path(@admin_team_member) do |f| -if @admin_team_member.errors.any? - #error_explanation - %h2= "#{pluralize(@admin_team_member.errors.count, "error")} prohibited this admin_project from being saved:" + .alert-message.block-message.error %ul - @admin_team_member.errors.full_messages.each do |msg| %li= msg - - if @admin_team_member.new_record? - .span-6 - = f.label :user_id - .span-6 - = f.select :user_id, User.all.map { |user| [user.name, user.id] } - .span-6 - = f.label :project_id - .span-6 - = f.select :project_id, Project.all.map { |user| [user.name, user.id] } + .clearfix + %label Project Access: + .input + = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, :class => "project-access-select" - .span-6 - %b Project Access: - .span-6 - = f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, :class => "project-access-select" - - .span-6 - %b Repository Access: - .span-6 - = f.select :repo_access, options_for_select(Repository.access_options, @admin_team_member.repo_access), {}, :class => "repo-access-select" %br .actions - = f.submit 'Save', :class => "grey-button" + = f.submit 'Save', :class => "btn primary" + = link_to 'Cancel', :back, :class => "btn" :css form select { diff --git a/app/views/admin/team_members/edit.html.haml b/app/views/admin/team_members/edit.html.haml index 2f4832b8..431387be 100644 --- a/app/views/admin/team_members/edit.html.haml +++ b/app/views/admin/team_members/edit.html.haml @@ -1,6 +1,19 @@ -= render 'form' +%h3 + Edit access + %small + = @admin_team_member.project.name + – + = @admin_team_member.user_name -%br -= link_to 'Show', admin_team_member_path(@admin_team_member) -\| -= link_to 'Back', admin_team_members_path +%hr +%table.zebra-striped + %tr + %td User: + %td= @admin_team_member.user_name + %tr + %td Project: + %td= @admin_team_member.project.name + %tr + %td Since: + %td= @admin_team_member.updated_at.stamp("Nov 11, 2010") += render 'form' diff --git a/app/views/admin/team_members/index.html.haml b/app/views/admin/team_members/index.html.haml deleted file mode 100644 index 8033e690..00000000 --- a/app/views/admin/team_members/index.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -- @admin_team_members.group_by(&:project).sort.each do |project, members| - %h3= link_to project.name, [:admin, project] - %table - %thead - %th Name - %th Project Access - %th Repo Access - %th Added - %th - %th - - members.each do |tm| - - user = tm.user - %tr - %td.span-6 - = link_to tm.user_name, admin_team_member_path(tm) - %br - %br - = tm.user_email - %td.span-3= select_tag :project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled - %td.span-3= select_tag :repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled - %td.span-3= time_ago_in_words(tm.updated_at) + " ago" - %td= link_to 'Edit', edit_admin_team_member_path(tm), :id => "edit_#{dom_id(tm)}" - %td= link_to 'Destroy', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete - -%br - -= paginate @admin_team_members -= link_to 'New Team Member', new_admin_team_member_path, :class => "grey-button" diff --git a/app/views/admin/team_members/new.html.haml b/app/views/admin/team_members/new.html.haml deleted file mode 100644 index c08ddc48..00000000 --- a/app/views/admin/team_members/new.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -%h1 New team member - -= render 'form' - -%br -= link_to 'Back', admin_team_members_path diff --git a/app/views/admin/team_members/show.html.haml b/app/views/admin/team_members/show.html.haml deleted file mode 100644 index 8579b6af..00000000 --- a/app/views/admin/team_members/show.html.haml +++ /dev/null @@ -1,26 +0,0 @@ -#infoblock - %p - %b Name: - = @admin_team_member.user_name - %p - %b Project: - = @admin_team_member.project.name - %p - %b Since: - = @admin_team_member.updated_at.stamp("Nov 11, 2010") - -#infoblock - .span-6 - %b Project Access: - = select_tag :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), :class => "project-access-select", :disabled => true - - %br - .span-6 - %b Repository Access: - = select_tag :repo_access, options_for_select(Repository.access_options, @admin_team_member.repo_access), :class => "repo-access-select", :disabled => true - -%br - -= link_to 'Edit', edit_admin_team_member_path(@admin_project) -\| -= link_to 'Back', admin_team_members_path diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index e6953322..bb54c184 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -2,48 +2,43 @@ = form_for [:admin, @admin_user] do |f| -if @admin_user.errors.any? #error_explanation - %h2= "#{pluralize(@admin_user.errors.count, "error")} prohibited this admin_user from being saved:" %ul - @admin_user.errors.full_messages.each do |msg| %li= msg - .form-row + .clearfix = f.label :name - %br - = f.text_field :name - .form-row + .input= f.text_field :name + .clearfix = f.label :email - %br - = f.text_field :email - .form-row + .input= f.text_field :email + .clearfix = f.label :password - %br - = f.password_field :password - .form-row + .input= f.password_field :password + .clearfix = f.label :password_confirmation - %br - = f.password_field :password_confirmation - .form-row - = f.check_box :admin - = f.label :admin + .input= f.password_field :password_confirmation - .form-row - = f.text_field :projects_limit, :class => "small_input" + .clearfix = f.label :projects_limit + .input= f.text_field :projects_limit, :class => "small_input" - .form-row + .clearfix = f.label :skype - %br - = f.text_field :skype - .form-row + .input= f.text_field :skype + .clearfix = f.label :linkedin - %br - = f.text_field :linkedin - .form-row + .input= f.text_field :linkedin + .clearfix = f.label :twitter - %br - = f.text_field :twitter - .clear - %br + .input= f.text_field :twitter + .clearfix + = f.label :admin do + = f.check_box :admin + %span Administrator .actions - = f.submit 'Save', :class => "grey-button" + = f.submit 'Save', :class => "btn primary" + - if @admin_user.new_record? + = link_to 'Cancel', admin_users_path, :class => "btn" + - else + = link_to 'Cancel', admin_user_path(@admin_user), :class => "btn" diff --git a/app/views/admin/users/edit.html.haml b/app/views/admin/users/edit.html.haml index 2ccd2f72..0e94be9e 100644 --- a/app/views/admin/users/edit.html.haml +++ b/app/views/admin/users/edit.html.haml @@ -1,6 +1,3 @@ +%h3= @admin_user.name +%hr = render 'form' - -%br -= link_to 'Back', admin_users_path, :class => "" -| -= link_to 'Show', [:admin, @admin_user], :class => "" diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index db58a6b4..a0b4df1f 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -1,4 +1,8 @@ -%table +%h3 + Users + = link_to 'New User', new_admin_user_path, :class => "btn small right" +%hr +%table.zebra-striped %thead %th Admin %th Name @@ -13,9 +17,7 @@ %td= link_to user.name, [:admin, user] %td= user.email %td= user.users_projects.count - %td= link_to 'Edit', edit_admin_user_path(user), :id => "edit_#{dom_id(user)}" - %td= link_to 'Destroy', [:admin, user], :confirm => 'Are you sure?', :method => :delete + %td= link_to 'Edit', edit_admin_user_path(user), :id => "edit_#{dom_id(user)}", :class => "btn small" + %td= link_to 'Destroy', [:admin, user], :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger" = paginate @admin_users -%br -= link_to 'New User', new_admin_user_path, :class => "grey-button" diff --git a/app/views/admin/users/new.html.haml b/app/views/admin/users/new.html.haml index 87ea570b..87d6b0f2 100644 --- a/app/views/admin/users/new.html.haml +++ b/app/views/admin/users/new.html.haml @@ -1,6 +1,3 @@ -%h1 New user - +%h2 New user +%hr = render 'form' - -%br -= link_to 'Back', admin_users_path, :class => "" diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index da8f4370..21529ab6 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -1,6 +1,10 @@ -%h2= @admin_user.name +%h3 + = @admin_user.name + = link_to 'Edit', edit_admin_user_path(@admin_user), :class => "btn small right" -%table.round-borders +%hr + +%table.zebra-striped %tr %td %b @@ -39,31 +43,55 @@ Twitter: %td = @admin_user.twitter + +%h3 Projects +%hr + +%table.zebra-striped %tr - %td{:colspan => 2} - = link_to 'Edit', edit_admin_user_path(@admin_user), :class => "grey-button" + %thead + %th Name + %th Project Access + %th Repository Access + %th + %th -.span-14 - %h2 Projects - - %table.round-borders + - @admin_user.users_projects.each do |tm| + - project = tm.project %tr - %thead - %th Name - %th Added - %th Project Access - %th Repository Access - %th - %th + %td= link_to project.name, admin_project_path(project) + %td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), :class => "medium project-access-select", :disabled => :disabled + %td= link_to 'Edit Access', edit_admin_team_member_path(tm), :class => "btn small" + %td= link_to 'Remove from team', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger" - - @admin_user.users_projects.each do |tm| - - project = tm.project += form_tag team_update_admin_user_path(@admin_user), :class => "bulk_import", :method => :put do + %table + %thead %tr - %td= link_to project.name, admin_project_path(project) - %td= time_ago_in_words(tm.updated_at) + " ago" - %td= select_tag :project_access, options_for_select(Project.access_options, tm.project_access), :class => "project-access-select", :disabled => :disabled - %td= select_tag :repo_access, options_for_select(Repository.access_options, tm.repo_access), :class => "repo-access-select", :disabled => :disabled - %td= link_to 'Edit', edit_admin_team_member_path(tm) - %td= link_to 'Cancel', admin_team_member_path(tm), :confirm => 'Are you sure?', :method => :delete + %th Projects + %th Project Access: + %th Repo Access: + + %tr + %td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), :multiple => true + %td= select_tag :project_access, options_for_select(Project.access_options), :class => "project-access-select" + + .actions + = submit_tag 'Add', :class => "btn primary" + + +:css + form select { + width:150px; + } + + #project_ids { + width:300px; + } + + +:javascript + $('select#project_ids').chosen(); + $('select#repo_access').chosen(); + $('select#project_access').chosen(); - = link_to 'Add To Another Project', new_admin_team_member_path(:team_member => {:user_id => @admin_user.id}), :class => "grey-button" diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml new file mode 100644 index 00000000..a579cca9 --- /dev/null +++ b/app/views/commits/_commit.html.haml @@ -0,0 +1,17 @@ +%li.wll.commit + .right.span2 + %p + %strong= link_to "Browse Code »", tree_project_ref_path(@project, commit.id), :class => "right" + = link_to project_commit_path(@project, :id => commit.id) do + %p + %code.left= commit.id.to_s[0..10] + %strong.cgray= commit.author_name + – + = image_tag gravatar_icon(commit.author_email), :class => "avatar", :width => 16 + %span.row_title= truncate(commit.safe_message, :length => 50) rescue "--broken encoding" + + %span.right.cgray + = time_ago_in_words(commit.committed_date) + ago +   + diff --git a/app/views/commits/_commits.html.haml b/app/views/commits/_commits.html.haml index 108d1b4c..c2c9ca62 100644 --- a/app/views/commits/_commits.html.haml +++ b/app/views/commits/_commits.html.haml @@ -1,24 +1,4 @@ - @commits.group_by { |c| c.committed_date.to_date }.each do |day, commits| - %div{ :class => "commits-date ui-box ui-box-small ui-box-big" } - .day-commits-table - %h3= day.stamp("28 Aug, 2010") - .data - - commits.each do |commit| - %a{ :class => "commit", :href => project_commit_path(@project, :id => commit.id) } - %span.commit-info - %data.commit-button - = truncate(commit.id.to_s, :length => 16) - %i - %data.commit-browse{ :onclick => "location.href='#{tree_project_ref_path(@project, commit.id)}';return false;"} - Browse Code - - if commit.author_email - = image_tag gravatar_icon(commit.author_email), :class => "left", :width => 40, :style => "padding-right:5px;" - - else - = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" - %span.commit-title - %strong - = truncate(commit.safe_message, :length => 70) - %span.commit-author - %strong= commit.author_name - = time_ago_in_words(commit.committed_date) - ago + %div.ui-box + %h5= day.stamp("28 Aug, 2010") + %ul.unstyled= render commits diff --git a/app/views/commits/_diff_head.html.haml b/app/views/commits/_diff_head.html.haml index 6e32fca0..20ec3cf1 100644 --- a/app/views/commits/_diff_head.html.haml +++ b/app/views/commits/_diff_head.html.haml @@ -1,5 +1,5 @@ %ul.bordered-list - - @commit.diffs.each do |diff| + - diffs.each do |diff| %li - if diff.deleted_file %span.removed_file diff --git a/app/views/commits/_diff.html.haml b/app/views/commits/_diffs.html.haml similarity index 68% rename from app/views/commits/_diff.html.haml rename to app/views/commits/_diffs.html.haml index 190c95dd..29eae1c4 100644 --- a/app/views/commits/_diff.html.haml +++ b/app/views/commits/_diffs.html.haml @@ -1,24 +1,26 @@ .file_stats - = render "commits/diff_head" - -- @commit.diffs.each_with_index do |diff, i| + = render "commits/diff_head", :diffs => diffs + +- diffs.each_with_index do |diff, i| - next if diff.diff.empty? - file = (@commit.tree / diff.b_path) + - file = (@commit.prev_commit.tree / diff.a_path) unless file - next unless file .diff_file .diff_file_header - if diff.deleted_file - %strong{:id => "#{diff.b_path}"}= diff.a_path + %strong{:id => "#{diff.a_path}"}= diff.a_path - else = link_to tree_file_project_ref_path(@project, @commit.id, diff.b_path) do %strong{:id => "#{diff.b_path}"}= diff.b_path %br/ .diff_file_content - if file.text? - = render :partial => "commits/text_file", :locals => { :diff => diff, :index => i } + = render "commits/text_file", :diff => diff, :index => i - elsif file.image? .diff_file_content_image %img{:src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} - else %p %center No preview for this file type + diff --git a/app/views/commits/_head.html.haml b/app/views/commits/_head.html.haml new file mode 100644 index 00000000..6951c3a2 --- /dev/null +++ b/app/views/commits/_head.html.haml @@ -0,0 +1,35 @@ +%ul.tabs + %li + = form_tag switch_project_refs_path(@project), :method => :get, :class => "project-refs-form" do + = select_tag "ref", grouped_options_refs, :onchange => "$(this.form).trigger('submit');", :class => "project-refs-select" + = hidden_field_tag :destination, "commits" + + %li{:class => "#{'active' if current_page?(project_commits_path(@project)) }"} + = link_to project_commits_path(@project) do + Commits + %li{:class => "#{'active' if current_page?(compare_project_commits_path(@project)) }"} + = link_to compare_project_commits_path(@project) do + Compare + %li{:class => "#{branches_tab_class}"} + = link_to project_repository_path(@project) do + Branches + %span.number= @project.repo.branches.count + + %li{:class => "#{'active' if current_page?(tags_project_repository_path(@project)) }"} + = link_to tags_project_repository_path(@project) do + Tags + %span.number= @project.repo.tags.count + + + - if current_page?(project_commits_path(@project)) && current_user.private_token + %li.right + %span + = link_to project_commits_path(@project, :atom, { :private_token => current_user.private_token, :ref => @ref }), :class => "btn" do + feed + = image_tag "Rss-UI.PNG", :width => 14, :title => "feed" + + +:javascript + $(function(){ + $('.project-refs-select').chosen(); + }); diff --git a/app/views/commits/_index.html.haml b/app/views/commits/_index.html.haml deleted file mode 100644 index f1e4c7eb..00000000 --- a/app/views/commits/_index.html.haml +++ /dev/null @@ -1,9 +0,0 @@ -= form_tag project_commits_path(@project), :method => :get do - %h3 - = @project.name - [ #{select_tag "branch", options_for_select(@repo.heads.map(&:name), @branch), :onchange => "this.form.submit();", :class => "small"} ] -= link_to 'Back', project_path(@project), :class => "button" -%h1 Listing commits -%div{:id => dom_id(@project)} - = render "commits" -%br/ diff --git a/app/views/commits/_text_file.html.haml b/app/views/commits/_text_file.html.haml index 513efdf0..441bdf2c 100644 --- a/app/views/commits/_text_file.html.haml +++ b/app/views/commits/_text_file.html.haml @@ -1,38 +1,22 @@ %table - - line_old = 0 - - line_new = 0 - - diff_str = diff.diff - - lines_arr = diff_str.lines.to_a - - lines_arr.each do |line| - - next if line.match(/^--- \/dev\/null/) - - next if line.match(/^--- a/) - - next if line.match(/^\+\+\+ b/) - - if line.match(/^@@ -/) - - unless line_old.zero? && line_new.zero? - %tr.line_holder - %td.old_line= "..." - %td.new_line= "..." - %td.line_content   - - - line_old = line.match(/\-[0-9]*/)[0].to_i.abs rescue 0 - - line_new = line.match(/\+[0-9]*/)[0].to_i.abs rescue 0 - - next - - - full_line = html_escape(line.gsub(/\n/, '')) + - each_diff_line(diff.diff.lines.to_a, index) do |line, type, line_code, line_new, line_old| %tr.line_holder - %td.old_line - = link_to raw(diff_line_class(line) == "new" ? " " : line_old), "#OLD#{index}-#{line_old}", :id => "OLD#{index}-#{line_old}" - %td.new_line - = link_to raw(diff_line_class(line) == "old" ? " " : line_new) , "#NEW#{index}-#{line_new}", :id => "NEW#{index}-#{line_new}" - %td.line_content{:class => "#{diff_line_class(full_line)} #{build_line_code(line, index, line_new, line_old)}", "line_code" => build_line_code(line, index, line_new, line_old)}= raw "#{full_line}  " - - comments = @line_notes.select { |n| n.for_line?(index, line_old, line_new) }.sort_by(&:created_at).reverse - - unless comments.empty? - - comments.each do |note| - = render "notes/per_line_show", :note => note - - if line[0] == "+" - - line_new += 1 - - elsif line[0] == "-" - - line_old += 1 - - else - - line_new += 1 - - line_old += 1 + - if type == "match" + %td.old_line= "..." + %td.new_line= "..." + %td.line_content.matched= line + - else + %td.old_line + = link_to raw(type == "new" ? " " : line_old), "##{line_code}", :id => line_code + - if @comments_allowed + = link_to "", "#", :class => "line_note_link", "line_code" => line_code, :title => "Add note for this line" + %td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", :id => line_code + %td.line_content{:class => "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line}  " + + - if @comments_allowed + - comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at).reverse + - unless comments.empty? + - comments.each_with_index do |note, i| + = render "notes/reply_button", :line_code => line_code if i.zero? + = render "notes/per_line_show", :note => note + - @line_notes.reject!{ |n| n == note } diff --git a/app/views/commits/compare.html.haml b/app/views/commits/compare.html.haml new file mode 100644 index 00000000..877bd407 --- /dev/null +++ b/app/views/commits/compare.html.haml @@ -0,0 +1,49 @@ += render "head" + +%h3 + Compare View +%hr + +%div + %p + Fill input field with commit id like + %code '4eedf23' + or branch/tag name like + %code master + & press compare button for commits list, code diff. + + %br + + = form_tag compare_project_commits_path(@project), :method => :get do + .clearfix + = text_field_tag :from, params[:from], :placeholder => "master", :class => "xlarge" + = "..." + = text_field_tag :to, params[:to], :placeholder => "aa8b4ef", :class => "xlarge" + .actions + = submit_tag "Compare", :class => "btn primary" + + +- unless @commits.empty? + %h4 Commits + %ul.unstyled= render @commits + +- unless @diffs.empty? + %h4 Diff + = render "commits/diffs", :diffs => @diffs + + +:javascript + $(function() { + var availableTags = #{@project.heads.map(&:name).to_json}; + + $( "#from" ).autocomplete({ + source: availableTags, + minLength: 1 + }); + + $( "#to" ).autocomplete({ + source: availableTags, + minLength: 1 + }); + }); + diff --git a/app/views/commits/index.html.haml b/app/views/commits/index.html.haml index 5a760b3a..6cc6ba5f 100644 --- a/app/views/commits/index.html.haml +++ b/app/views/commits/index.html.haml @@ -1,16 +1,14 @@ -- content_for(:body_class, "project-page commits-page") -- if current_user.private_token - = content_for :rss_icon do - .rss-icon - = link_to project_commits_path(@project, :atom, { :private_token => current_user.private_token, :ref => @ref }) do - = image_tag "Rss-UI.PNG", :width => 22, :title => "feed" += render "head" - if params[:path] - %h2 - = link_to project_commits_path(@project) do - = @project.code - \/ - %a{:href => "#"}= params[:path].split("/").join(" / ") + %ul.breadcrumb + %li + = link_to project_commits_path(@project) do + = @project.code + %span.divider + \/ + %li + %a{:href => "#"}= params[:path].split("/").join(" / ") %div{:id => dom_id(@project)} #commits_list= render "commits" @@ -21,5 +19,6 @@ - if @commits.count == @limit :javascript $(function(){ - CommitsList.init("#{@ref}", 20); + CommitsList.init("#{@ref}", #{@limit}); }); + diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml index 3e847e78..9c1df54e 100644 --- a/app/views/commits/show.html.haml +++ b/app/views/commits/show.html.haml @@ -1,20 +1,16 @@ -- content_for(:body_class, "project-page commits-page") .commit - %span.commit-info - = link_to tree_project_ref_path(@project, @commit.id) do - %data.commit-button - Browse Code - %i - - if @commit.author_email - = image_tag gravatar_icon(@commit.author_email), :class => "left", :width => 40, :style => "padding-right:5px;" - - else - = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" - %span.commit-title - %strong - = truncate(@commit.id.to_s, :length => 60) - %span.commit-author - %strong= @commit.author_name - = @commit.created_at.stamp("Aug 21, 2011 9:23pm") + = link_to tree_project_ref_path(@project, @commit.id), :class => "btn right small" do + Browse Code » + = image_tag gravatar_icon(@commit.author_email), :class => "avatar" + %code= @commit.id.to_s + %h5 + = @commit.author_name + %small= @commit.created_at.stamp("Aug 21, 2011 9:23pm") + - if @commit.author_name != @commit.committer_name or @commit.author_email != @commit.committer_email or @commit.authored_date != @commit.committed_date + – + %cite committed by + = @commit.committer_name + %small= @commit.committed_date.stamp("Aug 21, 2011 9:23pm") %hr %pre.commit_message @@ -22,17 +18,20 @@ .clear %br -= render "commits/diff" -= render "notes/notes" +%p.cgray + Showing #{pluralize(@commit.diffs.count, "changed file")} += render "commits/diffs", :diffs => @commit.diffs += render "notes/notes", :tid => @commit.id, :tt => "commit" = render "notes/per_line_form" :javascript $(document).ready(function(){ - $(".line_content").live("dblclick", function(e) { + $(".line_note_link, .line_note_reply_link").live("click", function(e) { var form = $(".per_line_form"); - $(this).parent().after(form); + $(this).parent().parent().after(form); form.find("#note_line_code").val($(this).attr("line_code")); form.show(); + return false; }); }); diff --git a/app/views/dashboard/_events_feed.html.haml b/app/views/dashboard/_events_feed.html.haml new file mode 100644 index 00000000..e3413195 --- /dev/null +++ b/app/views/dashboard/_events_feed.html.haml @@ -0,0 +1,19 @@ +- @events.each do |event| + .wll.event_feed + - if event.push? + - if event.new_branch? + User pushed new branch + - else + = image_tag gravatar_icon(event.pusher_email), :class => "avatar" + #{event.pusher_name} pushed to + = link_to project_commits_path(event.project, :ref => event.branch_name) do + %strong= event.branch_name + %span.cgray + = time_ago_in_words(event.created_at) + ago. + - if event.commits.count > 1 + = link_to compare_project_commits_path(event.project, :from => event.commits.first.prev_commit_id, :to => event.commits.last.id) do + Compare #{event.commits.first.commit.id[0..8]}...#{event.commits.last.id[0..8]} + - @project = event.project + %ul.unstyled + = render event.commits diff --git a/app/views/dashboard/_issues_feed.html.haml b/app/views/dashboard/_issues_feed.html.haml index 45892664..5c0e05ef 100644 --- a/app/views/dashboard/_issues_feed.html.haml +++ b/app/views/dashboard/_issues_feed.html.haml @@ -1,26 +1,10 @@ -#feeds_content_holder - - unless @issues.empty? - .project-box.project-updates.ui-box.ui-box-small.ui-box-big - .data - - @issues.each do |update| - %a.project-update{:href => dashboard_feed_path(update.project, update)} - %strong.issue-number= "##{update.id}" - %span.update-title - = truncate update.title, :length => 35 - .right= truncate update.project.name - %span.update-author - %strong= update.author_name - authored - = time_ago_in_words(update.created_at) - ago - .right - - if update.critical - %span.tag.high critical - - if update.today? - %span.tag.today today - - - else - %h2 - No assigned - %span.tag.open open - issues +- @issues.each do |issue| + .wll + = link_to [issue.project, issue] do + %p + %strong + %span.label= issue.project.name + – + Issue # + = issue.id + = truncate issue.title, :length => 50 diff --git a/app/views/dashboard/_menu.html.haml b/app/views/dashboard/_menu.html.haml deleted file mode 100644 index 73d4149d..00000000 --- a/app/views/dashboard/_menu.html.haml +++ /dev/null @@ -1,21 +0,0 @@ --#%h4.dash-tabs - = link_to "Activities", dashboard_path, :remote => true, :class => "dash-button #{"active" if current_page?(dashboard_path) || current_page?(root_path) }", :id => "activities_slide" - = link_to "Issues", dashboard_issues_path, :remote => true, :class => "dash-button #{"active" if current_page?(dashboard_issues_path)}", :id => "issues_slide" - = link_to "Merge Requests", dashboard_merge_requests_path, :remote => true, :class => "dash-button #{"active" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide" - = image_tag "ajax-loader-facebook.gif", :class => "dashboard-loader" - -:javascript - $(function(){ - $(".dash-button").live("click", function() { - $(".dash-button").removeClass("active"); - $(this).addClass("active"); - }); - - $(".dash-button").live("ajax:before", function() { - $(".dashboard-loader").show(); - }); - - $(".dash-button").live("ajax:complete", function() { - $(".dashboard-loader").hide(); - }); - }); diff --git a/app/views/dashboard/_merge_requests_feed.html.haml b/app/views/dashboard/_merge_requests_feed.html.haml index 1f8553e4..db1ebd32 100644 --- a/app/views/dashboard/_merge_requests_feed.html.haml +++ b/app/views/dashboard/_merge_requests_feed.html.haml @@ -1,24 +1,10 @@ -#feeds_content_holder - - unless @merge_requests.empty? - .project-box.project-updates.ui-box.ui-box-small.ui-box-big - .data - - @merge_requests.each do |update| - %a.project-update{:href => project_merge_request_path(update.project, update)} - = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 - %span.update-title - = truncate update.title, :length => 35 - .right= truncate update.project.name - %span.update-author - %strong= update.author_name - authored - = time_ago_in_words(update.created_at) - ago - .right - %span.tag.commit= update.source_branch - → - %span.tag.commit= update.target_branch - - else - %h2 - No authored or assigned - %span.tag.open open - merge requests +- @merge_requests.each do |merge_request| + .wll + = link_to [merge_request.project, merge_request] do + %p + %strong + %span.label= merge_request.project.name + – + Merge Request # + = merge_request.id + = truncate merge_request.title, :length => 50 diff --git a/app/views/dashboard/_projects_feed.html.haml b/app/views/dashboard/_projects_feed.html.haml index 0d347246..1d53cf74 100644 --- a/app/views/dashboard/_projects_feed.html.haml +++ b/app/views/dashboard/_projects_feed.html.haml @@ -1,20 +1,8 @@ -#feeds_content_holder - - @active_projects.first(3).each do |project| - .project-box.project-updates.ui-box.ui-box-small.ui-box-big - = link_to project do - %h3= project.name - .data - - project.updates(3).each do |update| - %a.project-update{:href => dashboard_feed_path(project, update)} - = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 - %span.update-title - = dashboard_feed_title(update) - %span.update-author - %strong= update.author_name - authored - = time_ago_in_words(update.created_at) - ago - .right - - klass = update.class.to_s.split("::").last.downcase - %span.tag{ :class => klass }= klass - +- @active_projects.first(5).each do |project| + .wll + = link_to project do + %h4 + = project.name + %small + last activity at + = project.last_activity_date_cached.stamp("Aug 25, 2011") diff --git a/app/views/dashboard/_sidebar.html.haml b/app/views/dashboard/_sidebar.html.haml deleted file mode 100644 index dec71186..00000000 --- a/app/views/dashboard/_sidebar.html.haml +++ /dev/null @@ -1,15 +0,0 @@ -%aside - %h4 - - if current_user.can_create_project? - %a.button-small.button-green{:href => new_project_path} New Project - Your Projects - %ol.project-list - - @projects.each do |project| - %li - %a{:href => project_path(project)} - -#%span.arrow → - %span.project-name= project.name - %span.time - %strong Last activity: - = project.last_activity_date_cached ? time_ago_in_words(project.last_activity_date_cached) + " ago" : "Never" - diff --git a/app/views/dashboard/index.html.haml b/app/views/dashboard/index.html.haml index 7f6beffb..27490e40 100644 --- a/app/views/dashboard/index.html.haml +++ b/app/views/dashboard/index.html.haml @@ -1,6 +1,65 @@ -- content_for(:body_class, "dashboard-page") +- if current_user.require_ssh_key? + .alert-message.warning + %p + You wont be able to pull/push project code unless you + = link_to new_key_path, :class => "vlink" do + add new key + to your profile -#dashboard-content.dashboard-content.content - = render "dashboard/sidebar" - = render "dashboard/menu" - #news-feed.news-feed= render "dashboard/projects_feed" +%div.dashboard_category + %h3 + Projects + %small + ( most recent ) + + %strong.right + = link_to projects_path do + Projects list → + %hr + .row + .dashboard_block + .row + .span9= render "dashboard/projects_feed" + .span3.right + - if current_user.can_create_project? + .alert-message.block-message.warning + You can create up to + = current_user.projects_limit + projects. Click on link below to add a new one + .link_holder + = link_to new_project_path, :class => "" do + New Project » + + +- unless @merge_requests.blank? + %div.dashboard_category + %h3 + Merge Requests + %small ( authored or assigned to you ) + %strong.right + = link_to dashboard_merge_requests_path do + Vist merge requests page → + %hr + .row + .dashboard_block= render "dashboard/merge_requests_feed" + +- unless @issues.blank? + %div.dashboard_category + %h3 + Issues + %small ( assigned to you ) + %strong.right + = link_to dashboard_merge_requests_path do + Vist issues page → + %hr + .row + .dashboard_block= render "dashboard/issues_feed" + +- unless @events.blank? + %div.dashboard_category + %h3 + Activities + + %hr + .row + .dashboard_block= render "dashboard/events_feed" diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml index 4b7af96a..b9c467a5 100644 --- a/app/views/dashboard/issues.html.haml +++ b/app/views/dashboard/issues.html.haml @@ -1,6 +1,6 @@ -- content_for(:body_class, "dashboard-page") +%h3 + Issues + %small ( assigned to you ) -#dashboard-content.dashboard-content.content - = render "dashboard/sidebar" - = render "dashboard/menu" - #news-feed.news-feed= render "dashboard/issues_feed" +%br +.ui-box= render "dashboard/issues_feed" diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml index 3497062c..ec1c233c 100644 --- a/app/views/dashboard/merge_requests.html.haml +++ b/app/views/dashboard/merge_requests.html.haml @@ -1,6 +1,6 @@ -- content_for(:body_class, "dashboard-page") +%h3 + Merge Requests + %small ( authored or assigned to you ) -#dashboard-content.dashboard-content.content - = render "dashboard/sidebar" - = render "dashboard/menu" - #news-feed.news-feed= render "dashboard/merge_requests_feed" +%br +.ui-box= render "dashboard/merge_requests_feed" diff --git a/app/views/deploy_keys/_form.html.haml b/app/views/deploy_keys/_form.html.haml index f0a300bb..2aa57cdc 100644 --- a/app/views/deploy_keys/_form.html.haml +++ b/app/views/deploy_keys/_form.html.haml @@ -1,18 +1,18 @@ %div = form_for [@project, @key], :url => project_deploy_keys_path do |f| -if @key.errors.any? - %ul.errors_holder - - @key.errors.full_messages.each do |msg| - %li= msg - - %table.no-borders - %tr - %td= f.label :title - %td= f.text_field :title, :style => "width:300px" - %tr - %td= f.label :key - %td= f.text_area :key, :style => "width:300px; height:130px" - %br - .merge-tabs - = f.submit 'Save', :class => "positive-button" + .alert-message.block-message.error + %ul + - @key.errors.full_messages.each do |msg| + %li= msg + + .clearfix + = f.label :title + .input= f.text_field :title + .clearfix + = f.label :key + .input= f.text_area :key, :class => "xlarge" + .actions + = f.submit 'Save', :class => "primary btn" + = link_to "Cancel", project_deploy_keys_path(@project), :class => "btn" diff --git a/app/views/deploy_keys/_show.html.haml b/app/views/deploy_keys/_show.html.haml index b1622f35..ff17b3cd 100644 --- a/app/views/deploy_keys/_show.html.haml +++ b/app/views/deploy_keys/_show.html.haml @@ -1,7 +1,12 @@ -%a.update-item{:href => project_deploy_key_path(key.project, key)} - %span.update-title - = key.title - %span.update-author - Added - = time_ago_in_words(key.created_at) - ago +%tr + %td + %a{:href => project_deploy_key_path(key.project, key)} + %strong= key.title + %td + %span.update-author + Added + = time_ago_in_words(key.created_at) + ago + %td + = link_to 'Remove', project_deploy_key_path(key.project, key), :confirm => 'Are you sure?', :method => :delete, :class => "danger btn delete-key small right" + diff --git a/app/views/deploy_keys/index.html.haml b/app/views/deploy_keys/index.html.haml index 02c8c135..b03e7539 100644 --- a/app/views/deploy_keys/index.html.haml +++ b/app/views/deploy_keys/index.html.haml @@ -1,17 +1,10 @@ = render "repositories/head" +- if can? current_user, :admin_project, @project + .alert-message.block-message + Deploy keys allow read-only access to repository. + = link_to new_project_deploy_key_path(@project), :class => "btn small", :title => "New Deploy Key" do + Add Deploy Key -%div#keys-table{ :class => "update-data ui-box ui-box-small ui-box-big" } - .data - - @keys.each do |key| - = render(:partial => 'show', :locals => {:key => key}) - -- if @keys.blank? - .notice_holder - %li Deploy Keys do not exist yet. - - if can? current_user, :admin_project, @project - %li You can add a new one by clicking on "Add New" button - -:javascript - $('.delete-key').live('ajax:success', function() { - $(this).closest('.update-item').fadeOut(); }); - +%table.zebra-striped.borders + - @keys.each do |key| + = render(:partial => 'show', :locals => {:key => key}) diff --git a/app/views/deploy_keys/new.html.haml b/app/views/deploy_keys/new.html.haml index 1e6b7e77..a2f1010b 100644 --- a/app/views/deploy_keys/new.html.haml +++ b/app/views/deploy_keys/new.html.haml @@ -1,5 +1,6 @@ = render "repositories/head" -%h2 New Deploy key +%h3 New Deploy key +%hr = render 'form' diff --git a/app/views/deploy_keys/show.html.haml b/app/views/deploy_keys/show.html.haml index 2c5c6149..16c441be 100644 --- a/app/views/deploy_keys/show.html.haml +++ b/app/views/deploy_keys/show.html.haml @@ -1,10 +1,7 @@ -.ui-box.width-100p - %h3= @key.title - .data - %pre= @key.key - .clear - .buttons - = link_to 'Remove', project_deploy_key_path(@key.project, @key), :confirm => 'Are you sure?', :method => :delete, :class => "red-button delete-key right" - .clear - - += render "repositories/head" +%h3= @key.title +%hr +%pre= @key.key +.actions + = link_to 'Remove', project_deploy_key_path(@key.project, @key), :confirm => 'Are you sure?', :method => :delete, :class => "danger btn delete-key" + .clear diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb deleted file mode 100644 index ff76588c..00000000 --- a/app/views/devise/passwords/edit.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -

Change your password

- -<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %> - <%= devise_error_messages! %> - <%= f.hidden_field :reset_password_token %> - -
<%= f.label :password, "New password" %>
- <%= f.password_field :password %>
- -
<%= f.label :password_confirmation, "Confirm new password" %>
- <%= f.password_field :password_confirmation %>
- -
<%= f.submit "Change my password" %>
-<% end %> - -<%= render :partial => "devise/shared/links" %> diff --git a/app/views/devise/passwords/edit.html.haml b/app/views/devise/passwords/edit.html.haml new file mode 100644 index 00000000..dfd715ac --- /dev/null +++ b/app/views/devise/passwords/edit.html.haml @@ -0,0 +1,12 @@ += form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put, :class => "login-box" }) do |f| + = image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" + %h3 Change your password + = devise_error_messages! + = f.hidden_field :reset_password_token + %div + = f.password_field :password, :class => "text top", :placeholder => "New password" + %div + = f.password_field :password_confirmation, :class => "text bottom", :placeholder => "Confirm new password" + %div + = f.submit "Change my password", :class => "btn primary" + .right= render :partial => "devise/shared/links" diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb index 01cb3375..cf56c5d2 100644 --- a/app/views/devise/passwords/new.html.erb +++ b/app/views/devise/passwords/new.html.erb @@ -1,8 +1,9 @@ <%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :class => "login-box", :method => :post }) do |f| %> <%= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo" %> <%= devise_error_messages! %> - <%= f.email_field :email, :placeholder => "Email", :class => "text top" %> + <%= f.email_field :email, :placeholder => "Email", :class => "text" %>
- <%= f.submit "Reset password", :class => "grey-button" %> +
+ <%= f.submit "Reset password", :class => "primary btn" %>
<%= render :partial => "devise/shared/links" %>
<% end %> diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index c17ff3f9..f40a8794 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -4,9 +4,12 @@ <%= f.password_field :password, :class => "text bottom", :placeholder => "Password" %> <% if devise_mapping.rememberable? -%> -
<%= f.check_box :remember_me %> <%= f.label :remember_me %>
+
<% end -%>
- <%= f.submit "Sign in", :class => "grey-button" %> + <%= f.submit "Sign in", :class => "primary btn" %>
<%= render :partial => "devise/shared/links" %>
+ <% if ldap_enable? -%> +

<%= link_to "via LDAP", user_omniauth_authorize_path(:ldap)%>

+ <% end -%> <% end %> diff --git a/app/views/devise/shared/_links.erb b/app/views/devise/shared/_links.erb index 33b1120f..c624c2d5 100644 --- a/app/views/devise/shared/_links.erb +++ b/app/views/devise/shared/_links.erb @@ -1,5 +1,5 @@ <%- if controller_name != 'sessions' %> - <%= link_to "Sign in", new_session_path(resource_name) %>
+ <%= link_to "Sign in", new_session_path(resource_name), :class => "btn" %>
<% end -%> <%- if devise_mapping.registerable? && controller_name != 'registrations' %> @@ -7,7 +7,7 @@ <% end -%> <%- if devise_mapping.recoverable? && controller_name != 'passwords' %> - <%= link_to "Forgot your password?", new_password_path(resource_name) %>
+<%= link_to "Forgot your password?", new_password_path(resource_name), :class => "btn" %>
<% end -%> <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> diff --git a/app/views/errors/access_denied.html.haml b/app/views/errors/access_denied.html.haml new file mode 100644 index 00000000..718663db --- /dev/null +++ b/app/views/errors/access_denied.html.haml @@ -0,0 +1,5 @@ +.alert-message.block-message.error + %h3 Access Denied + %hr + %p Youre not allowed to access this page + %p Read more about project permissions #{link_to "here", help_permissions_path, :class => "vlink"} diff --git a/app/views/errors/git_not_found.html.haml b/app/views/errors/git_not_found.html.haml new file mode 100644 index 00000000..172bd4e6 --- /dev/null +++ b/app/views/errors/git_not_found.html.haml @@ -0,0 +1,9 @@ +.alert-message.block-message.error + %h3 Git Resource Not found + %hr + %p + Application cant get access to some + %span.label branch + or + %span.label commit + in your repository. Maybe it was moved diff --git a/app/views/errors/gitolite.html.haml b/app/views/errors/gitolite.html.haml new file mode 100644 index 00000000..41d7d83a --- /dev/null +++ b/app/views/errors/gitolite.html.haml @@ -0,0 +1,18 @@ +.alert-message.block-message.error + %h3 Gitolite Error + %hr + %h4 Application cant get access to your gitolite system. + %ol + %li + %p + Check 'config/gitlab.yml' for correct settings. + %li + %p + Make sure web server user has access to gitolite. + %a{:href => "https://github.com/gitlabhq/gitlabhq/wiki/Gitolite"} Setup tutorial + %li + %p + Try: + %pre + sudo chmod -R 770 /home/git/repositories/ + sudo chown -R git:git /home/git/repositories/ diff --git a/app/views/errors/not_found.html.haml b/app/views/errors/not_found.html.haml new file mode 100644 index 00000000..9b76a9bf --- /dev/null +++ b/app/views/errors/not_found.html.haml @@ -0,0 +1,5 @@ +.alert-message.block-message.error + %h3 Not found + %hr + %p Resource you were looking for doesn't exist. + %P You may have mistyped the address or it was removed. diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml index fd1f512b..2b0b5a19 100644 --- a/app/views/help/index.html.haml +++ b/app/views/help/index.html.haml @@ -1,43 +1,17 @@ -- bash_lexer = Pygments::Lexer[:bash] -%div.help_content - %h2 - Gitlabhq - %span.right v2.1 - %hr - %h3 Self Hosted Git Management - %h3 Fast, secure and stable solution based on Ruby on Rails & Gitolite. +%h3 + Gitlabhq + %span.right v2.2 +%hr +%h4 Self Hosted Git Management +%h4 Fast, secure and stable solution based on Ruby on Rails & Gitolite. - %hr +%hr - .menu - %h3= link_to "Workflow", "#", :class => "active" +%h3 Help - .content - %h3 Clone project - .bash - %pre - git clone git@example.com:project-name.git +%ol + %li + = link_to "Workflow", help_workflow_path - %h3 Create branch with your feature - .bash - %pre - git checkout -b $feature_name - - %h3 Write code. Commit changes - .bash - %pre - git commit -am "My feature is ready" - - %h3 Push your branch to gitlabhq - .bash - %pre - git push origin $feature_name - - %h3 Review your code - .bash= image_tag "help_commit.png", :width => 600 - - - %h3 Open a merge request - .bash= image_tag "help_merge_request.png", :width => 600 - - %h3 Your team lead will review code & merge it to main branch + %li + = link_to "Permissions", help_permissions_path diff --git a/app/views/help/permissions.html.haml b/app/views/help/permissions.html.haml new file mode 100644 index 00000000..0e6e351b --- /dev/null +++ b/app/views/help/permissions.html.haml @@ -0,0 +1,36 @@ +%h3 Permissions +%hr + +%h4 Guest +%ul + %li Create new issue + %li Leave comments + %li Write on project wall + +%h4 Reporter +%ul + %li Pull project code + %li Download project + %li Create new issue + %li Create new merge request + %li Write on project wall + %li Create a code snippets + + +%h4 Developer +%ul + %li Pull project code + %li Create new branches + %li Push to non-protected branches + %li Remove non-protected branches + %li Add tags + %li Create new issue + %li Create new merge request + %li Write on project wall + %li Write a wiki + +%h4 Master +%ul + %li Full repository access + %li Full project access + %li Add new team members diff --git a/app/views/help/workflow.html.haml b/app/views/help/workflow.html.haml new file mode 100644 index 00000000..4785b367 --- /dev/null +++ b/app/views/help/workflow.html.haml @@ -0,0 +1,38 @@ +- bash_lexer = Pygments::Lexer[:bash] +%h3 Workflow +%hr + +%ol.help + %li + %p Clone project + .bash + %pre + git clone git@example.com:project-name.git + + %li + %p Create branch with your feature + .bash + %pre + git checkout -b $feature_name + + %li + %p Write code. Commit changes + .bash + %pre + git commit -am "My feature is ready" + + %li + %p Push your branch to gitlabhq + .bash + %pre + git push origin $feature_name + + %li + %p Review your code on Commits page + + %li + %p Create a merge request + + %li + %p Your team lead will review code & merge it to main branch + diff --git a/app/views/hooks/index.html.haml b/app/views/hooks/index.html.haml index 3bff76f4..69881752 100644 --- a/app/views/hooks/index.html.haml +++ b/app/views/hooks/index.html.haml @@ -1,25 +1,22 @@ -= render "repositories/head" -- unless @hooks.empty? - %div.update-data.ui-box.ui-box-small - .data - - @hooks.each do |hook| - %a.update-item{:href => project_hook_path(@project, hook)} - %span.update-title{:style => "margin-bottom:0px;"} - = hook.url - %span.update-author.right - Added - = time_ago_in_words(hook.created_at) - ago -- else - %h3 No hooks += render "projects/project_head" -.clear -%hr -%p - Post receive hooks. For now only POST request allowed. We send some data with request. Example below +- if can? current_user, :admin_project, @project + .alert-message.block-message + Post receive hooks for binding events when someone push to repository. + = link_to new_project_hook_path(@project), :class => "btn small", :title => "New Web Hook" do + Add Post Receive Hook -.view_file - .view_file_header - %strong POST data passed - .data.no-padding - = render "data_ex" +%table.zebra-striped.borders + - @hooks.each do |hook| + %tr + %td + = link_to project_hook_path(@project, hook) do + = hook.url + %td + = link_to 'Remove', project_hook_path(@project, hook), :confirm => 'Are you sure?', :method => :delete, :class => "danger btn small" + + +.alert-message.block-message + We send some data with POST request when someone makes git push + +.well= render "data_ex" diff --git a/app/views/hooks/new.html.haml b/app/views/hooks/new.html.haml index 8078aefa..f2a5ef53 100644 --- a/app/views/hooks/new.html.haml +++ b/app/views/hooks/new.html.haml @@ -4,10 +4,9 @@ %ul - @hook.errors.full_messages.each do |msg| %li= msg - = f.label :url, "URL:" - = f.text_field :url, :class => "text_field" - .clear - %br - .merge-tabs - = f.submit "Save", :class => "grey-button" + .clearfix + = f.label :url, "URL:" + .input= f.text_field :url, :class => "text_field" + .actions + = f.submit "Save", :class => "btn" diff --git a/app/views/hooks/show.html.haml b/app/views/hooks/show.html.haml index 47c1ddea..5ec4d5d8 100644 --- a/app/views/hooks/show.html.haml +++ b/app/views/hooks/show.html.haml @@ -1,11 +1,7 @@ = render "repositories/head" -%h3 - %span.commit.tag POST - = @hook.url - +%pre= @hook.url - if can? current_user, :admin_project, @project - .merge-tabs - = link_to 'Test Hook', test_project_hook_path(@project, @hook), :class => "grey-button" - .right - = link_to 'Remove', project_hook_path(@project, @hook), :confirm => 'Are you sure?', :method => :delete, :class => "red-button" + .actions + = link_to 'Test Hook', test_project_hook_path(@project, @hook), :class => "btn" + = link_to 'Remove', project_hook_path(@project, @hook), :confirm => 'Are you sure?', :method => :delete, :class => "danger btn" diff --git a/app/views/issues/_form.html.haml b/app/views/issues/_form.html.haml index d13827e7..3b379198 100644 --- a/app/views/issues/_form.html.haml +++ b/app/views/issues/_form.html.haml @@ -1,51 +1,41 @@ %div.issue-form-holder = form_for [@project, @issue], :remote => request.xhr? do |f| - %div - %span.entity-info - - if request.xhr? - = link_to "#back", :onclick => "backToIssues();" do - .entity-button - Issues - %i - - else - - if @issue.new_record? - = link_to project_issues_path(@project) do - .entity-button - Issues - %i - - else - = link_to project_issue_path(@project, @issue) do - .entity-button - Show Issue - %i - - %h2= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}" - %hr + %h3= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}" + %hr -if @issue.errors.any? - %ul.errors_holder - - @issue.errors.full_messages.each do |msg| - %li= msg + .alert-message.block-message.error + %ul + - @issue.errors.full_messages.each do |msg| + %li= msg - %table.no-borders - %tr - %td= f.label :assignee_id - %td= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }) + .clearfix + = f.label :assignee_id + .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }) - %tr - %td= f.label :critical, "Critical" - %td= f.check_box :critical - - - unless @issue.new_record? - %tr - %td= f.label :closed - %td= f.check_box :closed + .clearfix + = f.label :critical, "Critical" + .input= f.check_box :critical - = f.text_area :title, :style => "width:718px; height:100px", :maxlength => 255 - %br - %br - .merge-tabs - = f.submit 'Save', :class => "positive-button" -   + - unless @issue.new_record? + .clearfix + = f.label :closed + .input= f.check_box :closed + + .clearfix + = f.label :title + .input= f.text_area :title, :maxlength => 255, :class => "xxlarge" + .actions + = f.submit 'Save', :class => "primary btn" + + - if request.xhr? + = link_to "Cancel", "#back", :onclick => "backToIssues();", :class => "btn" + - else + - if @issue.new_record? + = link_to "Cancel", project_issues_path(@project), :class => "btn" + - else + = link_to "Cancel", project_issue_path(@project, @issue), :class => "btn" + + - unless @issue.new_record? .right - = link_to 'Remove', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "red-button" + = link_to 'Remove', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "danger btn" diff --git a/app/views/issues/_head.html.haml b/app/views/issues/_head.html.haml index 7d44b875..d5390252 100644 --- a/app/views/issues/_head.html.haml +++ b/app/views/issues/_head.html.haml @@ -1,14 +1,4 @@ -.top-tabs - = link_to project_issues_path(@project), :class => "tab #{'active' if current_page?(project_issues_path(@project)) }" do - %span - Issues - - -#= link_to project_issues_path(@project), :class => "tab" do - %span - Milestones - - - if current_page?(project_issues_path(@project)) - - if can? current_user, :write_issue, @project - = link_to new_project_issue_path(@project), :class => "add_new", :title => "New Issue", :remote => true do - Add new - +.tabs + %li{:class => "#{'active' if current_page?(project_issues_path(@project))}"} + = link_to project_issues_path(@project), :class => "tab" do + Issues diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml index 8c095268..1d5cbd21 100644 --- a/app/views/issues/_show.html.haml +++ b/app/views/issues/_show.html.haml @@ -1,26 +1,27 @@ -%tr{ :id => dom_id(issue), :class => "issue #{issue.critical ? "critical" : ""}", :url => project_issue_path(issue.project, issue) } - %td - %strong.issue-number{:class => sort_class}= "##{issue.id}" - %span - = truncate(html_escape(issue.title), :length => 100) - %br - %br - %div.note-author - %strong= issue.assignee.name - %cite.cgray - = time_ago_in_words(issue.created_at) - ago - - if issue.critical - %span.tag.high critical - - if issue.today? - %span.tag.today today - .right.action-links - - if can? current_user, :write_issue, issue - - if issue.closed - = link_to 'Reopen', project_issue_path(issue.project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "cgray", :remote => true - - else - = link_to 'Resolve', project_issue_path(issue.project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "cgray", :remote => true - - if can? current_user, :write_issue, issue - = link_to 'Edit', edit_project_issue_path(issue.project, issue), :class => "cgray edit-issue-link", :remote => true - - if can?(current_user, :admin_issue, @project) || issue.author == current_user - = link_to 'Remove', [issue.project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-issue negative", :id => "destroy_issue_#{issue.id}" +%li.wll{ :id => dom_id(issue), :class => "issue #{issue.critical ? "critical" : ""}", :url => project_issue_path(issue.project, issue) } + .right + - if can? current_user, :modify_issue, issue + - if issue.closed + = link_to 'Reopen', project_issue_path(issue.project, issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "btn small", :remote => true + - else + = link_to 'Resolve', project_issue_path(issue.project, issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "success btn small", :remote => true + = link_to 'Edit', edit_project_issue_path(issue.project, issue), :class => "btn small edit-issue-link", :remote => true + -#- if can?(current_user, :admin_issue, @project) || issue.author == current_user + = link_to 'Remove', [issue.project, issue], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "danger btn small delete-issue", :id => "destroy_issue_#{issue.id}" + = image_tag gravatar_icon(issue.assignee_email), :class => "avatar" + %span.update-author + assigned to + %strong= issue.assignee_name + - if issue.critical + %span.label.important critical + - if issue.today? + %span.label.success today + + + + = link_to project_issue_path(issue.project, issue) do + %p.row_title= truncate(issue.title, :length => 60) + + + + diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml index 37654c83..297eab25 100644 --- a/app/views/issues/index.html.haml +++ b/app/views/issues/index.html.haml @@ -1,57 +1,54 @@ -= render "issues/head" -- if current_user.private_token - = content_for :rss_icon do - .rss-icon +.issues_content + %h3 + Issues + %span.rss-icon = link_to project_issues_path(@project, :atom, { :private_token => current_user.private_token }) do = image_tag "Rss-UI.PNG", :width => 22, :title => "feed" -%div#issues-table-holder - .top_panel_issues - = form_tag search_project_issues_path(@project), :method => :get, :remote => true, :class => :right, :id => "issue_search_form" do - = hidden_field_tag :project_id, @project.id, { :id => 'project_id' } - = search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search' } - - .left.issues_filter - = form_tag project_issues_path(@project), :method => :get do - .left - = radio_button_tag :f, 0, (params[:f] || "0") == "0", :onclick => "setIssueFilter(this.form, 0)", :id => "open_issues", :class => "status" - = label_tag "open_issues" do - %span.tag.open Open - .left - = radio_button_tag :f, 2, params[:f] == "2", :onclick => "setIssueFilter(this.form, 2)", :id => "closed_issues", :class => "status" - = label_tag "closed_issues" do - %span.tag.closed Closed - .left - = radio_button_tag :f, 3, params[:f] == "3", :onclick => "setIssueFilter(this.form, 3)", :id => "my_issues", :class => "status" - = label_tag "my_issues","To Me" - .left - = radio_button_tag :f, 1, params[:f] == "1", :onclick => "setIssueFilter(this.form, 1)", :id => "all_issues", :class => "status" - = label_tag "all_issues","All" - - .clear - %hr - %table.no-borders#issues-table - = render "issues" + - if can? current_user, :write_issue, @project + = link_to new_project_issue_path(@project), :class => "right btn small", :title => "New Issue", :remote => true do + New Issue %br + %div#issues-table-holder.ui-box + .title + .row + .span8 + %ul.pills.left + %li{:class => ("active" if (params[:f] == "0" || !params[:f]))} + = link_to project_issues_path(@project, :f => 0) do + Open + %li{:class => ("active" if params[:f] == "2")} + = link_to project_issues_path(@project, :f => 2) do + Closed + %li{:class => ("active" if params[:f] == "3")} + = link_to project_issues_path(@project, :f => 3) do + To Me + %li{:class => ("active" if params[:f] == "1")} + = link_to project_issues_path(@project, :f => 1) do + All + + .span3.right + = form_tag search_project_issues_path(@project), :method => :get, :remote => true, :id => "issue_search_form", :class => :right do + = hidden_field_tag :project_id, @project.id, { :id => 'project_id' } + = hidden_field_tag :status, params[:f] + = search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search' } + + %ul#issues-table.unstyled= render "issues" + :javascript var href = $('.issue_search').parent().attr('action'); var last_terms = ''; - var setIssueFilter = function(form, value){ - $.cookie('issue_filter', value, { expires: 140 }); - form.submit(); - } - $('.issue_search').keyup(function() { var terms = $(this).val(); var project_id = $('#project_id').val(); - var status = $('.status:checked').val(); + var status = $('#status').val(); if (terms != last_terms) { last_terms = terms; if (terms.length >= 2 || terms.length == 0) { $.get(href, { 'status': status, 'terms': terms, project: project_id }, function(response) { - $('#issues-table tbody').html(response); + $('#issues-table').html(response); setSortable(); }); } @@ -62,7 +59,7 @@ $(this).closest('tr').fadeOut(); updatePage();}); function setSortable(){ - $('#issues-table>tbody').sortable({ + $('#issues-table').sortable({ axis: 'y', dropOnEmpty: false, handle: '.handle', @@ -73,10 +70,10 @@ update: function(){ $.ajax({ type: 'post', - data: $('#issues-table>tbody').sortable('serialize'), + data: $('#issues-table').sortable('serialize'), dataType: 'script', complete: function(request){ - $('#issues-table>tbody').effect('highlight'); + $('#issues-table').effect('highlight'); }, url: "#{sort_project_issues_path(@project)}"}) } diff --git a/app/views/issues/index.js.haml b/app/views/issues/index.js.haml index a08ffe5a..a534cfbf 100644 --- a/app/views/issues/index.js.haml +++ b/app/views/issues/index.js.haml @@ -1,3 +1,3 @@ :plain - $('#issues-table tbody').html("#{escape_javascript(render('issues'))}"); + $('#issues-table').html("#{escape_javascript(render('issues'))}"); setSortable(); diff --git a/app/views/issues/show.html.haml b/app/views/issues/show.html.haml index 48fca97d..13292d4e 100644 --- a/app/views/issues/show.html.haml +++ b/app/views/issues/show.html.haml @@ -1,49 +1,44 @@ -%div - %span.entity-info +%h3 + Issue ##{@issue.id} + %small + created at + = @issue.created_at.stamp("Aug 21, 2011") + + %span.right - if can?(current_user, :admin_project, @project) || @issue.author == current_user - = link_to edit_project_issue_path(@project, @issue) do - .entity-button - Edit Issue - %i - = image_tag gravatar_icon(@issue.author_email), :class => "left", :width => 40, :style => "padding-right:5px;" - %span.commit-title - %strong - = "Issue ##{@issue.id}:" - %span.commit-author - %strong - = link_to project_team_member_path(@project, @project.team_member_by_id(@issue.author.id)) do - %span.author= @issue.author_name - - if @issue.author != @issue.assignee - → - = link_to project_team_member_path(@project, @project.team_member_by_id(@issue.assignee.id)) do - %span.author= @issue.assignee_name -   + - if @issue.closed + = link_to 'Reopen', project_issue_path(@project, @issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "btn" + - else + = link_to 'Close', project_issue_path(@project, @issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "btn", :title => "Close Issue" + - if can?(current_user, :admin_project, @project) || @issue.author == current_user + = link_to edit_project_issue_path(@project, @issue), :class => "btn small" do + Edit -   - = @issue.created_at.stamp("Aug 21, 2011 9:23pm") +.back_link + = link_to project_issues_path(@project) do + ← To issues list - %hr - %br - %h3 - = simple_format @issue.title -.clear -%br -%br +%hr +- if @issue.closed + .alert-message.error Closed +- else + .alert-message.success Open -.merge-tabs - = link_to "#notes", :class => "merge-notes-tab active tab" do - %span - Notes - .right - - if @issue.closed - = link_to 'Reopen', project_issue_path(@project, @issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "red-button" - - else - = link_to 'Close', project_issue_path(@project, @issue, :issue => {:closed => true }, :status_only => true), :method => :put, :class => "positive-button" -.merge-request-notes - .issue_notes= render "notes/notes" - .loading{ :style => "display:none;"} - %center= image_tag "ajax-loader.gif" - .clear +%div.well + %div + %cite.cgray Created by + = image_tag gravatar_icon(@issue.author_email), :width => 16, :class => "lil_av" + %strong.author= link_to_issue_author(@issue) + %cite.cgray and currently assigned to + = image_tag gravatar_icon(@issue.assignee_email), :width => 16, :class => "lil_av" + %strong.author= link_to_issue_assignee(@issue) + + %hr + + %div= simple_format @issue.title + + +.issue_notes= render "notes/notes", :tid => @issue.id, :tt => "issue" diff --git a/app/views/issues/show.js.haml b/app/views/issues/show.js.haml deleted file mode 100644 index ee31c0b8..00000000 --- a/app/views/issues/show.js.haml +++ /dev/null @@ -1 +0,0 @@ -= render "notes/load" diff --git a/app/views/kaminari/_first_page.html.haml b/app/views/kaminari/_first_page.html.haml new file mode 100644 index 00000000..fee8112f --- /dev/null +++ b/app/views/kaminari/_first_page.html.haml @@ -0,0 +1,9 @@ +-# Link to the "First" page +-# available local variables +-# url: url to the first page +-# current_page: a page object for the currently displayed page +-# num_pages: total number of pages +-# per_page: number of items to fetch per page +-# remote: data-remote +%span.first + = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, :remote => remote diff --git a/app/views/kaminari/_gap.html.haml b/app/views/kaminari/_gap.html.haml new file mode 100644 index 00000000..f82f185a --- /dev/null +++ b/app/views/kaminari/_gap.html.haml @@ -0,0 +1,8 @@ +-# Non-link tag that stands for skipped pages... +-# available local variables +-# current_page: a page object for the currently displayed page +-# num_pages: total number of pages +-# per_page: number of items to fetch per page +-# remote: data-remote +%span.page.gap + = raw(t 'views.pagination.truncate') diff --git a/app/views/kaminari/_last_page.html.haml b/app/views/kaminari/_last_page.html.haml new file mode 100644 index 00000000..6e41d232 --- /dev/null +++ b/app/views/kaminari/_last_page.html.haml @@ -0,0 +1,9 @@ +-# Link to the "Last" page +-# available local variables +-# url: url to the last page +-# current_page: a page object for the currently displayed page +-# num_pages: total number of pages +-# per_page: number of items to fetch per page +-# remote: data-remote +%span.last + = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, {:remote => remote} diff --git a/app/views/kaminari/_next_page.html.haml b/app/views/kaminari/_next_page.html.haml new file mode 100644 index 00000000..76f40e72 --- /dev/null +++ b/app/views/kaminari/_next_page.html.haml @@ -0,0 +1,9 @@ +-# Link to the "Next" page +-# available local variables +-# url: url to the next page +-# current_page: a page object for the currently displayed page +-# num_pages: total number of pages +-# per_page: number of items to fetch per page +-# remote: data-remote +%li.next + = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, :rel => 'next', :remote => remote diff --git a/app/views/kaminari/_page.html.haml b/app/views/kaminari/_page.html.haml new file mode 100644 index 00000000..59668129 --- /dev/null +++ b/app/views/kaminari/_page.html.haml @@ -0,0 +1,10 @@ +-# Link showing page number +-# available local variables +-# page: a page object for "this" page +-# url: url to this page +-# current_page: a page object for the currently displayed page +-# num_pages: total number of pages +-# per_page: number of items to fetch per page +-# remote: data-remote +%li{:class => "page#{' active' if page.current?}"} + = link_to page, url, {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil} diff --git a/app/views/kaminari/_paginator.html.haml b/app/views/kaminari/_paginator.html.haml new file mode 100644 index 00000000..6f9fb332 --- /dev/null +++ b/app/views/kaminari/_paginator.html.haml @@ -0,0 +1,17 @@ +-# The container tag +-# available local variables +-# current_page: a page object for the currently displayed page +-# num_pages: total number of pages +-# per_page: number of items to fetch per page +-# remote: data-remote +-# paginator: the paginator that renders the pagination tags inside += paginator.render do + %div.pagination + %ul + = prev_page_tag unless current_page.first? + - each_page do |page| + - if page.left_outer? || page.right_outer? || page.inside_window? + = page_tag page + - elsif !page.was_truncated? + = gap_tag + = next_page_tag unless current_page.last? diff --git a/app/views/kaminari/_prev_page.html.haml b/app/views/kaminari/_prev_page.html.haml new file mode 100644 index 00000000..cef885ee --- /dev/null +++ b/app/views/kaminari/_prev_page.html.haml @@ -0,0 +1,9 @@ +-# Link to the "Previous" page +-# available local variables +-# url: url to the previous page +-# current_page: a page object for the currently displayed page +-# num_pages: total number of pages +-# per_page: number of items to fetch per page +-# remote: data-remote +%li{:class => "prev" } + = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote diff --git a/app/views/keys/_form.html.haml b/app/views/keys/_form.html.haml index 1cc7e336..cdabdc73 100644 --- a/app/views/keys/_form.html.haml +++ b/app/views/keys/_form.html.haml @@ -1,16 +1,18 @@ %div - = form_for @key, :remote => true do |f| + = form_for @key do |f| -if @key.errors.any? - %ul - - @key.errors.full_messages.each do |msg| - %li= msg + .alert-message.block-message.error + %ul + - @key.errors.full_messages.each do |msg| + %li= msg - .form-row + .clearfix = f.label :title - = f.text_field :title, :style => "width:300px" - .form-row + .input= f.text_field :title + .clearfix = f.label :key - = f.text_area :key, :style => "width:300px; height:130px" - .form-row - = f.submit 'Save', :class => "grey-button" + .input= f.text_area :key, :class => "xlarge" + .actions + = f.submit 'Save', :class => "primary btn" + = link_to "Cancel", keys_path, :class => "btn" diff --git a/app/views/keys/_show.html.haml b/app/views/keys/_show.html.haml index 3d506e42..1df9b91d 100644 --- a/app/views/keys/_show.html.haml +++ b/app/views/keys/_show.html.haml @@ -1,7 +1,13 @@ -%a.update-item{:href => key_path(key)} - %span.update-title - = key.title - %span.update-author - Added - = time_ago_in_words(key.created_at) - ago +%tr + %td + = link_to key_path(key) do + %p + %strong= key.title + %td + %span.right.cgray + Added + = time_ago_in_words(key.created_at) + ago + %td + = link_to 'Remove', key, :confirm => 'Are you sure?', :method => :delete, :class => "btn small danger delete-key right" + diff --git a/app/views/keys/index.html.haml b/app/views/keys/index.html.haml index 933eef63..59ce7846 100644 --- a/app/views/keys/index.html.haml +++ b/app/views/keys/index.html.haml @@ -1,16 +1,9 @@ -%h2.icon - %span> +%h3 SSH Keys -%div#new-key-holder.right - = link_to "Add new", new_key_path, :remote => true, :class => "grey-button" -%br - -%div#keys-table{ :class => "update-data ui-box ui-box-small ui-box-big" } - .data - - @keys.each do |key| - = render(:partial => 'show', :locals => {:key => key}) - -:javascript - $('.delete-key').live('ajax:success', function() { - $(this).closest('.update-item').fadeOut(); }); + = link_to "Add new", new_key_path, :class => "btn small right" + +%hr +%table#keys-table.zebra-striped.borders + - @keys.each do |key| + = render(:partial => 'show', :locals => {:key => key}) diff --git a/app/views/keys/new.html.haml b/app/views/keys/new.html.haml index fed448b4..743a3173 100644 --- a/app/views/keys/new.html.haml +++ b/app/views/keys/new.html.haml @@ -1,5 +1,3 @@ -%h1 New key - +%h3 New key +%hr = render 'form' - -= link_to 'Back', keys_path diff --git a/app/views/keys/show.html.haml b/app/views/keys/show.html.haml index 9dcaa093..fe7f80d5 100644 --- a/app/views/keys/show.html.haml +++ b/app/views/keys/show.html.haml @@ -1,10 +1,7 @@ -.ui-box.width-100p - %h3= @key.title - .data - %pre= @key.key - .clear - .buttons - = link_to 'Remove', @key, :confirm => 'Are you sure?', :method => :delete, :class => "red-button delete-key right" - .clear +%h3= @key.title +%hr +%pre= @key.key +.actions + = link_to 'Remove', @key, :confirm => 'Are you sure?', :method => :delete, :class => "btn danger delete-key" diff --git a/app/views/layouts/_app_menu.html.haml b/app/views/layouts/_app_menu.html.haml new file mode 100644 index 00000000..27d9b458 --- /dev/null +++ b/app/views/layouts/_app_menu.html.haml @@ -0,0 +1,6 @@ +%nav.main_menu + = render "layouts/const_menu_links" + = link_to "Projects", projects_path, :class => "#{"current" if current_page?(projects_path)}" + = link_to "Issues", dashboard_issues_path, :class => "#{"current" if current_page?(dashboard_issues_path)}", :id => "issues_slide" + = link_to "Requests", dashboard_merge_requests_path, :class => "#{"current" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide" + = link_to "Help", help_path, :class => "#{"current" if controller.controller_name == "help"}" diff --git a/app/views/layouts/_const_menu_links.html.haml b/app/views/layouts/_const_menu_links.html.haml new file mode 100644 index 00000000..ffd028ec --- /dev/null +++ b/app/views/layouts/_const_menu_links.html.haml @@ -0,0 +1 @@ += link_to "Home", root_path, :class => "home #{"current" if current_page?(dashboard_path) || current_page?(root_path)}", :title => "Home" diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml index 4011485c..2e40f0a6 100644 --- a/app/views/layouts/_flash.html.haml +++ b/app/views/layouts/_flash.html.haml @@ -1,16 +1,15 @@ - if alert || notice - text = alert || notice %div{:style => "display:none", :id => "flash_container"} - .container - %center - %h4= text + %center + %h4= text :javascript $(function(){ $("#flash_container").slideDown("slow"); $("#flash_container").click(function(){ $(this).slideUp("slow"); }); - setTimeout("hideFlash()",2000); + setTimeout("hideFlash()",3000); }); function hideFlash(){ diff --git a/app/views/layouts/_head.html.haml b/app/views/layouts/_head.html.haml new file mode 100644 index 00000000..cbe50995 --- /dev/null +++ b/app/views/layouts/_head.html.haml @@ -0,0 +1,17 @@ +%head + %meta{:charset => "utf-8"} + %title + GitLab + = " - #{@project.name}" if @project && !@project.new_record? + = favicon_link_tag 'favicon.ico' + = stylesheet_link_tag "application" + = javascript_include_tag "application" + + -# Atom feed + - if @project && !@project.new_record? + - if current_page?(tree_project_ref_path(@project, @project.root_ref)) || current_page?(project_commits_path(@project)) + = auto_discovery_link_tag(:atom, project_commits_url(@project, :atom, :ref => @ref, :private_token => current_user.private_token), :title => "Recent commits to #{@project.name}:#{@ref}") + - if request.path == project_issues_path(@project) + = auto_discovery_link_tag(:atom, project_issues_url(@project, :atom, :private_token => current_user.private_token), :title => "#{@project.name} issues") + = csrf_meta_tags + diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml index 5f775228..86ad2bd0 100644 --- a/app/views/layouts/_head_panel.html.haml +++ b/app/views/layouts/_head_panel.html.haml @@ -2,32 +2,19 @@ %header.top_panel_holder .wrapper .top_panel_content - %div.main_links + %div.app_logo = link_to root_path, :class => "home", :title => "Home" do - = image_tag "logo.png", :width => 100 + = image_tag "logo_tr.png", :width => 50 + %h1 + GITLAB - - if project_layout - .project_name - = truncate @project.name, :length => 28 - .git_url_wrapper - %input.git-url.text{:id => "", :name => "", :readonly => "", :type => "text", :value => @project.url_to_repo, :class => "one_click_select"} - - if @project.repo_exists? - .left{:style => "margin-left:5px;"} - = render :partial => "projects/refs", :locals => { :destination => controller.controller_name == "commits" ? "commits" : "tree" } - = yield :rss_icon + - if current_user.is_admin? + = link_to admin_projects_path, :class => "admin_link", :title => "Admin area" do + = image_tag "admin.PNG", :width => 16 + + %h1.project_name= title + .search= text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" - - else - .dashboard_links - = link_to "Activities", dashboard_path, :class => "#{"active" if current_page?(dashboard_path) || current_page?(root_path) }" - = link_to "Projects", projects_path, :class => "#{"active" if current_page?(projects_path)}" - = link_to "Issues", dashboard_issues_path, :class => "#{"active" if current_page?(dashboard_issues_path)}", :id => "issues_slide" - = link_to "Requests", dashboard_merge_requests_path, :class => "#{"active" if current_page?(dashboard_merge_requests_path)}", :id => "merge_requests_slide" - - if current_user.is_admin? - = link_to admin_root_path, :class => "admin", :title => "Admin" do - Admin - = link_to "Help", help_path, :class => "#{"active" if controller.controller_name == "help"}" - .search - = text_field_tag "search", nil, :placeholder => "Search", :class => "search-input" .account-box = link_to profile_path, :class => "pic" do @@ -36,16 +23,20 @@ = link_to profile_path, :class => "username" do My profile = link_to 'Logout', destroy_user_session_path, :class => "logout", :method => :delete - - if current_user - = javascript_tag do - $(function(){ - $("#search").autocomplete({ - source: #{raw search_autocomplete_source}, - select: function(event, ui) { location.href = ui.item.url } - }); - }); - -#- if current_user.require_ssh_key? - #no_ssh_key_defined.big-message.error - %p - No SSH Key is defined. You won't be able to use any Git command!. Click #{link_to( 'here', keys_path )} to add one! +:javascript + $(function(){ + $("#search").autocomplete({ + source: #{raw search_autocomplete_source}, + select: function(event, ui) { location.href = ui.item.url } + }); + + $(document).keypress(function(e) { + if( $(e.target).is(":input") ) return; + switch(e.which) { + case 115: focusSearch(); + e.preventDefault(); + } + }); + }); + diff --git a/app/views/layouts/_project_menu.html.haml b/app/views/layouts/_project_menu.html.haml new file mode 100644 index 00000000..1f1b2e60 --- /dev/null +++ b/app/views/layouts/_project_menu.html.haml @@ -0,0 +1,27 @@ +%nav.main_menu + = render "layouts/const_menu_links" + = link_to project_path(@project), :class => "#{project_tab_class}", :title => "Project" do + Project + + - if @project.repo_exists? + - if can? current_user, :download_code, @project + = link_to "Files", tree_project_ref_path(@project, @project.root_ref), :class => tree_tab_class + = link_to "Commits", project_commits_path(@project), :class => commit_tab_class + + = link_to "Network", graph_project_path(@project), :class => current_page?(:controller => "projects", :action => "graph", :id => @project) ? "current" : nil + - if @project.issues_enabled + = link_to project_issues_filter_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do + Issues + %span.count= @project.issues.opened.count + - if @project.merge_requests_enabled + = link_to project_merge_requests_path(@project), :class => (controller.controller_name == "merge_requests") ? "current" : nil do + Merge Requests + %span.count= @project.merge_requests.opened.count + + - if @project.wall_enabled + = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do + Wall + + - if @project.wiki_enabled + = link_to project_wiki_path(@project, :index), :class => (controller.controller_name == "wikis") ? "current" : nil do + Wiki diff --git a/app/views/layouts/_project_side.html.haml b/app/views/layouts/_project_side.html.haml deleted file mode 100644 index 00038cc3..00000000 --- a/app/views/layouts/_project_side.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -.project-sidebar - .fixed - %aside - = link_to project_path(@project), :class => project_tab_class do - Project - - - if @project.repo_exists? - = link_to "Repository", project_repository_path(@project), :class => repository_tab_class - = link_to "Tree", tree_project_ref_path(@project, @ref || @project.root_ref), :class => tree_tab_class - = link_to "Commits", project_commits_path(@project, :ref => (@ref || @project.root_ref)), :class => (controller.controller_name == "commits") ? "current" : nil - = link_to "Network", graph_project_path(@project), :class => current_page?(:controller => "projects", :action => "graph", :id => @project) ? "current" : nil - = link_to project_issues_filter_path(@project), :class => (controller.controller_name == "issues") ? "current" : nil do - Issues - = link_to wall_project_path(@project), :class => current_page?(:controller => "projects", :action => "wall", :id => @project) ? "current" : nil do - Wall - - if @project.common_notes.today.count > 0 - %span{ :class => "number" }= @project.common_notes.today.count - = link_to project_merge_requests_path(@project), :class => (controller.controller_name == "merge_requests") ? "current" : nil do - Requests diff --git a/app/views/layouts/_project_side_right.html.haml b/app/views/layouts/_project_side_right.html.haml new file mode 100644 index 00000000..cc4e6b14 --- /dev/null +++ b/app/views/layouts/_project_side_right.html.haml @@ -0,0 +1,8 @@ +%aside.project-right + - if content_for? :sidebar_all + = render :sidebar_all + - else + - if content_for? :sidebar_top_block + = yield :sidebar_top_block + = render "widgets/project_member" + = render "widgets/recent_projects" diff --git a/app/views/layouts/_projects_side.html.haml b/app/views/layouts/_projects_side.html.haml new file mode 100644 index 00000000..4f0a2e49 --- /dev/null +++ b/app/views/layouts/_projects_side.html.haml @@ -0,0 +1,21 @@ +%aside.projects + - if current_user.can_create_project? + .widget + You can create up to + = current_user.projects_limit + projects. Click on link below to add a new one + .link_holder + = link_to new_project_path, :class => "" do + New Project » + + - if current_user.is_admin? + .widget + You have administrator privilegies. You can configure application following this button: + .link_holder + = link_to admin_root_path, :class => "", :title => "Admin" do + Visit Admin Area » + + - if current_user.projects.count > 0 + = render "widgets/recent_projects" + + diff --git a/app/views/layouts/admin.html.haml b/app/views/layouts/admin.html.haml index 2b318805..df471660 100644 --- a/app/views/layouts/admin.html.haml +++ b/app/views/layouts/admin.html.haml @@ -1,28 +1,15 @@ -!!! -%html - %head - %title - GitLab #{" - #{@project.name}" if @project && !@project.new_record?} - = favicon_link_tag 'favicon.ico' - = stylesheet_link_tag "application" - = javascript_include_tag "application" - = csrf_meta_tags - = javascript_tag do - REQ_URI = "#{request.env["REQUEST_URI"]}"; - REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => body_class('project-page'), :id => yield(:boyd_id)} - = render :partial => "layouts/flash" - #container - = render :partial => "layouts/head_panel" - .project-container - .project-sidebar - .fixed - %aside - = link_to "Users", admin_users_path, :class => controller.controller_name == "users" ? "current" : nil - = link_to "Projects", admin_projects_path, :class => controller.controller_name == "projects" ? "current" : nil - = link_to "Teams", admin_team_members_path, :class => controller.controller_name == "team_members" ? "current" : nil - = link_to "Emails", admin_emails_path, :class => controller.controller_name == "mailer" ? "current" : nil - = link_to "Resque", "/info/resque" +!!! 5 +%html{ :lang => "en"} + = render "layouts/head" + %body.ui_basic.admin + = render "layouts/flash" + = render "layouts/head_panel", :title => "Admin area" + .container + %nav.main_menu + = render "layouts/const_menu_links" + = link_to "Users", admin_users_path, :class => controller.controller_name == "users" ? "current" : nil + = link_to "Projects", admin_projects_path, :class => controller.controller_name == "projects" ? "current" : nil + = link_to "Emails", admin_emails_path, :class => controller.controller_name == "mailer" ? "current" : nil + = link_to "Resque", "/info/resque" - .project-content - = yield + .content= yield diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index e86e5c74..8a1739f1 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,18 +1,10 @@ -!!! -%html - %head - %title - GitLab - = favicon_link_tag 'favicon.ico' - = stylesheet_link_tag "application" - = javascript_include_tag "application" - = csrf_meta_tags - = javascript_tag do - REQ_URI = "#{request.env["REQUEST_URI"]}"; - REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => body_class, :id => yield(:boyd_id)} - = render :partial => "layouts/flash" - #container - = render :partial => "layouts/head_panel" - = render :partial => "layouts/page_title" - = yield +!!! 5 +%html{ :lang => "en"} + = render "layouts/head" + %body.ui_basic.application + = render "layouts/flash" + = render "layouts/head_panel", :title => "Dashboard" + .container + = render :partial => "layouts/app_menu" + .content + = yield diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml index 882195ae..c293734b 100644 --- a/app/views/layouts/devise.html.haml +++ b/app/views/layouts/devise.html.haml @@ -1,15 +1,6 @@ -!!! -%html - %head - %title - GitLab #{" - #{@project.name}" if @project && !@project.new_record?} - = favicon_link_tag 'favicon.ico' - = stylesheet_link_tag "application" - = javascript_include_tag "application" - = csrf_meta_tags - = javascript_tag do - REQ_URI = "#{request.env["REQUEST_URI"]}"; - REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body.login-page +!!! 5 +%html{ :lang => "en"} + = render "layouts/head" + %body.ui_basic.login-page = render :partial => "layouts/flash" - = yield + .container= yield diff --git a/app/views/layouts/error.html.haml b/app/views/layouts/error.html.haml new file mode 100644 index 00000000..544fdcc7 --- /dev/null +++ b/app/views/layouts/error.html.haml @@ -0,0 +1,11 @@ +!!! 5 +%html{ :lang => "en"} + = render "layouts/head" + %body.ui_basic.application + = render "layouts/flash" + = render "layouts/head_panel", :title => "" + .container + %nav.main_menu + = render "layouts/const_menu_links" + .content + %h3= yield diff --git a/app/views/layouts/profile.html.haml b/app/views/layouts/profile.html.haml index 6eeecb29..091e8563 100644 --- a/app/views/layouts/profile.html.haml +++ b/app/views/layouts/profile.html.haml @@ -1,30 +1,18 @@ -!!! -%html - %head - %title - GitLab #{" - #{@project.name}" if @project && !@project.new_record?} - = favicon_link_tag 'favicon.ico' - = stylesheet_link_tag "application" - = javascript_include_tag "application" - = csrf_meta_tags - = javascript_tag do - REQ_URI = "#{request.env["REQUEST_URI"]}"; - REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => body_class('project-page'), :id => yield(:boyd_id)} - = render :partial => "layouts/flash" - #container - = render :partial => "layouts/head_panel" - .project-container - .project-sidebar - .fixed - %aside - = link_to "Profile", profile_path, :class => current_page?(:controller => "profile", :action => :show) ? "current" : nil - = link_to "Password & token", profile_password_path, :class => current_page?(:controller => "profile", :action => :password) ? "current" : nil - = link_to "Design", profile_design_path, :class => current_page?(:controller => "profile", :action => :design) ? "current" : nil - = link_to keys_path, :class => controller.controller_name == "keys" ? "current" : nil do - Keys - - unless current_user.keys.empty? - %span{ :class => "number" }= current_user.keys.count - - .project-content - = yield +!!! 5 +%html{ :lang => "en"} + = render "layouts/head" + %body.ui_basic.profile + = render "layouts/flash" + = render "layouts/head_panel", :title => "Profile" + .container + %nav.main_menu + = render "layouts/const_menu_links" + = link_to "Profile", profile_path, :class => current_page?(:controller => "profile", :action => :show) ? "current" : nil + = link_to "Password & token", profile_password_path, :class => current_page?(:controller => "profile", :action => :password) ? "current" : nil + = link_to "Design", profile_design_path, :class => current_page?(:controller => "profile", :action => :design) ? "current" : nil + = link_to keys_path, :class => controller.controller_name == "keys" ? "current" : nil do + SSH Keys + .content + .row + .span12= yield + .sidebar= render "layouts/projects_side" diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml index a87b3400..2bc326df 100644 --- a/app/views/layouts/project.html.haml +++ b/app/views/layouts/project.html.haml @@ -1,24 +1,16 @@ -!!! -%html - %head - %title - GitLab #{" - #{@project.name}" if @project && !@project.new_record?} - = favicon_link_tag 'favicon.ico' - = stylesheet_link_tag "application" - = javascript_include_tag "application" - - if current_page?(tree_project_ref_path(@project, @project.root_ref)) || current_page?(project_commits_path(@project)) - = auto_discovery_link_tag(:atom, project_commits_url(@project, :atom, :ref => @ref, :private_token => current_user.private_token), :title => "Recent commits to #{@project.name}:#{@ref}") - - if request.path == project_issues_path(@project) - = auto_discovery_link_tag(:atom, project_issues_url(@project, :atom, :private_token => current_user.private_token), :title => "#{@project.name} issues") - = csrf_meta_tags - = javascript_tag do - REQ_URI = "#{request.env["REQUEST_URI"]}"; - REQ_REFFER = "#{request.env["HTTP_REFERER"]}"; - %body{ :class => body_class('project-page'), :id => yield(:boyd_id)} - = render :partial => "layouts/flash" - #container - = render :partial => "layouts/head_panel" - .project-container - = render :partial => "layouts/project_side" - .project-content +!!! 5 +%html{ :lang => "en"} + = render "layouts/head" + %body.ui_basic.project + = render "layouts/flash" + = render "layouts/head_panel", :title => @project.name + .container + = render :partial => "layouts/project_menu" + .content + - if @full_content = yield + - else + .row + .span12= yield + .sidebar= render "layouts/project_side_right" + diff --git a/app/views/merge_requests/_commits.html.haml b/app/views/merge_requests/_commits.html.haml index c0d7486b..7606e71e 100644 --- a/app/views/merge_requests/_commits.html.haml +++ b/app/views/merge_requests/_commits.html.haml @@ -1,19 +1,13 @@ -- if @commits.size > 0 - .merge-request-commits.ui-box.width-100p - - @commits.each do |commit| - %a{ :class => "commit", :href => project_commit_path(@project, :id => commit.id) } - - if commit.author_email - = image_tag gravatar_icon(commit.author_email), :class => "left", :width => 40, :style => "padding-right:5px;" - - else - = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" - %span.update-title - = truncate commit.safe_message, :length => 60 - %span.update-author - %strong= commit.author_name - authored - = time_ago_in_words(commit.created_at) - ago - .clear +- unless @commits.empty? + .ui-box + %h5 Commits + .merge-request-commits + %ul.unstyled= render @commits -- if @commits.empty? - %p.cgray Nothing to merge +- else + %h5 + Nothing to merge from + %span.label #{@merge_request.source_branch} + to + %span.label #{@merge_request.target_branch} + %br diff --git a/app/views/merge_requests/_diffs.html.haml b/app/views/merge_requests/_diffs.html.haml index ef6b0f1f..bd904a77 100644 --- a/app/views/merge_requests/_diffs.html.haml +++ b/app/views/merge_requests/_diffs.html.haml @@ -1,24 +1,3 @@ -- @diffs.each_with_index do |diff, i| - - next if diff.diff.empty? - - file = (@commit.tree / diff.b_path) - - next unless file - .diff_file - .diff_file_header - - if diff.deleted_file - %strong{:id => "#{diff.b_path}"}= diff.a_path - - else - = link_to tree_file_project_ref_path(@project, @commit.id, diff.b_path) do - %strong{:id => "#{diff.b_path}"}= diff.b_path - %br/ - .diff_file_content - - if file.text? - = render :partial => "commits/text_file", :locals => { :diff => diff, :index => i } - - elsif file.image? - .diff_file_content_image - %img{:src => "data:#{file.mime_type};base64,#{Base64.encode64(file.data)}"} - - else - %p - %center No preview for this file type - += render "commits/diffs", :diffs => @diffs - if @diffs.empty? %p.cgray Nothing to merge diff --git a/app/views/merge_requests/_form.html.haml b/app/views/merge_requests/_form.html.haml index d771661b..cab517dc 100644 --- a/app/views/merge_requests/_form.html.haml +++ b/app/views/merge_requests/_form.html.haml @@ -1,46 +1,35 @@ = form_for [@project, @merge_request] do |f| - %div - %span.entity-info - - if @merge_request.new_record? - = link_to project_merge_requests_path(@project) do - .entity-button - Merge Requests - %i - - else - = link_to project_merge_request_path(@project, @merge_request) do - .entity-button - Show Merge Request - %i + -if @merge_request.errors.any? + .alert-message.block-message.error + %ul + - @merge_request.errors.full_messages.each do |msg| + %li= msg - %h2= @merge_request.new_record? ? "New Merge Request" : "Edit Merge Request ##{@merge_request.id}" + .clearfix + = f.label :source_branch, "From" + .input= f.select(:source_branch, @project.heads.map(&:name), { :include_blank => "Select branch" }, :style => "width:250px") + .clearfix + = f.label :target_branch, "To" + .input= f.select(:target_branch, @project.heads.map(&:name), { :include_blank => "Select branch" }, :style => "width:250px") + .clearfix + = f.label :assignee_id, "Assign to" + .input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }, :style => "width:250px") - %hr - %table.no-borders - -if @merge_request.errors.any? - %tr - %td{:colspan => 2} - #error_explanation - - @merge_request.errors.full_messages.each do |msg| - %span= msg - %br - %tr - %td= f.label :source_branch, "From" - %td= f.select(:source_branch, @project.heads.map(&:name), { :include_blank => "Select branch" }, :style => "width:250px") - %tr - %td= f.label :target_branch, "To" - %td= f.select(:target_branch, @project.heads.map(&:name), { :include_blank => "Select branch" }, :style => "width:250px") - %tr - %td= f.label :assignee_id, "Assign to" - %td= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }, :style => "width:250px") - = f.text_area :title, :style => "width:718px; height:100px", :maxlength => 255 - %br - %br - .merge-tabs - = f.submit 'Save', :class => "positive-button" + .clearfix + = f.label :title + .input= f.text_area :title, :class => "xlarge", :maxlength => 255, :rows => 5 + .actions + = f.submit 'Save', :class => "primary btn" + - if @merge_request.new_record? + = link_to project_merge_requests_path(@project), :class => "btn" do + Cancel + - else + = link_to project_merge_request_path(@project, @merge_request), :class => "btn" do + Cancel   - unless @merge_request.new_record? .right - = link_to 'Remove', [@project, @merge_request], :confirm => 'Are you sure?', :method => :delete, :class => "red-button" + = link_to 'Remove', [@project, @merge_request], :confirm => 'Are you sure?', :method => :delete, :class => "btn danger" diff --git a/app/views/merge_requests/_head.html.haml b/app/views/merge_requests/_head.html.haml index ccebd8ef..3d847b30 100644 --- a/app/views/merge_requests/_head.html.haml +++ b/app/views/merge_requests/_head.html.haml @@ -2,11 +2,4 @@ = link_to project_merge_requests_path(@project), :class => "tab #{'active' if current_page?(project_merge_requests_path(@project)) }" do %span Merge Requests - - - - if current_page?(project_merge_requests_path(@project)) - - if can? current_user, :write_merge_request, @project - = link_to new_project_merge_request_path(@project), :class => "add_new", :title => "New Merge request" do - Add new - diff --git a/app/views/merge_requests/_how_to_merge.html.haml b/app/views/merge_requests/_how_to_merge.html.haml new file mode 100644 index 00000000..19caca3f --- /dev/null +++ b/app/views/merge_requests/_how_to_merge.html.haml @@ -0,0 +1,25 @@ +%div#modal_merge_info.modal.hide + .modal-header + %a.close{:href => "#"} × + %h3 How To Merge + .modal-body + %pre + :erb + git fetch origin + git checkout -b <%=@merge_request.source_branch%> origin/<%=@merge_request.source_branch%> + git checkout <%=@merge_request.target_branch%> + git merge <%=@merge_request.source_branch%> + git push origin <%=@merge_request.target_branch%> + + +:javascript + $(function(){ + var modal = $('#modal_merge_info').modal({modal: true}); + $('.info_link').bind("click", function(){ + modal.show(); + }); + $('.modal-header .close').bind("click", function(){ + modal.hide(); + }) + }) + diff --git a/app/views/merge_requests/_merge_request.html.haml b/app/views/merge_requests/_merge_request.html.haml index 262aa661..583cc440 100644 --- a/app/views/merge_requests/_merge_request.html.haml +++ b/app/views/merge_requests/_merge_request.html.haml @@ -1,14 +1,13 @@ -%a.update-item{:href => project_merge_request_path(merge_request.project, merge_request)} - = image_tag gravatar_icon(merge_request.author_email), :class => "left", :width => 40 - %span.update-title - = truncate(merge_request.title, :length => 60) +%li.wll + = image_tag gravatar_icon(merge_request.author_email), :class => "avatar" %span.update-author %strong= merge_request.author_name authored = time_ago_in_words(merge_request.created_at) ago .right - %span.tag.commit= merge_request.source_branch + %span.label= merge_request.source_branch → - %span.tag.commit= merge_request.target_branch - + %span.label= merge_request.target_branch + = link_to project_merge_request_path(merge_request.project, merge_request) do + %p.row_title= truncate(merge_request.title, :length => 60) diff --git a/app/views/merge_requests/edit.html.haml b/app/views/merge_requests/edit.html.haml index bcc58327..9e4f9327 100644 --- a/app/views/merge_requests/edit.html.haml +++ b/app/views/merge_requests/edit.html.haml @@ -1 +1,4 @@ +%h3 + = "Edit merge request #{@merge_request.id}" +%hr = render 'form' diff --git a/app/views/merge_requests/index.html.haml b/app/views/merge_requests/index.html.haml index fa02be9e..9ced7a86 100644 --- a/app/views/merge_requests/index.html.haml +++ b/app/views/merge_requests/index.html.haml @@ -1,30 +1,26 @@ -= render "merge_requests/head" +%h3 + Merge Requests + - if can? current_user, :write_issue, @project + = link_to new_project_merge_request_path(@project), :class => "right btn small", :title => "New Merge Request" do + New Merge Request -.left.issues_filter - = form_tag project_merge_requests_path(@project), :method => :get do - .left - = radio_button_tag :f, 0, (params[:f] || "0") == "0", :onclick => "this.form.submit()", :id => "open_merge_requests", :class => "status" - = label_tag "open_merge_requests" do - %span.tag.open Open - .left - = radio_button_tag :f, 2, params[:f] == "2", :onclick => "this.form.submit()", :id => "closed_merge_requests", :class => "status" - = label_tag "closed_merge_requests" do - %span.tag.closed Closed +%br -.clear -%hr +.ui-box + .title + %ul.pills + %li{:class => ("active" if (params[:f] == "0" || !params[:f]))} + = link_to project_merge_requests_path(@project, :f => 0) do + Open + %li{:class => ("active" if params[:f] == "2")} + = link_to project_merge_requests_path(@project, :f => 2) do + Closed + %li{:class => ("active" if params[:f] == "3")} + = link_to project_merge_requests_path(@project, :f => 3) do + To Me + %li{:class => ("active" if params[:f] == "1")} + = link_to project_merge_requests_path(@project, :f => 1) do + All -- if @merge_requests.count > 0 - %div{ :class => "update-data ui-box ui-box-small ui-box-big" } - .data - = render @merge_requests - - .clear - %br - -- unless @merge_requests.count > 0 || params[:f] == "2" - .notice_holder - %li Merge Requests do not exist yet. - - if can? current_user, :write_merge_request, @project - %li You can add a new one by clicking on "Add New" button + %ul.unstyled= render @merge_requests diff --git a/app/views/merge_requests/new.html.haml b/app/views/merge_requests/new.html.haml index bcc58327..efafa45d 100644 --- a/app/views/merge_requests/new.html.haml +++ b/app/views/merge_requests/new.html.haml @@ -1 +1,3 @@ +%h3 New Merge Request +%hr = render 'form' diff --git a/app/views/merge_requests/show.html.haml b/app/views/merge_requests/show.html.haml index 6fc6d5c1..e725c198 100644 --- a/app/views/merge_requests/show.html.haml +++ b/app/views/merge_requests/show.html.haml @@ -1,65 +1,70 @@ -%div - %span.entity-info - - if can?(current_user, :admin_project, @project) || @merge_request.author == current_user - = link_to edit_project_merge_request_path(@project, @merge_request) do - .entity-button - Edit Merge Request - %i - = image_tag gravatar_icon(@merge_request.author_email), :class => "left", :width => 40, :style => "padding-right:5px;" - %span.commit-title - %strong - = "Merge Request ##{@merge_request.id}:" -   - .tag.commit.inline= @merge_request.source_branch - → - .tag.commit.inline= @merge_request.target_branch - %span.commit-author - %strong - = link_to project_team_member_path(@project, @project.team_member_by_id(@merge_request.author.id)) do - %span.author= @merge_request.author_name - → - = link_to project_team_member_path(@project, @project.team_member_by_id(@merge_request.assignee.id)) do - %span.author= @merge_request.assignee_name +%h3 + = "Merge Request ##{@merge_request.id}:" +   + %span.label= @merge_request.source_branch + → + %span.label= @merge_request.target_branch -   -   - = @merge_request.created_at.stamp("Aug 21, 2011 9:23pm") + %small + created at + = @merge_request.created_at.stamp("Aug 21, 2011") - %hr - %br - %h3 - = simple_format @merge_request.title - -.clear -%br -%br - -.merge-tabs - = link_to "#notes", :class => "merge-notes-tab active tab" do - %span - Notes - = link_to "#commits", "data-url" => commits_project_merge_request_path(@project, @merge_request), :class => "merge-commits-tab tab" do - %span - Commits - = link_to "#diffs", "data-url" => diffs_project_merge_request_path(@project, @merge_request), :class => "merge-diffs-tab tab" do - %span - Diff - - - if can?(current_user, :admin_project, @project) || @merge_request.author == current_user - .right + %span.right + - if can?(current_user, :modify_merge_request, @merge_request) - if @merge_request.closed - = link_to 'Reopen', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => false }, :status_only => true), :method => :put, :class => "red-button" + = link_to 'Reopen', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => false }, :status_only => true), :method => :put, :class => "btn" - else - = link_to 'Close', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => true }, :status_only => true), :method => :put, :class => "positive-button", :title => "Close merge request" - %img{:src => "/assets/ajax-loader-facebook.gif", :class => "dashboard-loader"} + = link_to 'Close', project_merge_request_path(@project, @merge_request, :merge_request => {:closed => true }, :status_only => true), :method => :put, :class => "btn", :title => "Close merge request" + = link_to edit_project_merge_request_path(@project, @merge_request), :class => "btn small" do + Edit + +.back_link + = link_to project_merge_requests_path(@project) do + ← To merge requests + + +%hr +- if @merge_request.closed + .alert-message.error Closed +- else + .alert-message.success + = link_to "#", :class => "info_link", :title => "How To Merge" do + = image_tag "Info-UI.PNG" + Open + += render "merge_requests/how_to_merge" + +%div.well + %div + %cite.cgray Created by + = image_tag gravatar_icon(@merge_request.author_email), :width => 16, :class => "lil_av" + %strong.author= link_to_merge_request_author(@merge_request) + + %cite.cgray and currently assigned to + = image_tag gravatar_icon(@merge_request.assignee_email), :width => 16, :class => "lil_av" + %strong.author= link_to_merge_request_assignee(@merge_request) + + %hr + + + %div= simple_format @merge_request.title + += render "merge_requests/commits" + +- unless @commits.empty? + .tabs + %li.active + = link_to "#notes", :class => "merge-notes-tab tab" do + Notes + %li + = link_to "#diffs", "data-url" => diffs_project_merge_request_path(@project, @merge_request), :class => "merge-diffs-tab tab" do + Diff + + %img{:src => "/assets/ajax-loader-facebook.gif", :class => "dashboard-loader"} .merge-request-notes - .issue_notes= render "notes/notes" - .loading{ :style => "display:none;"} - %center= image_tag "ajax-loader.gif" - .clear + .merge_request_notes= render "notes/notes", :tid => @merge_request.id, :tt => "merge_request" -.merge-request-commits .merge-request-diffs @@ -67,3 +72,15 @@ $(function(){ MergeRequest.init(); }) + += render "notes/per_line_form" +:javascript + $(document).ready(function(){ + $(".line_note_link, .line_note_reply_link").live("click", function(e) { + var form = $(".per_line_form"); + $(this).parent().parent().after(form); + form.find("#note_line_code").val($(this).attr("line_code")); + form.show(); + return false; + }); + }); diff --git a/app/views/notes/_create_common.js.haml b/app/views/notes/_create_common.js.haml new file mode 100644 index 00000000..583812bf --- /dev/null +++ b/app/views/notes/_create_common.js.haml @@ -0,0 +1,9 @@ +- if note.valid? + :plain + $("#new_note .errors").remove(); + $('#new_note textarea').val(""); + NoteList.prepend(#{note.id}, "#{escape_javascript(render :partial => "notes/show", :locals => {:note => note})}"); +- else + :plain + $("#new_note").replaceWith("#{escape_javascript(render('form'))}"); + diff --git a/app/views/notes/_create_line.js.haml b/app/views/notes/_create_line.js.haml new file mode 100644 index 00000000..9cf085cd --- /dev/null +++ b/app/views/notes/_create_line.js.haml @@ -0,0 +1,8 @@ +- if note.valid? + :plain + $(".per_line_form").hide(); + $('#new_note textarea').val(""); + $("a.line_note_reply_link[line_code='#{note.line_code}']").closest("tr").remove(); + var trEl = $(".#{note.line_code}").parent(); + trEl.after("#{escape_javascript(render :partial => "notes/per_line_show", :locals => {:note => note})}"); + trEl.after("#{escape_javascript(render :partial => "notes/reply_button", :locals => {:line_code => note.line_code})}"); diff --git a/app/views/notes/_form.html.haml b/app/views/notes/_form.html.haml index 95a3b01a..0d20bb15 100644 --- a/app/views/notes/_form.html.haml +++ b/app/views/notes/_form.html.haml @@ -1,37 +1,31 @@ -%div - = form_for [@project, @note], :remote => "true", :multipart => true do |f| - -if @note.errors.any? - .errors.error - - @note.errors.full_messages.each do |msg| - %div= msg += form_for [@project, @note], :remote => "true", :multipart => true do |f| + %h3 Leave a note + -if @note.errors.any? + .alert-message.block-message.error + - @note.errors.full_messages.each do |msg| + %div= msg - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + = f.text_area :note, :size => 255 - %div - = f.label :note - %cite.cgray markdown supported - %br - %br - = f.text_area :note, :size => 255 + .row + .span4 + %h5 Notify via email: + .clearfix + = label_tag :notify do + = check_box_tag :notify, 1, @note.noteable_type != "Commit" + %span Project team - %div.attach_holder - %br - = f.label :attachment - %cite.cgray (less than 10 MB) - %br - %br - = f.file_field :attachment - - %p.notify_controls - %span Notify: - = check_box_tag :notify, 1, @note.noteable_type != "Commit" - = label_tag :notify, "Project team" + - if @note.notify_only_author?(current_user) + = label_tag :notify_author do + = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" + %span Commit author + .span4 + %h5 Attachment: + .clearfix + = f.label :attachment, "Any file, < 10 MB" + .input= f.file_field :attachment, :class => "input-file" - -if @note.noteable_type == "Commit" - = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" - = label_tag :notify_author, "Commit author" - .clear - %br - = f.submit 'Add note', :class => "positive-button", :id => "submit_note" + = f.submit 'Add note', :class => "btn primary", :id => "submit_note" diff --git a/app/views/notes/_load.js.haml b/app/views/notes/_load.js.haml index 62d44fe1..fa373145 100644 --- a/app/views/notes/_load.js.haml +++ b/app/views/notes/_load.js.haml @@ -1,12 +1,7 @@ - unless @notes.blank? - - - if params[:last_id] && params[:first_id] + - if params[:last_id] :plain - NoteList.replace(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); - - - elsif params[:last_id] - :plain - NoteList.prepend(#{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); + NoteList.replace("#{escape_javascript(render(:partial => 'notes/notes_list'))}"); - elsif params[:first_id] :plain @@ -14,3 +9,9 @@ - else :plain + NoteList.setContent(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}"); + +- else + - if params[:first_id] + :plain + NoteList.append(#{params[:first_id]}, ""); diff --git a/app/views/notes/_notes.html.haml b/app/views/notes/_notes.html.haml index 4a5c3aab..e692e746 100644 --- a/app/views/notes/_notes.html.haml +++ b/app/views/notes/_notes.html.haml @@ -2,25 +2,12 @@ = render "notes/form" .clear %hr -%ul#notes-list= render "notes/notes_list" +%ul#new_notes_list +%ul#notes-list +.status + :javascript - $('.delete-note').live('ajax:success', function() { - $(this).closest('li').fadeOut(); }); - - $("#new_note").live("ajax:before", function(){ - $("#submit_note").attr("disabled", "disabled"); - }) - - $("#new_note").live("ajax:complete", function(){ - $("#submit_note").removeAttr("disabled"); - }) - $(function(){ - $("#note_note").live("click", function(){ - $(this).css("height", "100px"); - $('.attach_holder').show(); - }); - - NoteList.init("wall", #{@notes.last.try(:id) || 0}, #{@notes.first.try(:id) || 0}); + NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}"); }); diff --git a/app/views/notes/_per_line_form.html.haml b/app/views/notes/_per_line_form.html.haml index 72989320..28faa630 100644 --- a/app/views/notes/_per_line_form.html.haml +++ b/app/views/notes/_per_line_form.html.haml @@ -1,29 +1,33 @@ %table{:style => "display:none;"} %tr.per_line_form %td{:colspan => 3 } - %div - = form_for [@project, @note], :remote => "true", :multipart => true do |f| - -if @note.errors.any? - .errors.error - - @note.errors.full_messages.each do |msg| - %div= msg + = form_for [@project, @note], :remote => "true", :multipart => true do |f| + %h3 Leave a note + .row + .span16 + -if @note.errors.any? + .alert-message.block-message.error + - @note.errors.full_messages.each do |msg| + %div= msg - = f.hidden_field :noteable_id - = f.hidden_field :noteable_type - = f.hidden_field :line_code - - %div - = f.label :note - %cite.cgray markdown supported - %br - %br + = f.hidden_field :noteable_id + = f.hidden_field :noteable_type + = f.hidden_field :line_code = f.text_area :note, :size => 255 + .actions + = f.submit 'Add note', :class => "btn primary", :id => "submit_note" + = link_to "Close", "#", :class => "btn hide-button" + .span6.entry + %h5 Notify via email: + .clearfix + = label_tag :notify do + = check_box_tag :notify, 1, @note.noteable_type != "Commit" + %span Project team - .clear - %br - = f.submit 'Add note', :class => "positive-button", :id => "submit_note" - .right - = link_to "Close", "#", :class => "grey-button hide-button" + - if @note.notify_only_author?(current_user) + = label_tag :notify_author do + = check_box_tag :notify_author, 1 , @note.noteable_type == "Commit" + %span Commit author :javascript $(function(){ diff --git a/app/views/notes/_reply_button.html.haml b/app/views/notes/_reply_button.html.haml new file mode 100644 index 00000000..f53b8c8d --- /dev/null +++ b/app/views/notes/_reply_button.html.haml @@ -0,0 +1,3 @@ +%tr.line_notes_row.reply + %td{:colspan => 3} + = link_to "Reply", "#", :class => "line_note_reply_link", "line_code" => line_code, :title => "Add note for this line" diff --git a/app/views/notes/_show.html.haml b/app/views/notes/_show.html.haml index d91fea04..6da1d590 100644 --- a/app/views/notes/_show.html.haml +++ b/app/views/notes/_show.html.haml @@ -6,7 +6,7 @@ = time_ago_in_words(note.updated_at) ago - if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project) - = link_to "Remove", [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-note right" + %strong= link_to "Remove", [@project, note], :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "cred delete-note btn small" %div.note-title = markdown(note.note) diff --git a/app/views/notes/create.js.haml b/app/views/notes/create.js.haml index b81ea5b0..67110340 100644 --- a/app/views/notes/create.js.haml +++ b/app/views/notes/create.js.haml @@ -1,18 +1,8 @@ -- if @note.valid? - - if @note.line_code - :plain - $(".per_line_form").hide(); - $('#new_note textarea').val(""); - $(".#{@note.line_code}").parent().after("#{escape_javascript(render :partial => "notes/per_line_show", :locals => {:note => @note})}"); - - else - :plain - $("#new_note .errors").remove(); - $('#new_note textarea').val(""); - NoteList.prepend(#{@note.id}, "#{escape_javascript(render :partial => "notes/show", :locals => {:note => @note})}"); -- else - - unless @note.line_code - :plain - $("#new_note").replaceWith("#{escape_javascript(render('form'))}"); +- if @note.line_code + = render "create_line", :note => @note +- else + = render "create_common", :note => @note +-# Enable submit button :plain $("#submit_note").removeAttr("disabled"); diff --git a/app/views/commits/show.js.haml b/app/views/notes/index.js.haml similarity index 100% rename from app/views/commits/show.js.haml rename to app/views/notes/index.js.haml diff --git a/app/views/notify/note_commit_email.html.haml b/app/views/notify/note_commit_email.html.haml index 81001d68..41501dee 100644 --- a/app/views/notify/note_commit_email.html.haml +++ b/app/views/notify/note_commit_email.html.haml @@ -4,7 +4,7 @@ %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %td{:align => "left", :style => "padding: 20px 0 0;"} %h2{:style => "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} - New comment for commmit + New comment for commit = link_to truncate(@commit.id.to_s, :length => 16), project_commit_url(@project, :id => @commit.id, :anchor => "note_#{@note.id}") %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} %tr @@ -17,7 +17,7 @@ %table{:border => "0", :cellpadding => "0", :cellspacing => "0", :width => "558"} %tr %td{:valign => "top"} - %cite{:style => "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "} - = @note.note + %div{ :style => "background:#f5f5f5; padding:20px;border:1px solid #ddd" } + = RDiscount.new(@note.note, :autolink, :no_pseudo_protocols, :safelink, :smart, :filter_html).to_html.html_safe %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} diff --git a/app/views/notify/note_issue_email.html.haml b/app/views/notify/note_issue_email.html.haml index 7d8e2156..28db944f 100644 --- a/app/views/notify/note_issue_email.html.haml +++ b/app/views/notify/note_issue_email.html.haml @@ -19,7 +19,7 @@ %table{:border => "0", :cellpadding => "0", :cellspacing => "0", :width => "558"} %tr %td{:valign => "top"} - %cite{:style => "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "} - = @note.note + %div{ :style => "background:#f5f5f5; padding:20px;border:1px solid #ddd" } + = RDiscount.new(@note.note, :autolink, :no_pseudo_protocols, :safelink, :smart, :filter_html).to_html.html_safe %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} diff --git a/app/views/notify/note_merge_request_email.html.haml b/app/views/notify/note_merge_request_email.html.haml index 27854e23..6a97f9ca 100644 --- a/app/views/notify/note_merge_request_email.html.haml +++ b/app/views/notify/note_merge_request_email.html.haml @@ -17,7 +17,7 @@ %table{:border => "0", :cellpadding => "0", :cellspacing => "0", :width => "558"} %tr %td{:valign => "top"} - %cite{:style => "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "} - = @note.note + %div{ :style => "background:#f5f5f5; padding:20px;border:1px solid #ddd" } + = RDiscount.new(@note.note, :autolink, :no_pseudo_protocols, :safelink, :smart, :filter_html).to_html.html_safe %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} diff --git a/app/views/notify/note_wall_email.html.haml b/app/views/notify/note_wall_email.html.haml index a2bd5a76..77b58f15 100644 --- a/app/views/notify/note_wall_email.html.haml +++ b/app/views/notify/note_wall_email.html.haml @@ -17,6 +17,6 @@ %table{:border => "0", :cellpadding => "0", :cellspacing => "0", :width => "558"} %tr %td{:valign => "top"} - %cite{:style => "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "} - = @note.note + %div{ :style => "background:#f5f5f5; padding:20px;border:1px solid #ddd" } + = RDiscount.new(@note.note, :autolink, :no_pseudo_protocols, :safelink, :smart, :filter_html).to_html.html_safe %td{:style => "font-size: 1px; line-height: 1px;", :width => "21"} diff --git a/app/views/profile/design.html.haml b/app/views/profile/design.html.haml index 4a0f758d..68746fdc 100644 --- a/app/views/profile/design.html.haml +++ b/app/views/profile/design.html.haml @@ -1,22 +1,20 @@ -.ui-box.width-100p - %h3 Design - = form_for @user, :url => profile_update_path, :method => :put do |f| - .data - .left.dark_scheme_box - %label{:for => "user_dark_scheme_false"} - = image_tag "white.png", :width => 310, :height => 212 - %center - %h4 - = f.radio_button :dark_scheme, false - White code preview - .right.dark_scheme_box - %label{:for => "user_dark_scheme_true"} - = image_tag "dark.png", :width => 310, :height => 212 - %center - %h4 - = f.radio_button :dark_scheme, true - Dark code preview - .clear - .buttons - = f.submit 'Save', :class => "grey-button" +%h3 Design +%hr += form_for @user, :url => profile_update_path, :method => :put do |f| + .row + %label.span4{:for => "user_dark_scheme_false"} + = image_tag "white.png", :width => 210 + %center + %h4 + = f.radio_button :dark_scheme, false + White code preview + %label.span4{:for => "user_dark_scheme_true"} + = image_tag "dark.png", :width => 210 + %center + %h4 + = f.radio_button :dark_scheme, true + Dark code preview + .clearfix + .actions + = f.submit 'Save', :class => "btn" diff --git a/app/views/profile/password.html.haml b/app/views/profile/password.html.haml index 893263f7..dc1f2214 100644 --- a/app/views/profile/password.html.haml +++ b/app/views/profile/password.html.haml @@ -1,44 +1,42 @@ -.ui-box.width-100p.append-bottom-20 - %h3 Password - = form_for @user, :url => profile_password_path, :method => :put do |f| - .data +%h3 Password +%hr += form_for @user, :url => profile_password_path, :method => :put do |f| + .data + .alert-message.block-message.warning %p After successfull password update you will be redirected to login page where you should login with new password - -if @user.errors.any? - #error_explanation - %ul - - @user.errors.full_messages.each do |msg| - %li= msg + -if @user.errors.any? + .alert-message.block-message.error + %ul + - @user.errors.full_messages.each do |msg| + %li= msg - .form-row - = f.label :password - %br - = f.password_field :password - .form-row - = f.label :password_confirmation - %br - = f.password_field :password_confirmation - .buttons - = f.submit 'Save', :class => "grey-button" -.clear - -.ui-box.width-100p - %h3 - Private token - %em.cred.right - keep it in secret! - = form_for @user, :url => profile_reset_private_token_path, :method => :put do |f| - .data - %p Private token used to access application resources without authentication. - %p For example its required to access commits feed. - %hr - %p.cgray - - if current_user.private_token - = text_field_tag "token", current_user.private_token - - else - You don`t have one yet. Click generate to fix it. - .buttons + .clearfix + = f.label :password + .input= f.password_field :password + .clearfix + = f.label :password_confirmation + .input= f.password_field :password_confirmation + .actions + = f.submit 'Save', :class => "btn" + +%h3 + Private token + %span.cred.right + keep it in secret! +%hr += form_for @user, :url => profile_reset_private_token_path, :method => :put do |f| + .data + %p Private token used to access application resources without authentication. + %p For example its required to access commits feed. + %hr + %p.cgray - if current_user.private_token - = f.submit 'Reset', :confirm => "Are you sure?", :class => "grey-button" + = text_field_tag "token", current_user.private_token - else - = f.submit 'Generate', :class => "positive-button" + You don`t have one yet. Click generate to fix it. + .actions + - if current_user.private_token + = f.submit 'Reset', :confirm => "Are you sure?", :class => "btn" + - else + = f.submit 'Generate', :class => "btn" diff --git a/app/views/profile/show.html.haml b/app/views/profile/show.html.haml index 8ebb4dcb..2c2249bf 100644 --- a/app/views/profile/show.html.haml +++ b/app/views/profile/show.html.haml @@ -1,38 +1,33 @@ -.ui-box.width-100p - %h3= @user.name - = form_for @user, :url => profile_update_path, :method => :put do |f| - .data - .left - -if @user.errors.any? - #error_explanation - %ul - - @user.errors.full_messages.each do |msg| - %li= msg +.media-grid + = link_to "#" do + = image_tag gravatar_icon(@user.email, 90), :class => "thumbnail" + %h3.media_h= @user.name - .form-row - = f.label :name - %br - = f.text_field :name - .form-row - = f.label :email - %br - = f.text_field :email - .form-row - = f.label :skype - %br - = f.text_field :skype - .form-row - = f.label :linkedin - %br - = f.text_field :linkedin - .form-row - = f.label :twitter - %br - = f.text_field :twitter +%hr - .right - = image_tag gravatar_icon(current_user.email,64), :width => 64, :style => "margin:5px; border:5px solid #eee;" - .clear - .buttons - = f.submit 'Save', :class => "grey-button" += form_for @user, :url => profile_update_path, :method => :put do |f| + -if @user.errors.any? + %div.alert-message.block-message.error + %ul + - @user.errors.full_messages.each do |msg| + %li= msg + + .clearfix + = f.label :name + .input= f.text_field :name + .clearfix + = f.label :email + .input= f.text_field :email + .clearfix + = f.label :skype + .input= f.text_field :skype + .clearfix + = f.label :linkedin + .input= f.text_field :linkedin + .clearfix + = f.label :twitter + .input= f.text_field :twitter + + .actions + = f.submit 'Save', :class => "primary btn" diff --git a/app/views/projects/_feed.html.haml b/app/views/projects/_feed.html.haml index 4f8e59f8..f907b8a2 100644 --- a/app/views/projects/_feed.html.haml +++ b/app/views/projects/_feed.html.haml @@ -1,79 +1,23 @@ -- if update.kind_of?(Note) - %a.project-update.titled{:href => dashboard_feed_path(project, update)} - = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 - %span.update-title - = dashboard_feed_title(update) - %span.update-author - %strong= update.author_name - = time_ago_in_words(update.created_at) - ago - - noteable = update.target - - if noteable.kind_of?(MergeRequest) - .title-block - %span.update-title - %span.commit.tag - Merge Request # - = noteable.id - %span.update-author - %span= noteable.source_branch - → - %span= noteable.target_branch - - - elsif noteable.kind_of?(Issue) - .title-block - %span.update-title - %span.commit.tag - Issue # - = noteable.id - %span.update-author - .left= truncate noteable.title - - - elsif noteable.kind_of?(Commit) - .title-block - %span.update-title - %span.commit.tag - commit - %span.update-author - .left= truncate noteable.id - - else - .title-block - %span.update-title - %span.commit.tag - Project Wall - - -- elsif update.kind_of?(MergeRequest) - %a.project-update.titled{:href => project_merge_request_path(project, update)} - = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 - %span.update-title - Opened merge request - %span.update-author - %strong= update.author_name - = time_ago_in_words(update.created_at) - ago - .title-block - %span.update-title - %span.commit.tag - Merge Request # - = update.id - %span.update-author - %span= update.source_branch - → - %span= update.target_branch - -- elsif update.kind_of?(Issue) - %a.project-update.titled{:href => dashboard_feed_path(project, update)} - = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 - %span.update-title - Created new Issue - %span.update-author - %strong= update.author_name - = time_ago_in_words(update.created_at) - ago - .title-block - %span.update-title - %span.commit.tag - Issue # - = update.id - %span.update-author - .left= truncate update.title +- @activities.each do |update| + .wll + = link_to dashboard_feed_path(@project, update) do + - if update.kind_of? Note + %p + %strong + - if update.target + = update.target.class.name.titleize + = truncate update.target.id.to_s, :length => 10 + commented + - else + Project wall + – + = image_tag gravatar_icon(update.author_email), :class => "", :width => 16 + = truncate dashboard_feed_title(update), :length => 50 + - else + %p + %strong + = update.class.name.titleize + = truncate update.id.to_s + – + = image_tag gravatar_icon(update.author_email), :class => "", :width => 16 + = truncate dashboard_feed_title(update), :length => 50 diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 421e8409..6137aa5e 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -1,67 +1,60 @@ = form_for(@project, :remote => true) do |f| - %div.form_content - - unless @project.new_record? - %h2.icon - %span - = @project.name - .clear - - if @project.errors.any? - %ul.errors_holder + - if @project.errors.any? + .alert-message.block-message.error + %ul - @project.errors.full_messages.each do |msg| %li= msg - %table - %tr - %td= f.label :name - %td= f.text_field :name, :placeholder => "Example Project" - %tr - %td - .left= f.label :path - %cite.right= "git@#{GIT_HOST["host"]}:" - %td - = f.text_field :path, :placeholder => "example_project", :disabled => !@project.new_record? - %tr - %td - .left= f.label :code - %cite.right= "http://#{GIT_HOST["host"]}/" - %td= f.text_field :code, :placeholder => "example" + .clearfix + = f.label :name + .input= f.text_field :name, :placeholder => "Example Project" + .clearfix + = f.label :path do + Path + .input + .input-prepend + %span.add-on= "git@#{GIT_HOST["host"]}:" + = f.text_field :path, :placeholder => "example_project", :disabled => !@project.new_record? + .clearfix + = f.label :code do + Code + .input + .input-prepend + %span.add-on= "http://#{GIT_HOST["host"]}/" + = f.text_field :code, :placeholder => "example" - - unless @project.new_record? || @project.heads.empty? - %tr - %td= f.label :default_branch, "Default Branch" - %td= f.select(:default_branch, @project.heads.map(&:name), {}, :style => "width:300px;") + - unless @project.new_record? || @project.heads.empty? + .clearfix + = f.label :default_branch, "Default Branch" + .input= f.select(:default_branch, @project.heads.map(&:name), {}, :style => "width:210px;") - -#%tr - %td= f.label :tag_list - %td= f.text_area :tag_list, :placeholder => "project tags", :style => "height:50px", :id => :tag_field - %tr - %td= f.label :description - %td= f.text_area :description, :placeholder => "project description", :style => "height:50px" + .alert-message.block-message.warning + %h5 Features - %br - %div{ :class => "ajax_loader", :style => "display:none;height:200px;"} - %center - = image_tag "ajax-loader.gif", :class => "append-bottom" - - if @project.new_record? - %h3.prepend-top Creating project & repository. Please wait for few minutes - - else - %h3.prepend-top Updating project & repository. Please wait for few minutes + .clearfix + = f.label :issues_enabled, "Issues" + .input= f.check_box :issues_enabled + + .clearfix + = f.label :merge_requests_enabled, "Merge Requests" + .input= f.check_box :merge_requests_enabled + + .clearfix + = f.label :wall_enabled, "Wall" + .input= f.check_box :wall_enabled + + .clearfix + = f.label :wiki_enabled, "Wiki" + .input= f.check_box :wiki_enabled + + .clearfix + = f.label :description + .input= f.text_area :description, :placeholder => "project description", :class => "xlarge", :rows => 4 + + %br - .merge-tabs - = f.submit 'Save', :class => "grey-button" -   + .actions + = f.submit 'Save', :class => "btn primary" + = link_to 'Cancel', @project, :class => "btn" - unless @project.new_record? .right - = link_to 'Remove', @project, :confirm => 'Are you sure?', :method => :delete, :class => "red-button" - - -:javascript - $(function(){ - $('.new_project, .edit_project').bind('ajax:before', function() { - $(this).find(".form_content").hide(); - $('.ajax_loader').show(); - }); - - taggifyForm(); - - $('form #project_default_branch').chosen(); - }) + = link_to 'Remove', @project, :confirm => 'Are you sure?', :method => :delete, :class => "btn danger" diff --git a/app/views/projects/_project_head.html.haml b/app/views/projects/_project_head.html.haml index cbcd0660..ebf0748c 100644 --- a/app/views/projects/_project_head.html.haml +++ b/app/views/projects/_project_head.html.haml @@ -1,27 +1,28 @@ -.top-tabs - = link_to project_path(@project), :class => "activities-tab tab #{'active' if current_page?(project_path(@project)) }" do - %span - Activities - = link_to info_project_path(@project), :class => "stat-tab tab #{'active' if current_page?(info_project_path(@project)) || current_page?(edit_project_path(@project)) }" do - %span - Info - = link_to team_project_path(@project), :class => "team-tab tab #{'active' if current_page?(team_project_path(@project)) }" do - %span - Team - = link_to files_project_path(@project), :class => "files-tab tab #{'active' if current_page?(files_project_path(@project)) }" do - %span - Files - = link_to project_snippets_path(@project), :class => "snippets-tab tab #{'active' if current_page?(project_snippets_path(@project)) }" do - %span - Snippets +%ul.tabs + %li{ :class => "#{'active' if current_page?(project_path(@project)) }" } + = link_to project_path(@project), :class => "activities-tab tab" do + Show + - if can? current_user, :admin_project, @project + %li{ :class => "#{'active' if current_page?(edit_project_path(@project)) }" } + = link_to edit_project_path(@project), :class => "stat-tab tab " do + Edit + + %li{ :class => " #{'active' if (controller.controller_name == "team_members") || current_page?(team_project_path(@project)) }" } + = link_to team_project_path(@project), :class => "team-tab tab" do + Team + %li{ :class => "#{'active' if current_page?(files_project_path(@project)) }" } + = link_to files_project_path(@project), :class => "files-tab tab " do + Attachments + %li{ :class => " #{'active' if (controller.controller_name == "snippets") }" } + = link_to project_snippets_path(@project), :class => "snippets-tab tab" do + Snippets - - if current_page?(project_snippets_path(@project)) - - if can? current_user, :write_snippet, @project - = link_to new_project_snippet_path(@project), :class => "add_new", :title => "New Snippet" do - Add new - - - - if current_page?(team_project_path(@project)) - - if can? current_user, :admin_team_member, @project - = link_to new_project_team_member_path(@project), :class => "add_new", :title => "New Team Member" do - Add New + - if can? current_user, :admin_project, @project + %li{:class => "#{'active' if controller.controller_name == "hooks" }"} + = link_to project_hooks_path(@project) do + %span + Hooks + %li{:class => "#{'active' if controller.controller_name == "deploy_keys"}"} + = link_to project_deploy_keys_path(@project) do + %span + Deploy Keys diff --git a/app/views/projects/_team.html.haml b/app/views/projects/_team.html.haml index 3d033a85..876270a8 100644 --- a/app/views/projects/_team.html.haml +++ b/app/views/projects/_team.html.haml @@ -1,19 +1,10 @@ -%table.no-borders#team-table - %thead - %th Name - %th Project - %th Repository - - if can? current_user, :admin_team_member, @project - %th Actions +%ul.media-grid - @project.users_projects.each do |up| = render(:partial => 'team_members/show', :locals => {:member => up}) :javascript $(function(){ - $('#team-table .repo-access-select, #team-table .project-access-select').live("change", function() { + $('.repo-access-select, .project-access-select').live("change", function() { $(this.form).submit(); }); }) - - $('.delete-team-member').live('ajax:success', function() { - $(this).closest('tr').fadeOut(); }); diff --git a/app/views/projects/_tile.html.haml b/app/views/projects/_tile.html.haml index d9549045..e49aa076 100644 --- a/app/views/projects/_tile.html.haml +++ b/app/views/projects/_tile.html.haml @@ -1,20 +1,13 @@ - @projects.in_groups_of(3, false) do |projects| - - projects.each_with_index do |project, i| - %div.grid_1.projects_selector - %div{ :class => "project-box ui-box ui-box-big" } - = link_to project_path(project) do - %h3= truncate(project.name, :length => 20) + .row + - projects.each_with_index do |project, i| + %div.project_tile + .title + = link_to project_path(project) do + %h3= truncate(project.name, :length => 28) .data - %p.title.repository.git_url_wrapper - %span Repository: + %p %input{ :value => project.url_to_repo, :class => ['git-url', 'one_click_select', 'text', 'project_list_url'], :readonly => 'readonly' } - %p.title.activity - %span Last Activity: - - if project.last_activity_date_cached - = project.last_activity_date_cached.stamp("Aug 24, 2011") - - else - Never - .buttons - %a.browse-code.button.yellow{:href => tree_project_ref_path(project, project.root_ref)} Browse code - %a.commits.button.green{:href => project_commits_path(project)} Commits + %a.btn.info{:href => tree_project_ref_path(project, project.root_ref)} Browse code + %a.btn{:href => project_commits_path(project)} Commits diff --git a/app/views/projects/create.js.haml b/app/views/projects/create.js.haml index c457527a..2b3106c8 100644 --- a/app/views/projects/create.js.haml +++ b/app/views/projects/create.js.haml @@ -4,3 +4,4 @@ - else :plain $("#new_project").replaceWith("#{escape_javascript(render('form'))}"); + $('.ajax_loader').hide(); diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index 69e0f218..be8aae7d 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -1,69 +1,29 @@ = render "project_head" - -= form_for(@project, :remote => true) do |f| - %div - %span.entity-info - = link_to info_project_path(@project) do - .entity-button - Info - %i - %h2= @project.name - %hr - %table.no-borders - -if @project.errors.any? - %tr - %td{:colspan => 2} - #error_explanation - - @project.errors.full_messages.each do |msg| - %span= msg - %br - - %tr - %td= f.label :name - %td= f.text_field :name, :placeholder => "Example Project" - %tr - %td - .left= f.label :path - %cite.right= "git@#{GIT_HOST["host"]}:" - %td - = f.text_field :path, :placeholder => "example_project", :disabled => !@project.new_record? - %tr - %td - .left= f.label :code - %cite.right= "http://#{GIT_HOST["host"]}/" - %td= f.text_field :code, :placeholder => "example" - - - unless @project.new_record? || @project.heads.empty? - %tr - %td= f.label :default_branch, "Default Branch" - %td= f.select(:default_branch, @project.heads.map(&:name), {}, :style => "width:300px;") - - %tr - %td= f.label :description - %td= f.text_area :description, :placeholder => "project description", :style => "height:50px" - - %br - - .merge-tabs - = f.submit 'Save', :class => "grey-button" -   - - unless @project.new_record? - .right - = link_to 'Remove', @project, :confirm => 'Are you sure?', :method => :delete, :class => "red-button" - +%h3 Edit Project +%hr += render "projects/form" %div{ :class => "ajax_loader", :style => "display:none;height:200px;"} %center = image_tag "ajax-loader.gif", :class => "append-bottom" - %h3.prepend-top Updating project & repository. Please wait for few minutes - -:javascript - $('.edit_project').bind('ajax:before', function() { - $(".edit_project").hide(); - $('.ajax_loader').show(); - }); + %h3.prepend-top Saving project & repository. Please wait... :javascript $(function(){ - $('#project_default_branch').chosen(); - }) + $("#project_name").live("change", function(){ + var slug = slugify($(this).val()); + $("#project_code").val(slug); + $("#project_path").val(slug); + }); + }); + function slugify(text) { + return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase(); + } + + $(function(){ + $('.edit_project').live('ajax:before', function() { + $(this).hide(); + $('.ajax_loader').show(); + }); + $('form #project_default_branch').chosen(); + }) diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index f089c6ec..5088c2e7 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -1,20 +1,21 @@ - if current_user.require_ssh_key? - %ul.errors_holder - %li You have no ssh keys added yo tour profile. - %li You wont be able to pull/push repository. - %li Visit profile → keys and add public key of every machine you want to use for work with gitlabhq. + .alert-message.block-message.error + %ul + %li You have no ssh keys added to your profile. + %li You wont be able to pull/push repository. + %li Visit profile → keys and add public key of every machine you want to use for work with gitlabhq. - -%ul.alert_holder - %li You should push repository to proceed. - %li After push you will be able to browse code, commits etc. +.alert-message.block-message.error + %ul.alert_holder + %li You should push repository to proceed. + %li After push you will be able to browse code, commits etc. - bash_lexer = Pygments::Lexer[:bash] %div.git-empty %h3 Git global setup: - setup_str = ["git config --global user.name \"#{current_user.name}\"", "git config --global user.email \"#{current_user.email}\""].join("\n") - = raw bash_lexer.highlight(setup_str) + = raw bash_lexer.highlight(setup_str, :lexer => 'bash', :options => {:encoding => 'utf-8'}) %br %br diff --git a/app/views/projects/files.html.haml b/app/views/projects/files.html.haml index 8ea4ac8a..48ceece7 100644 --- a/app/views/projects/files.html.haml +++ b/app/views/projects/files.html.haml @@ -1,16 +1,17 @@ = render "project_head" - unless @notes.empty? - %div.update-data.ui-box.ui-box-small - .data - - @notes.each do |note| - %a.update-item{:href => note.attachment.url} - = image_tag gravatar_icon(note.author_email), :class => "left", :width => 16 - %span.update-title{:style => "margin-bottom:0px;"} + %table.zebra-striped.borders + - @notes.each do |note| + %tr + %td + %a{:href => note.attachment.url} + = image_tag gravatar_icon(note.author_email), :class => "left", :width => 16 +   = note.attachment_identifier - %span.update-author.right - Added - = time_ago_in_words(note.created_at) - ago + %td + Added + = time_ago_in_words(note.created_at) + ago - else .notice_holder %li All files attached to project wall, issues etc will be displayed here diff --git a/app/views/projects/graph.html.haml b/app/views/projects/graph.html.haml index 9dc973d7..394a11fd 100644 --- a/app/views/projects/graph.html.haml +++ b/app/views/projects/graph.html.haml @@ -1,8 +1,6 @@ -.top-tabs - = link_to graph_project_path(@project), :class => "tab #{'active' if current_page?(graph_project_path(@project)) }" do - %span - Network Graph -#holder.graph +%h3 Network Graph +%br +#holder.graph.well :javascript var chunk1={commits:#{@commits_json}}; diff --git a/app/views/projects/index.html.haml b/app/views/projects/index.html.haml index 8a4343b0..3838c339 100644 --- a/app/views/projects/index.html.haml +++ b/app/views/projects/index.html.haml @@ -1,29 +1,23 @@ -- content_for(:body_class, "projects-page") -.container_4 - .grid_4 - - if current_user.can_create_project? - %a.grey-button.right{:href => new_project_path} Create new project - %h2.icon - %span - Projects +%h3 + Projects + %small= "( #{current_user.projects.count} )" + - if current_user.can_create_project? + %span.right + = link_to new_project_path, :class => "btn small" do + New Project +%hr +- unless @projects.empty? + %div.content_list= render "tile" - %div.clear - - unless @projects.empty? - %div{:class => "tile"} - = render "tile" + -# If projects requris paging + -# We add ajax loader & init script + - if @projects.count == @limit + .loading{ :style => "display:none;"} + %center= image_tag "ajax-loader.gif" - -# If projects requris paging - -# We add ajax loader & init script - - if @projects.count == @limit - .clear - .loading{ :style => "display:none;"} - %center= image_tag "ajax-loader.gif" - - :javascript - $(function(){ - ProjectsList.init(16); - }); - - else - %center.prepend-top - %h2 - %cite Nothing here + :javascript + $(function(){ + Pager.init(#{@limit}); + }); +- else + %h2 Nothing here diff --git a/app/views/projects/index.js.haml b/app/views/projects/index.js.haml index 25da7cb4..15bbd973 100644 --- a/app/views/projects/index.js.haml +++ b/app/views/projects/index.js.haml @@ -1,2 +1,2 @@ :plain - ProjectsList.append(#{@projects.count}, "#{escape_javascript(render(:partial => 'projects/tile'))}"); + Pager.append(#{@projects.count}, "#{escape_javascript(render(:partial => 'projects/tile'))}"); diff --git a/app/views/projects/info.html.haml b/app/views/projects/info.html.haml deleted file mode 100644 index 787ad06d..00000000 --- a/app/views/projects/info.html.haml +++ /dev/null @@ -1,28 +0,0 @@ -= render "project_head" - -%div - %span.entity-info - = link_to edit_project_path(@project) do - .entity-button - Edit - %i - %h2= @project.name - %hr - -%table.no-borders - %tr - %td Name - %td= @project.name - - %tr - %td Slug - %td= @project.code - - %tr - %td Created - %td= @project.created_at.stamp("Aug 21, 2011") - - %tr - %td{:colspan => 2}= simple_format @project.description - - diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index 02ddc683..5883e7b8 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -1,17 +1,14 @@ -- content_for(:body_class, "new-project-page") -- content_for(:page_title) do - .new-project-hodler - .container - %h2.icon - %span - New Project - - %div.clear - = render 'form' +%h3 New Project +%hr += render 'form' +%div{ :class => "ajax_loader", :style => "display:none;height:200px;"} + %center + = image_tag "ajax-loader.gif", :class => "append-bottom" + %h3.prepend-top Creating project & repository. Please wait for few minutes :javascript $(function(){ - $("#project_name").change(function(){ + $("#project_name").live("change", function(){ var slug = slugify($(this).val()); $("#project_code").val(slug); $("#project_path").val(slug); @@ -21,3 +18,11 @@ function slugify(text) { return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase(); } + + $(function(){ + $('.new_project').live('ajax:before', function() { + $(this).hide(); + $('.ajax_loader').show(); + }); + $('form #project_default_branch').chosen(); + }) diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 2eb220b5..5fbed303 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,13 +1,22 @@ -- content_for(:body_class, "project-page dashboard") - = render "project_head" -#news-feed.news-feed - .project-box.project-updates - - @activities.each do |update| - = render "projects/feed", :update => update, :project => @project +%h3 + = @project.name + - if can? current_user, :download_code, @project + = link_to "Download", archive_project_repository_path(@project), :class => "btn small right" +.back_link + = link_to projects_path do + ← To projects list +%br +.alert-message.block-message.warning + .input + .input-prepend + %span.add-on git clone + = text_field_tag :project_clone, @project.url_to_repo, :class => "xlarge one_click_select git_clone_url" + += simple_format @project.description +- unless @activities.blank? + .ui-box + %h5.cgray Recent Activity + .content_list= render "feed" + -:javascript - function updateDashboard(){ - $('.project-content').load("#{escape_javascript(project_path(@project))} .project-content>*"); - } - setInterval("updateDashboard()", 300000); diff --git a/app/views/projects/team.html.haml b/app/views/projects/team.html.haml index 295e212f..7f2d6dcc 100644 --- a/app/views/projects/team.html.haml +++ b/app/views/projects/team.html.haml @@ -1,3 +1,12 @@ = render "project_head" + +- if can? current_user, :admin_team_member, @project + .alert-message.block-message + = link_to new_project_team_member_path(@project), :class => "btn small right", :title => "New Team Member" do + New Team Member + %p Read more about project permissions #{link_to "here", help_permissions_path, :class => "vlink"} + %p To open team member profile - click on avatar. + + = render :partial => "team", :locals => {:project => @project} diff --git a/app/views/projects/update.js.haml b/app/views/projects/update.js.haml index 70d8490e..de12527e 100644 --- a/app/views/projects/update.js.haml +++ b/app/views/projects/update.js.haml @@ -1,6 +1,7 @@ - if @project.valid? :plain - location.href = "#{info_project_path(@project, :notice => 'Project was successfully updated.')}"; + location.href = "#{edit_project_path(@project, :notice => 'Project was successfully updated.')}"; - else :plain $(".edit_project").replaceWith("#{escape_javascript(render('form'))}"); + $('.ajax_loader').hide(); diff --git a/app/views/projects/wall.html.haml b/app/views/projects/wall.html.haml index 4f0ec41e..bd538e8f 100644 --- a/app/views/projects/wall.html.haml +++ b/app/views/projects/wall.html.haml @@ -1,6 +1,2 @@ %div.wall_page - = render "notes/notes" - -.loading{ :style => "display:none;"} - %center= image_tag "ajax-loader.gif" - + = render "notes/notes", :tid => nil, :tt => "wall" diff --git a/app/views/projects/wall.js.haml b/app/views/projects/wall.js.haml deleted file mode 100644 index ee31c0b8..00000000 --- a/app/views/projects/wall.js.haml +++ /dev/null @@ -1 +0,0 @@ -= render "notes/load" diff --git a/app/views/protected_branches/index.html.haml b/app/views/protected_branches/index.html.haml new file mode 100644 index 00000000..de04cc08 --- /dev/null +++ b/app/views/protected_branches/index.html.haml @@ -0,0 +1,55 @@ += render "repositories/branches_head" + +.alert-message.block-message + %p Protected branches designed to prevent push for all except #{link_to "masters", help_permissions_path, :class => "vlink"}. + %p This ability allows: + %ul + %li keep stable branches secured + %li forced code review before merge to protected branches + %p Read more about project permissions #{link_to "here", help_permissions_path, :class => "vlink"} + + + +- unless @branches.empty? + %table.zebra-striped + %thead + %tr + %th Name + %th Last commit + %th + %tbody + - @branches.each do |branch| + %tr + %td + = link_to project_commits_path(@project, :ref => branch.name) do + %strong= branch.name + - if branch.name == @project.root_ref + %span.label default + %td + = link_to project_commits_path(@project, branch.commit.id) do + = truncate branch.commit.id.to_s, :length => 10 + = time_ago_in_words(branch.commit.committed_date) + ago + %td + - if can? current_user, :admin_project, @project + = link_to 'Unprotect', [@project, branch], :confirm => 'Are you sure?', :method => :delete, :class => "danger btn small" + + + +- if can? current_user, :admin_project, @project + = form_for [@project, @protected_branch] do |f| + -if @protected_branch.errors.any? + .alert-message.block-message.error + %ul + - @protected_branch.errors.full_messages.each do |msg| + %li= msg + + .clearfix + = f.label :name + .input= f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , { :include_blank => "Select branch" }, { :style => "width:300px" }) + .actions + = f.submit 'Add', :class => "primary btn" + + +:javascript + $('select#protected_branch_name').chosen(); diff --git a/app/views/refs/_submodule_item.html.haml b/app/views/refs/_submodule_item.html.haml new file mode 100644 index 00000000..6db49310 --- /dev/null +++ b/app/views/refs/_submodule_item.html.haml @@ -0,0 +1,13 @@ +- url = content.url(@ref) rescue nil +- name = content.basename +- return unless url +%tr{ :class => "tree-item", :url => url } + %td.tree-item-file-name + = image_tag "submodule.png" + %strong= truncate(name, :length => 40) + %td + %code= content.id[0..10] + %td + = link_to truncate(url, :length => 40), url + + diff --git a/app/views/refs/_tree.html.haml b/app/views/refs/_tree.html.haml index 0ab69574..e5908676 100644 --- a/app/views/refs/_tree.html.haml +++ b/app/views/refs/_tree.html.haml @@ -1,19 +1,19 @@ -#tree-breadcrumbs - %div +%ul.breadcrumb + %li + %span.arrow = link_to tree_project_ref_path(@project, @ref, :path => nil), :remote => true do - = @project.code - - tree.breadcrumbs(6) do |link| - \/ - = link -   - %span.tree_progress + = @project.name + - tree.breadcrumbs(6) do |link| + \/ + %li= link .clear +%div.tree_progress #tree-content-holder - if tree.is_blob? = render :partial => "refs/tree_file", :locals => { :name => tree.name, :content => tree.data, :file => tree } - else - contents = tree.contents - %table#tree-slider.no-borders + %table#tree-slider.bordered-table %thead %th Name %th Last Update @@ -33,6 +33,8 @@ = render :partial => "refs/tree_item", :locals => { :content => content } - contents.select{ |i| i.is_a?(Grit::Blob)}.each do |content| = render :partial => "refs/tree_item", :locals => { :content => content } + - contents.select{ |i| i.is_a?(Grit::Submodule)}.each do |content| + = render :partial => "refs/submodule_item", :locals => { :content => content } - if content = contents.select{ |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }.first #tree-readme-holder @@ -43,12 +45,20 @@ - else = simple_format(content.data) +- if params[:path] + - history_path = tree_file_project_ref_path(@project, @ref, params[:path]) +- else + - history_path = tree_project_ref_path(@project, @ref) :javascript $(function(){ $('select#branch').selectmenu({style:'popup', width:200}); $('select#tag').selectmenu({style:'popup', width:200}); + $('.project-refs-select').chosen(); + + history.pushState({ path: this.path }, '', "#{history_path}") }); + - if params[:path] && request.xhr? :javascript $(window).unbind('popstate'); diff --git a/app/views/refs/_tree_file.html.haml b/app/views/refs/_tree_file.html.haml index 8b9a45c8..78662229 100644 --- a/app/views/refs/_tree_file.html.haml +++ b/app/views/refs/_tree_file.html.haml @@ -1,13 +1,13 @@ :css .view_file .view_file_header - %strong - %span.file_icon= image_tag "txt.png" - %span.mode_text= file.mode - %span.file_name= name - = link_to "raw", blob_project_ref_path(@project, @ref, :path => params[:path] ), :class => "right", :target => "_blank" - = link_to "history", project_commits_path(@project, :path => params[:path], :ref => @ref ), :class => "right", :style => "margin-right:10px;" - %br/ + .row + .span1.file_icon= image_tag "txt.png" + .span2.mode_text= file.mode + .span7.file_name= name + .span4.right + = link_to "raw", blob_project_ref_path(@project, @ref, :path => params[:path] ), :class => "right", :target => "_blank" + = link_to "history", project_commits_path(@project, :path => params[:path], :ref => @ref ), :class => "right", :style => "margin-right:10px;" - if file.text? .view_file_content - unless file.empty? diff --git a/app/views/refs/_tree_item.html.haml b/app/views/refs/_tree_item.html.haml index 73385514..420307c7 100644 --- a/app/views/refs/_tree_item.html.haml +++ b/app/views/refs/_tree_item.html.haml @@ -14,5 +14,5 @@ %td.commit - tm = @project.team_member_by_name_or_email(content_commit.author_email, content_commit.author_name) - if tm - = link_to "[#{tm.user_name}]", project_team_member_path(@project, tm) - = link_to truncate(content_commit.safe_message, :length => tm ? 20 : 40), project_commit_path(@project, content_commit.id), :class => "tree-commit-link" + %strong= link_to "[#{tm.user_name}]", project_team_member_path(@project, tm) + = link_to truncate(content_commit.safe_message, :length => tm ? 30 : 50), project_commit_path(@project, content_commit.id), :class => "tree-commit-link" diff --git a/app/views/refs/tree.html.haml b/app/views/refs/tree.html.haml index 46eeb6f5..ece6f188 100644 --- a/app/views/refs/tree.html.haml +++ b/app/views/refs/tree.html.haml @@ -1,3 +1,13 @@ +%ul.tabs + %li + = form_tag switch_project_refs_path(@project), :method => :get, :class => "project-refs-form", :remote => true do + = select_tag "ref", grouped_options_refs, :onchange => "$(this.form).trigger('submit');", :class => "project-refs-select" + = hidden_field_tag :destination, "tree" + = hidden_field_tag :path, params[:path] + %li{:class => "#{'active' if (controller.controller_name == "refs") }"} + = link_to tree_project_ref_path(@project, @ref) do + Code + #tree-holder= render :partial => "tree", :locals => {:repo => @repo, :commit => @commit, :tree => @tree} :javascript diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml new file mode 100644 index 00000000..04f64fd5 --- /dev/null +++ b/app/views/repositories/_branch.html.haml @@ -0,0 +1,20 @@ +%tr + %td + = link_to project_commits_path(@project, :ref => branch.name) do + %strong= branch.name + - if branch.name == @project.root_ref + %span.label default + %td + = link_to project_commit_path(@project, branch.commit.id) do + %code= branch.commit.id.to_s[0..10] + + = image_tag gravatar_icon(Commit.new(branch.commit).author_email), :class => "", :width => 16 + = truncate(Commit.new(branch.commit).safe_message, :length => 40) + %td + %span.update-author.right + = time_ago_in_words(branch.commit.committed_date) + ago + %td + - if can? current_user, :download_code, @project + = link_to "Download", archive_project_repository_path(@project, :ref => branch.name), :class => "visible_link download_repo_link" + diff --git a/app/views/repositories/_branches_head.html.haml b/app/views/repositories/_branches_head.html.haml new file mode 100644 index 00000000..9a189498 --- /dev/null +++ b/app/views/repositories/_branches_head.html.haml @@ -0,0 +1,12 @@ += render "commits/head" +%ul.pills + %li{:class => ("active" if current_page?(project_repository_path(@project)))} + = link_to project_repository_path(@project) do + Recent + %li{:class => ("active" if current_page?(project_protected_branches_path(@project)))} + = link_to project_protected_branches_path(@project) do + Protected + %li{:class => ("active" if current_page?(branches_project_repository_path(@project)))} + = link_to branches_project_repository_path(@project) do + All +%hr diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml index f163b477..9fdba10b 100644 --- a/app/views/repositories/_feed.html.haml +++ b/app/views/repositories/_feed.html.haml @@ -1,15 +1,19 @@ -%a.project-update.titled{:href => project_commits_path(project, :ref => update.head.name)} - = image_tag gravatar_icon(update.author_email), :class => "left", :width => 40 - %span.update-title - = dashboard_feed_title(update) - %span.update-author - %strong= update.author_name - authored - = time_ago_in_words(update.created_at) - ago - .title-block - %span.update-title - %span.commit.tag= update.head.name - %span.update-author - .left= truncate update.commit.id +- commit = update +%tr + %td + = link_to project_commits_path(@project, :ref => commit.head.name) do + %strong + = commit.head.name + - if commit.head.name == @project.root_ref + %span.label default + %td + %div + = link_to project_commits_path(@project, commit.id) do + %code= commit.id.to_s[0..10] + = image_tag gravatar_icon(commit.author_email), :class => "", :width => 16 + = truncate(commit.safe_message, :length => 40) + %td + %span.right.cgray + = time_ago_in_words(commit.committed_date) + ago diff --git a/app/views/repositories/_head.html.haml b/app/views/repositories/_head.html.haml index 0095098e..bc96f306 100644 --- a/app/views/repositories/_head.html.haml +++ b/app/views/repositories/_head.html.haml @@ -1,28 +1 @@ -.top-tabs.repository - = link_to project_repository_path(@project), :class => "activities-tab tab #{'active' if current_page?(project_repository_path(@project)) }" do - %span - Activities - = link_to branches_project_repository_path(@project), :class => "tab #{'active' if current_page?(branches_project_repository_path(@project)) }" do - %span - Branches - = link_to tags_project_repository_path(@project), :class => "tab #{'active' if current_page?(tags_project_repository_path(@project)) }" do - %span - Tags - = link_to project_hooks_path, :class => "tab #{'active' if controller.controller_name == "hooks" }" do - %span - Hooks - - if can? current_user, :admin_project, @project - = link_to project_deploy_keys_path(@project), :class => "tab #{'active' if controller.controller_name == "deploy_keys"}" do - %span - Deploy Keys - - - if current_page?(project_hooks_path(@project)) - - if can? current_user, :admin_project, @project - = link_to new_project_hook_path(@project), :class => "add_new", :title => "New Web Hook" do - Add new - - - if current_page?(project_deploy_keys_path(@project)) - - if can? current_user, :admin_project, @project - = link_to new_project_deploy_key_path(@project), :class => "add_new", :title => "New Deploy Key" do - Add new - += render "projects/project_head" diff --git a/app/views/repositories/branches.html.haml b/app/views/repositories/branches.html.haml index befa88cc..c56b54d5 100644 --- a/app/views/repositories/branches.html.haml +++ b/app/views/repositories/branches.html.haml @@ -1,13 +1,6 @@ -= render "head" += render "repositories/branches_head" - unless @branches.empty? - %div.update-data.ui-box.ui-box-small - .data + %table.zebra-striped.borders + %tbody - @branches.each do |branch| - %a.update-item{:href => project_commits_path(@project, :ref => branch.name)} - %span.update-title{:style => "margin-bottom:0px;"} - = branch.name - %span.update-author.right - = time_ago_in_words(branch.commit.committed_date) - ago -- else - %h3 No brances + = render "repositories/branch", :branch => branch diff --git a/app/views/repositories/show.html.haml b/app/views/repositories/show.html.haml index 3c9208cb..43514551 100644 --- a/app/views/repositories/show.html.haml +++ b/app/views/repositories/show.html.haml @@ -1,8 +1,6 @@ -- content_for(:body_class, "project-page dashboard") -= render "head" += render "branches_head" -#news-feed.news-feed - .project-box.project-updates - - @activities.each do |update| - = render "repositories/feed", :update => update, :project => @project +%table.zebra-striped.borders + - @activities.each do |update| + = render "repositories/branch", :branch => update.head diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml index bff838fa..16113853 100644 --- a/app/views/repositories/tags.html.haml +++ b/app/views/repositories/tags.html.haml @@ -1,13 +1,23 @@ -= render "head" += render "commits/head" - unless @tags.empty? - %div.update-data.ui-box.ui-box-small - .data - - @tags.each do |tag| - %a.update-item{:href => project_commits_path(@project, :ref => tag.name)} - %span.update-title{:style => "margin-bottom:0px;"} - = tag.name - %span.update-author.right - = time_ago_in_words(tag.commit.committed_date) - ago + %table.zebra-striped.borders + - @tags.each do |tag| + %tr + %td + %strong= link_to tag.name, project_commits_path(@project, :ref => tag.name), :class => "" + %td + = link_to project_commits_path(@project, tag.commit.id) do + %code= tag.commit.id.to_s[0..10] + = image_tag gravatar_icon(Commit.new(tag.commit).author_email), :class => "", :width => 16 + = truncate(Commit.new(tag.commit).safe_message, :length => 40) + %td + %span.update-author.right + = time_ago_in_words(tag.commit.committed_date) + ago +   + %td + - if can? current_user, :download_code, @project + = link_to "Download", archive_project_repository_path(@project, :ref => tag.name), :class => "visible_link download_repo_link" + - else %h3 No tags diff --git a/app/views/snippets/_form.html.haml b/app/views/snippets/_form.html.haml index 63ba3512..a0a00556 100644 --- a/app/views/snippets/_form.html.haml +++ b/app/views/snippets/_form.html.haml @@ -1,48 +1,31 @@ +%h3= @snippet.new_record? ? "New Snippet" : "Edit Snippet ##{@snippet.id}" +%hr = form_for [@project, @snippet] do |f| - %div - %span.entity-info - - if @snippet.new_record? - = link_to project_snippets_path(@project) do - .entity-button - Snippets - %i - - else - = link_to project_snippet_path(@project, @snippet) do - .entity-button - Show Snippet - %i - %h2= @snippet.new_record? ? "New Snippet" : "Edit Snippet ##{@snippet.id}" - - %hr %table.no-borders -if @snippet.errors.any? - %tr - %td{:colspan => 2} - #error_explanation - - @snippet.errors.full_messages.each do |msg| - %span= msg - %br + .alert-message.block-message.error + %ul + - @snippet.errors.full_messages.each do |msg| + %li= msg - %tr - %td= f.label :title - %td= f.text_field :title, :placeholder => "Example Snippet" - %tr - %td= f.label :file_name - %td= f.text_field :file_name, :placeholder => "example.rb" - %tr - %td= f.label "Lifetime" - %td= f.select :expires_at, lifetime_select_options, {}, :style => "width:200px;" - %tr - %td{:colspan => 2} - = f.label :content, "Code" - %br - %br - = f.text_area :content + .clearfix + = f.label :title + .input= f.text_field :title, :placeholder => "Example Snippet" + .clearfix + = f.label :file_name + .input= f.text_field :file_name, :placeholder => "example.rb" + .clearfix + = f.label "Lifetime" + .input= f.select :expires_at, lifetime_select_options, {}, :style => "width:200px;" + .clearfix + = f.label :content, "Code" + = f.text_area :content, :class => "xxlarge" - .merge-tabs - = f.submit 'Save', :class => "positive-button" + .actions + = f.submit 'Save', :class => "primary btn" + = link_to "Cancel", project_snippets_path(@project), :class => " btn" - unless @snippet.new_record? - .right= link_to 'Destroy', [@project, @snippet], :confirm => 'Are you sure?', :method => :delete, :class => "red-button delete-snippet", :id => "destroy_snippet_#{@snippet.id}" + .right= link_to 'Destroy', [@project, @snippet], :confirm => 'Are you sure?', :method => :delete, :class => "btn right danger delete-snippet", :id => "destroy_snippet_#{@snippet.id}" diff --git a/app/views/snippets/_snippet.html.haml b/app/views/snippets/_snippet.html.haml index f8a48308..d6002362 100644 --- a/app/views/snippets/_snippet.html.haml +++ b/app/views/snippets/_snippet.html.haml @@ -1,12 +1,6 @@ -%a.update-item{:href => project_snippet_path(snippet.project, snippet)} - = image_tag gravatar_icon(snippet.author_email), :class => "left", :width => 40 - %span.update-title - = truncate(snippet.title, :length => 60) - %span.update-author - %strong= snippet.author_name - authored - = time_ago_in_words(snippet.created_at) - ago - .right - %span.tag.commit= snippet.file_name - +%tr + %td + %a{:href => project_snippet_path(snippet.project, snippet)} + = truncate(snippet.title, :length => 60) + %span.right.cgray + = snippet.file_name diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml index f81c0b8b..8afaf46e 100644 --- a/app/views/snippets/edit.html.haml +++ b/app/views/snippets/edit.html.haml @@ -1 +1,2 @@ += render "projects/project_head" = render "snippets/form" diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml index 1021dd1f..762265f1 100644 --- a/app/views/snippets/index.html.haml +++ b/app/views/snippets/index.html.haml @@ -1,12 +1,12 @@ = render "projects/project_head" +- if can? current_user, :write_snippet, @project + .alert-message.block-message + = link_to new_project_snippet_path(@project), :class => "btn small add_new right", :title => "New Snippet" do + Add new snippet + Share code pastes with others if it cant be in a git repository + %br + To add new snippet - click on button. + - unless @snippets.fresh.empty? - %div{ :class => "update-data ui-box ui-box-small ui-box-big" } - .data - = render @snippets.fresh -- else - .notice_holder - %li Snippets do not exist yet. - - if can? current_user, :write_snippet, @project - %li You can add a new one by clicking on "Add New" button - + %table.zebra-striped.borders= render @snippets.fresh diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml index f81c0b8b..8afaf46e 100644 --- a/app/views/snippets/new.html.haml +++ b/app/views/snippets/new.html.haml @@ -1 +1,2 @@ += render "projects/project_head" = render "snippets/form" diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml index 59f810a7..6e8ee762 100644 --- a/app/views/snippets/show.html.haml +++ b/app/views/snippets/show.html.haml @@ -1,20 +1,10 @@ -%div - %span.entity-info - - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user - = link_to edit_project_snippet_path(@project, @snippet) do - .entity-button - Edit Snippet - %i - - if @snippet.author_email - = image_tag gravatar_icon(@snippet.author_email), :class => "left", :width => 40, :style => "padding-right:5px;" - - else - = image_tag "no_avatar.png", :class => "left", :width => 40, :style => "padding-right:5px;" - %span.commit-title - %strong - = truncate(@snippet.title, :length => 60) - %span.commit-author - %strong= @snippet.author_name - = @snippet.created_at.stamp("Aug 21, 2011 9:23pm") += render "projects/project_head" + +%h3 + = @snippet.title + %small= @snippet.file_name + - if can?(current_user, :admin_snippet, @project) || @snippet.author == current_user + = link_to "Edit", edit_project_snippet_path(@project, @snippet), :class => "btn small right" %hr @@ -24,8 +14,5 @@ .data.no-padding :erb <%= raw @snippet.colorize %> -.clear -%br -.snippet_notes= render "notes/notes" -.clear += render "notes/notes", :tid => @snippet.id, :tt => "snippet" diff --git a/app/views/tags/index.html.haml b/app/views/tags/index.html.haml deleted file mode 100644 index b7f422ad..00000000 --- a/app/views/tags/index.html.haml +++ /dev/null @@ -1,10 +0,0 @@ -- content_for(:body_class, "projects-page") -- content_for(:page_title) do - .grid_4 - %h2 - Tags - - .tags-list - - @tags.all.each do |tag| - = link_to "#{tag.name}(#{tag.count})", tag_path(name) - diff --git a/app/views/team_members/_form.html.haml b/app/views/team_members/_form.html.haml index 2a299fd0..281776de 100644 --- a/app/views/team_members/_form.html.haml +++ b/app/views/team_members/_form.html.haml @@ -1,33 +1,33 @@ +%h3= "New Team member" +%hr = form_for @team_member, :as => :team_member, :url => project_team_members_path(@project, @team_member) do |f| - %div - %span.entity-info - - if request.xhr? - = link_to project_team_members_path(@project) do - .entity-button - Team List - %i - %h3= "New Team member" - - %hr -if @team_member.errors.any? - %ul.errors_holder - - @team_member.errors.full_messages.each do |msg| - %li= msg + .alert-message.block-message.error + %ul + - @team_member.errors.full_messages.each do |msg| + %li= msg - .span-6.append-bottom - %b Name - .span-6 - = f.select(:user_id, User.not_in_project(@project).all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }, { :style => "width:300px" }) - .span-6 - %b Project Access: - .span-6 - = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, :class => "project-access-select" + .clearfix + = f.label :user_id, "Name" + .input= f.select(:user_id, User.not_in_project(@project).all.collect {|p| [ p.name, p.id ] }, { :include_blank => "Select user" }, { :style => "width:300px" }) - .span-6 - %b Repository Access: - .span-6 - = f.select :repo_access, options_for_select(Repository.access_options, @team_member.repo_access), {}, :class => "repo-access-select" - %br - .merge-tabs - = f.submit 'Save', :class => "grey-button" + .clearfix + = f.label :project_access, "Project Access" + .input= f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, :class => "project-access-select" + + + .actions + = f.submit 'Save', :class => "btn primary" + = link_to "Cancel", team_project_path(@project), :class => "btn" + +:css + form select { + width:300px; + } + +:javascript + $('select#team_member_user_id').chosen(); + $('select#team_member_project_access').chosen(); + //$('select#team_member_repo_access').chosen(); + //$('select#team_member_project_access').chosen(); diff --git a/app/views/team_members/_show.html.haml b/app/views/team_members/_show.html.haml index b0e8f172..febdef1d 100644 --- a/app/views/team_members/_show.html.haml +++ b/app/views/team_members/_show.html.haml @@ -1,19 +1,16 @@ - user = member.user - allow_admin = can? current_user, :admin_project, @project -%tr{:id => dom_id(member)} - %td - = link_to image_tag(gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding:0 5px;"), project_team_member_path(@project, member) +%li{:id => dom_id(member), :class => "team_member_row"} + = link_to project_team_member_path(@project, member), :title => user.name do + = image_tag gravatar_icon(user.email, 60), :class => "thumbnail" + .row + .span8 + %h4 + = truncate(user.name, :lenght => 24) + %small= truncate user.email, :lenght => 24 - = link_to truncate(user.name, :lenght => 24), project_team_member_path(@project, member) - %br - .cgray{:style => "padding-top:10px;"}= truncate user.email, :lenght => 24 - %td + .span3 = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f| - = f.select :project_access, options_for_select(Project.access_options, member.project_access), {}, :class => "project-access-select", :disabled => !allow_admin - %td - = form_for(member, :as => :team_member, :url => project_team_member_path(@project, member)) do |f| - = f.select :repo_access, options_for_select(Repository.access_options, member.repo_access), {}, :class => "repo-access-select", :disabled => !allow_admin - - if allow_admin - %td - = link_to 'Cancel', project_team_member_path(:project_id => @project, :id => member.id), :confirm => 'Are you sure?', :method => :delete, :class => "grey-button negative delete-team-member", :remote => true - + = f.select :project_access, options_for_select(UsersProject.access_roles, member.project_access), {}, :class => "medium project-access-select", :disabled => !allow_admin + - if @project.owner == user + %span.label Project Owner diff --git a/app/views/team_members/create.js.haml b/app/views/team_members/create.js.haml index 2f1d6108..bfe8ca0d 100644 --- a/app/views/team_members/create.js.haml +++ b/app/views/team_members/create.js.haml @@ -1,13 +1,13 @@ - if @team_member.valid? :plain - $("#team_member_new").hide("slide", { direction: "right" }, 150, function(){ + $("#new_team_member").hide("slide", { direction: "right" }, 150, function(){ $("#team-table").show("slide", { direction: "left" }, 150, function() { - $("#team_member_new").remove(); + $("#new_team_member").remove(); $("#team-table").replaceWith("#{escape_javascript(render('projects/team'))}"); $(".add_new").show(); }); }); - else :plain - $("#team_member_new").replaceWith("#{escape_javascript(render('form'))}"); + $("#new_team_member").replaceWith("#{escape_javascript(render('form'))}"); $('select#team_member_user_id').chosen(); diff --git a/app/views/team_members/show.html.haml b/app/views/team_members/show.html.haml index 6293eee9..d05ef740 100644 --- a/app/views/team_members/show.html.haml +++ b/app/views/team_members/show.html.haml @@ -1,23 +1,19 @@ - allow_admin = can? current_user, :admin_project, @project - user = @team_member.user -%div - %span.entity-info - = link_to team_project_path(@project) do - .entity-button - Team - %i +.media-grid + = link_to "#" do + = image_tag gravatar_icon(user.email, 60), :class => "thumbnail", :width => 60 + %h3.media_h + = user.name + %br + %small= user.email - = image_tag gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding-right:5px;" - %span.commit-title - %strong - = user.name - %span.commit-author - %strong - = user.email - %hr - %br +.back_link + = link_to team_project_path(@project), :class => "" do + ← To team list -%table.no-borders +%br +%table.zebra-striped.borders %tr %td Name %td= user.name @@ -31,18 +27,14 @@ %td= @team_member.created_at.stamp("Aug 21, 2011") %tr - %td Project Access + %td + Project Access + (#{link_to "read more", help_permissions_path, :class => "vlink"}) + %td = form_for(@team_member, :as => :team_member, :url => project_team_member_path(@project, @team_member)) do |f| = f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, :class => "project-access-select", :disabled => !allow_admin - %tr - %td Repository Access - %td - = form_for(@team_member, :as => :team_member, :url => project_team_member_path(@project, @team_member)) do |f| - = f.select :repo_access, options_for_select(Repository.access_options, @team_member.repo_access), {}, :class => "repo-access-select", :disabled => !allow_admin - - - unless user.skype.empty? %tr %td Skype: @@ -59,9 +51,8 @@ %td= user.twitter - if can? current_user, :admin_project, @project - .merge-tabs - .right - = link_to 'Remove from team', [@project, @issue], :confirm => 'Are you sure?', :method => :delete, :class => "red-button" + .actions + = link_to 'Remove from team', project_team_member_path(:project_id => @project, :id => @team_member.id), :confirm => 'Are you sure?', :method => :delete, :class => "btn danger" :javascript $(function(){ diff --git a/app/views/widgets/_project_member.html.haml b/app/views/widgets/_project_member.html.haml new file mode 100644 index 00000000..131853fa --- /dev/null +++ b/app/views/widgets/_project_member.html.haml @@ -0,0 +1,54 @@ +- member = @project.team_member_by_id(current_user.id) +.widget + .media-grid + %li + = link_to project_team_member_path(@project, member), :title => current_user.name do + = image_tag gravatar_icon(current_user.email, 60), :class => "thumbnail", :width => 60 + %h4 + Hey, + #{truncate current_user.first_name, :lenght => 24}! + + %p + - if @project.issues_enabled + %span + Assigned Issues: + = current_user.assigned_issues.opened.count + %br + - if @project.merge_requests_enabled + %span + Assigned Requests: + = current_user.assigned_merge_requests.opened.count + %br + %br + - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project) + = link_to new_project_merge_request_path(@project), :title => "New Merge Request", :class => "btn small padded" do + Merge Request + - if @project.issues_enabled && can?(current_user, :write_issue, @project) + = link_to new_project_issue_path(@project), :title => "New Issue", :class => "btn small" do + Issue + + %hr + %p + Your access level in this project is + %code #{member.project_access_human} + %br + Visit member card for more information + + .link_holder + = link_to project_team_member_path(@project, member), :title => current_user.name do + = "Member Card »" + + + +-#- if can? current_user, :write_project, @project + .widget + - if @project.issues_enabled && @project.merge_requests_enabled + .span3 + %p You have access to create new issue or merge request. + %div + = link_to new_project_issue_path(@project), :title => "New Issue", :class => "" do + New Issue » + %div + = link_to new_project_merge_request_path(@project), :title => "New Merge Request", :class => "" do + New Merge Request » + diff --git a/app/views/widgets/_recent_projects.html.haml b/app/views/widgets/_recent_projects.html.haml new file mode 100644 index 00000000..7f1028bc --- /dev/null +++ b/app/views/widgets/_recent_projects.html.haml @@ -0,0 +1,11 @@ +- if current_user.projects.count > 0 + %div.widget + %h4 + Recent Projects: + %ul + - current_user.projects.order("id DESC").limit(5).each do |project| + %li + = link_to project_path(project) do + = project.name + .link_holder + = link_to "Projects » ", projects_path diff --git a/app/views/wikis/_form.html.haml b/app/views/wikis/_form.html.haml new file mode 100644 index 00000000..55191250 --- /dev/null +++ b/app/views/wikis/_form.html.haml @@ -0,0 +1,24 @@ += form_for [@project, @wiki] do |f| + -if @wiki.errors.any? + #error_explanation + %h2= "#{pluralize(@wiki.errors.count, "error")} prohibited this wiki from being saved:" + %ul + - @wiki.errors.full_messages.each do |msg| + %li= msg + + .alert-message.block-message.warning + %p + Wiki content is parsed with #{link_to "Markdown", "http://en.wikipedia.org/wiki/Markdown"}. + %br + To add link to new page you can just type + %code [Link Title](page-slug) + .clearfix + = f.label :title + .input= f.text_field :title, :class => :xxlarge + = f.hidden_field :slug + .clearfix + = f.label :content + .input= f.text_area :content, :class => :xxlarge + .actions + = f.submit 'Save', :class => "primary btn" + = link_to "Cancel", project_wiki_path(@project, :index), :class => "btn" diff --git a/app/views/wikis/edit.html.haml b/app/views/wikis/edit.html.haml new file mode 100644 index 00000000..26cbd52a --- /dev/null +++ b/app/views/wikis/edit.html.haml @@ -0,0 +1,3 @@ +%h3 Editing page +%hr += render 'form' diff --git a/app/views/wikis/history.html.haml b/app/views/wikis/history.html.haml new file mode 100644 index 00000000..ad5a50b8 --- /dev/null +++ b/app/views/wikis/history.html.haml @@ -0,0 +1,19 @@ +%h3 Versions +%table + %thead + %tr + %th # + %th last edit + %th created by + %tbody + - @wikis.each_with_index do |wiki_page, i| + %tr + %td= i + 1 + %td + = link_to wiki_page.created_at.to_s(:short), project_wiki_path(@project, wiki_page, :old_page_id => wiki_page.id) + ( + = time_ago_in_words(wiki_page.created_at) + ago + ) + %td= wiki_page.user.name + diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml new file mode 100644 index 00000000..696f6ec7 --- /dev/null +++ b/app/views/wikis/show.html.haml @@ -0,0 +1,16 @@ +%h3 + = @wiki.title + %span.right + - if can? current_user, :write_wiki, @project + = link_to history_project_wiki_path(@project, @wiki), :class => "btn small padded" do + History + = link_to edit_project_wiki_path(@project, @wiki), :class => "btn small" do + Edit +%hr + += markdown_to_html @wiki.content + +%p.time Last edited by #{@wiki.user.name}, in #{time_ago_in_words @wiki.created_at} +- if can? current_user, :admin_wiki, @project + = link_to project_wiki_path(@project, @wiki), :confirm => "Are you sure you want to delete this page?", :method => :delete do + Delete this page diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 922a66eb..d74f10a1 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -1,10 +1,14 @@ class PostReceive @queue = :post_receive - def self.perform(reponame, oldrev, newrev, ref) + def self.perform(reponame, oldrev, newrev, ref, author_key_id) project = Project.find_by_path(reponame) return false if project.nil? - project.execute_web_hooks(oldrev, newrev, ref) + # Ignore push from non-gitlab users + return false unless Key.find_by_identifier(author_key_id) + + project.observe_push(oldrev, newrev, ref, author_key_id) + project.execute_web_hooks(oldrev, newrev, ref, author_key_id) end end diff --git a/config/application.rb b/config/application.rb index bdd5bbf3..a3ef29c0 100644 --- a/config/application.rb +++ b/config/application.rb @@ -23,7 +23,7 @@ module Gitlab # config.plugins = [ :exception_notification, :ssl_requirement, :all ] # Activate observers that should always be running. - config.active_record.observers = :mailer_observer + config.active_record.observers = :mailer_observer, :activity_observer # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. diff --git a/config/database.yml b/config/database.yml.example similarity index 100% rename from config/database.yml rename to config/database.yml.example diff --git a/config/environments/development.rb b/config/environments/development.rb index 173bfc74..87b095e2 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -30,4 +30,11 @@ Gitlab::Application.configure do config.action_mailer.default_url_options = { :host => 'localhost:3000' } config.action_mailer.delivery_method = :letter_opener + + # Raise exception on mass assignment protection for Active Record models + config.active_record.mass_assignment_sanitizer = :strict + + # Log the query plan for queries taking more than this (works + # with SQLite, MySQL, and PostgreSQL) + config.active_record.auto_explain_threshold_in_seconds = 0.5 end diff --git a/config/gitlab.yml b/config/gitlab.yml.example similarity index 100% rename from config/gitlab.yml rename to config/gitlab.yml.example diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb new file mode 100644 index 00000000..9bb62f6d --- /dev/null +++ b/config/initializers/carrierwave.rb @@ -0,0 +1 @@ +CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/ diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 68bf5a0e..ae378b73 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -199,6 +199,15 @@ Devise.setup do |config| # up on your models and hooks. # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo' + #config.omniauth :ldap, + # :host => 'YOUR_LDAP_SERVER', + # :base => 'THE_BASE_WHERE_YOU_SEARCH_FOR_USERS', + # :uid => 'sAMAccountName', + # :port => 389, + # :method => :plain, + # :bind_dn => 'THE_FULL_DN_OF_THE_USER_YOU_WILL_BIND_WITH', + # :password => 'THE_PASSWORD_OF_THE_BIND_USER' + # ==> Warden configuration # If you want to use other strategies, that are not supported by Devise, or # change the failure app, you can configure them inside the config.warden block. diff --git a/config/initializers/gitlabhq/30_resque_queues.rb b/config/initializers/gitlabhq/30_resque_queues.rb new file mode 100644 index 00000000..5b0087ab --- /dev/null +++ b/config/initializers/gitlabhq/30_resque_queues.rb @@ -0,0 +1 @@ +Resque.watch_queue(PostReceive.instance_variable_get("@queue")) diff --git a/config/routes.rb b/config/routes.rb index b8149f8f..77c20380 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,22 +1,27 @@ Gitlab::Application.routes.draw do + # Optionally, enable Resque here require 'resque/server' mount Resque::Server.new, at: '/info/resque' - get 'tags'=> 'tags#index' - get 'tags/:tag' => 'projects#index' get 'help' => 'help#index' + get 'help/permissions' => 'help#permissions' + get 'help/workflow' => 'help#workflow' namespace :admin do - resources :users + resources :users do + member do + put :team_update + end + end resources :projects, :constraints => { :id => /[^\/]+/ } do member do get :team put :team_update end end - resources :team_members + resources :team_members, :only => [:edit, :update, :destroy] get 'emails', :to => 'mailer#preview' get 'mailer/preview_note' get 'mailer/preview_user_new' @@ -41,25 +46,32 @@ Gitlab::Application.routes.draw do resources :projects, :constraints => { :id => /[^\/]+/ }, :only => [:new, :create, :index] resources :keys - devise_for :users + devise_for :users, :controllers => { :omniauth_callbacks => :omniauth_callbacks } resources :projects, :constraints => { :id => /[^\/]+/ }, :except => [:new, :create, :index], :path => "/" do member do get "team" get "wall" get "graph" - get "info" get "files" end + resources :wikis, :only => [:show, :edit, :destroy, :create] do + member do + get "history" + end + end + resource :repository do member do get "branches" get "tags" + get "archive" end end resources :deploy_keys + resources :protected_branches, :only => [:index, :create, :destroy] resources :refs, :only => [], :path => "/" do collection do @@ -88,7 +100,6 @@ Gitlab::Application.routes.draw do resources :merge_requests do member do get :diffs - get :commits end end @@ -98,7 +109,11 @@ Gitlab::Application.routes.draw do get :test end end - resources :commits + resources :commits do + collection do + get :compare + end + end resources :team_members resources :issues do collection do @@ -106,7 +121,7 @@ Gitlab::Application.routes.draw do get :search end end - resources :notes, :only => [:create, :destroy] + resources :notes, :only => [:index, :create, :destroy] end root :to => "dashboard#index" end diff --git a/db/migrate/20120206170141_add_modularity_fields_to_project.rb b/db/migrate/20120206170141_add_modularity_fields_to_project.rb new file mode 100644 index 00000000..d63de0c2 --- /dev/null +++ b/db/migrate/20120206170141_add_modularity_fields_to_project.rb @@ -0,0 +1,7 @@ +class AddModularityFieldsToProject < ActiveRecord::Migration + def change + add_column :projects, :issues_enabled, :boolean, :null => false, :default => true + add_column :projects, :wall_enabled, :boolean, :null => false, :default => true + add_column :projects, :merge_requests_enabled, :boolean, :null => false, :default => true + end +end diff --git a/db/migrate/20120215182305_create_protected_branches.rb b/db/migrate/20120215182305_create_protected_branches.rb new file mode 100644 index 00000000..841d08c3 --- /dev/null +++ b/db/migrate/20120215182305_create_protected_branches.rb @@ -0,0 +1,10 @@ +class CreateProtectedBranches < ActiveRecord::Migration + def change + create_table :protected_branches do |t| + t.integer :project_id, :null => false + t.string :name, :null => false + + t.timestamps + end + end +end diff --git a/db/migrate/20120216085842_move_to_roles_permissions.rb b/db/migrate/20120216085842_move_to_roles_permissions.rb new file mode 100644 index 00000000..36d02cf9 --- /dev/null +++ b/db/migrate/20120216085842_move_to_roles_permissions.rb @@ -0,0 +1,22 @@ +class MoveToRolesPermissions < ActiveRecord::Migration + def up + repo_n = 0 + repo_r = 1 + repo_rw = 2 + project_rwa = 3 + + + # Build masters and reset repo_access + UsersProject.update_all({:project_access => UsersProject::MASTER, :repo_access => 99 }, ["project_access = ?", project_rwa]) + + # Build other roles based on repo access + UsersProject.update_all ["project_access = ?", UsersProject::DEVELOPER], ["repo_access = ?", repo_rw] + UsersProject.update_all ["project_access = ?", UsersProject::REPORTER], ["repo_access = ?", repo_r] + UsersProject.update_all ["project_access = ?", UsersProject::GUEST], ["repo_access = ?", repo_n] + + remove_column :users_projects, :repo_access + end + + def down + end +end diff --git a/db/migrate/20120216215008_create_wikis.rb b/db/migrate/20120216215008_create_wikis.rb new file mode 100644 index 00000000..38947df3 --- /dev/null +++ b/db/migrate/20120216215008_create_wikis.rb @@ -0,0 +1,11 @@ +class CreateWikis < ActiveRecord::Migration + def change + create_table :wikis do |t| + t.string :title + t.text :content + t.integer :project_id + + t.timestamps + end + end +end diff --git a/db/migrate/20120219130957_add_slug_to_wiki.rb b/db/migrate/20120219130957_add_slug_to_wiki.rb new file mode 100644 index 00000000..5f2d5970 --- /dev/null +++ b/db/migrate/20120219130957_add_slug_to_wiki.rb @@ -0,0 +1,6 @@ +class AddSlugToWiki < ActiveRecord::Migration + def change + add_column :wikis, :slug, :string + + end +end diff --git a/db/migrate/20120219140810_add_wiki_enabled_to_project.rb b/db/migrate/20120219140810_add_wiki_enabled_to_project.rb new file mode 100644 index 00000000..ebd71bea --- /dev/null +++ b/db/migrate/20120219140810_add_wiki_enabled_to_project.rb @@ -0,0 +1,6 @@ +class AddWikiEnabledToProject < ActiveRecord::Migration + def change + add_column :projects, :wiki_enabled, :boolean, :default => true, :null => false + + end +end diff --git a/db/migrate/20120219193300_add_user_to_wiki.rb b/db/migrate/20120219193300_add_user_to_wiki.rb new file mode 100644 index 00000000..8a6c0a06 --- /dev/null +++ b/db/migrate/20120219193300_add_user_to_wiki.rb @@ -0,0 +1,6 @@ +class AddUserToWiki < ActiveRecord::Migration + def change + add_column :wikis, :user_id, :integer + + end +end diff --git a/db/migrate/20120228130210_create_events.rb b/db/migrate/20120228130210_create_events.rb new file mode 100644 index 00000000..c01f557a --- /dev/null +++ b/db/migrate/20120228130210_create_events.rb @@ -0,0 +1,14 @@ +class CreateEvents < ActiveRecord::Migration + def change + create_table :events do |t| + t.string :target_type, :null => true + t.integer :target_id, :null => true + + t.string :title, :null => true + t.text :data, :null => true + t.integer :project_id, :null => true + + t.timestamps + end + end +end diff --git a/db/migrate/20120228134252_add_action_to_event.rb b/db/migrate/20120228134252_add_action_to_event.rb new file mode 100644 index 00000000..aade3d90 --- /dev/null +++ b/db/migrate/20120228134252_add_action_to_event.rb @@ -0,0 +1,5 @@ +class AddActionToEvent < ActiveRecord::Migration + def change + add_column :events, :action, :integer, :null => true + end +end diff --git a/db/schema.rb b/db/schema.rb index 3e7866f3..a0baf8e2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,18 +11,17 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120121122616) do +ActiveRecord::Schema.define(:version => 20120228134252) do - create_table "features", :force => true do |t| - t.string "name" - t.string "branch_name" - t.integer "assignee_id" - t.integer "author_id" + create_table "events", :force => true do |t| + t.string "target_type" + t.integer "target_id" + t.string "title" + t.text "data" t.integer "project_id" - t.datetime "created_at" - t.datetime "updated_at" - t.string "version" - t.integer "status", :default => 0, :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.integer "action" end create_table "issues", :force => true do |t| @@ -85,10 +84,21 @@ ActiveRecord::Schema.define(:version => 20120121122616) do t.text "description" t.datetime "created_at" t.datetime "updated_at" - t.boolean "private_flag", :default => true, :null => false + t.boolean "private_flag", :default => true, :null => false t.string "code" t.integer "owner_id" - t.string "default_branch", :default => "master", :null => false + t.string "default_branch", :default => "master", :null => false + t.boolean "issues_enabled", :default => true, :null => false + t.boolean "wall_enabled", :default => true, :null => false + t.boolean "merge_requests_enabled", :default => true, :null => false + t.boolean "wiki_enabled", :default => true, :null => false + end + + create_table "protected_branches", :force => true do |t| + t.integer "project_id", :null => false + t.string "name", :null => false + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "snippets", :force => true do |t| @@ -150,7 +160,6 @@ ActiveRecord::Schema.define(:version => 20120121122616) do t.integer "project_id", :null => false t.datetime "created_at" t.datetime "updated_at" - t.integer "repo_access", :default => 0, :null => false t.integer "project_access", :default => 0, :null => false end @@ -161,4 +170,14 @@ ActiveRecord::Schema.define(:version => 20120121122616) do t.datetime "updated_at" end + create_table "wikis", :force => true do |t| + t.string "title" + t.text "content" + t.integer "project_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "slug" + t.integer "user_id" + end + end diff --git a/lib/gitlabhq/gitolite.rb b/lib/gitlabhq/gitolite.rb index e6eb8e51..4f911113 100644 --- a/lib/gitlabhq/gitolite.rb +++ b/lib/gitlabhq/gitolite.rb @@ -64,21 +64,9 @@ module Gitlabhq def update_project(repo_name, project) ga_repo = ::Gitolite::GitoliteAdmin.new(File.join(@local_dir,'gitolite')) conf = ga_repo.config - - repo = if conf.has_repo?(repo_name) - conf.get_repo(repo_name) - else - ::Gitolite::Config::Repo.new(repo_name) - end - - name_readers = project.repository_readers - name_writers = project.repository_writers - - repo.clean_permissions - repo.add_permission("R", "", name_readers) unless name_readers.blank? - repo.add_permission("RW+", "", name_writers) unless name_writers.blank? + repo = update_project_config(project, conf) conf.add_repo(repo, true) - + ga_repo.save end @@ -89,25 +77,43 @@ module Gitlabhq conf = ga_repo.config projects.each do |project| - repo_name = project.path - - repo = if conf.has_repo?(repo_name) - conf.get_repo(repo_name) - else - ::Gitolite::Config::Repo.new(repo_name) - end - - name_readers = project.repository_readers - name_writers = project.repository_writers - - repo.clean_permissions - repo.add_permission("R", "", name_readers) unless name_readers.blank? - repo.add_permission("RW+", "", name_writers) unless name_writers.blank? + repo = update_project_config(project, conf) conf.add_repo(repo, true) end ga_repo.save end + def update_project_config(project, conf) + repo_name = project.path + + repo = if conf.has_repo?(repo_name) + conf.get_repo(repo_name) + else + ::Gitolite::Config::Repo.new(repo_name) + end + + name_readers = project.repository_readers + name_writers = project.repository_writers + name_masters = project.repository_masters + + pr_br = project.protected_branches.map(&:name).join(" ") + + repo.clean_permissions + + # Deny access to protected branches for writers + unless name_writers.blank? || pr_br.blank? + repo.add_permission("-", pr_br, name_writers) + end + + # Add read permissions + repo.add_permission("R", "", name_readers) unless name_readers.blank? + + # Add write permissions + repo.add_permission("RW+", "", name_writers) unless name_writers.blank? + repo.add_permission("RW+", "", name_masters) unless name_masters.blank? + + repo + end end end diff --git a/lib/post-receive-hook b/lib/post-receive-hook index d7354d65..93eb96c2 100755 --- a/lib/post-receive-hook +++ b/lib/post-receive-hook @@ -8,5 +8,5 @@ do # For every branch or tag that was pushed, create a Resque job in redis. pwd=`pwd` reponame=`basename "$pwd" | cut -d. -f1` - env -i redis-cli rpush "resque:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$reponame\",\"$oldrev\",\"$newrev\",\"$ref\"]}" > /dev/null 2>&1 + env -i redis-cli rpush "resque:queue:post_receive" "{\"class\":\"PostReceive\",\"args\":[\"$reponame\",\"$oldrev\",\"$newrev\",\"$ref\",\"$GL_USER\"]}" > /dev/null 2>&1 done diff --git a/lib/tasks/update_hooks.rake b/lib/tasks/update_hooks.rake new file mode 100644 index 00000000..472023c8 --- /dev/null +++ b/lib/tasks/update_hooks.rake @@ -0,0 +1,15 @@ +desc "Rewrite hooks for repos" +task :update_hooks => :environment do + puts "Starting Projects" + Project.find_each(:batch_size => 100) do |project| + begin + if project.commit + project.repository.write_hooks + print ".".green + end + rescue Exception => e + print e.message.red + end + end + puts "\nDone with projects" +end diff --git a/lib/utils.rb b/lib/utils.rb index 677322c9..82463f9e 100644 --- a/lib/utils.rb +++ b/lib/utils.rb @@ -34,6 +34,10 @@ module Utils :c when /(\.cpp|\.hpp|\.c++|\.h++|\.cc|\.hh|\.cxx|\.hxx)$/ :cpp + when /(\.d|\.di)$/ + :d + when /(\.hs|\.lhs)$/ + :haskell when /(\.rb|\.ru|\.rake|Rakefile|\.gemspec|\.rbx|Gemfile)$/ :ruby when /(\.py|\.pyw|\.sc|SConstruct|SConscript|\.tac)$/ diff --git a/public/404.html b/public/404.html index 16d8fcbc..33325890 100644 --- a/public/404.html +++ b/public/404.html @@ -2,22 +2,12 @@ The page you were looking for doesn't exist (404) - + - -
-

404

+

404

+

The page you were looking for doesn't exist.

You may have mistyped the address or the page may have moved.

diff --git a/public/422.html b/public/422.html index 24532664..8b19ea89 100644 --- a/public/422.html +++ b/public/422.html @@ -2,22 +2,13 @@ The change you wanted was rejected (422) - + -
-

422

+

422

+

The change you wanted was rejected.

Maybe you tried to change something you didn't have access to.

diff --git a/public/500.html b/public/500.html index b1d54464..36e14b80 100644 --- a/public/500.html +++ b/public/500.html @@ -2,22 +2,13 @@ We're sorry, but something went wrong (500) - + -
-

500

+

500

+

We're sorry, but something went wrong.

We've been notified about this issue and we'll take a look at it shortly.

diff --git a/public/static.css b/public/static.css new file mode 100644 index 00000000..6090d7b2 --- /dev/null +++ b/public/static.css @@ -0,0 +1,57 @@ +body { color: #666; text-align: center; font-family: arial, sans-serif; margin:0; padding:0; } +h1 { font-size: 48px; color: #444; line-height: 1.5em; } +h2 { font-size: 24px; color: #666; line-height: 1.5em; } + +.alert-message { + position: relative; + padding: 7px 15px; + margin-bottom: 18px; + color: #404040; + background-color: #eedc94; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94)); + background-image: -moz-linear-gradient(top, #fceec1, #eedc94); + background-image: -ms-linear-gradient(top, #fceec1, #eedc94); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94)); + background-image: -webkit-linear-gradient(top, #fceec1, #eedc94); + background-image: -o-linear-gradient(top, #fceec1, #eedc94); + background-image: linear-gradient(top, #fceec1, #eedc94); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFCEEC1', endColorstr='#FFEEDC94', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #eedc94 #eedc94 #e4c652; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) fadein(rgba(0, 0, 0, 0.1), 15%); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + border-width: 1px; + border-style: solid; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); +} +.alert-message .close { + margin-top: 1px; + *margin-top: 0; +} +.alert-message a { + font-weight: bold; + color: #404040; +} +.alert-message.danger p a, .alert-message.error p a, .alert-message.success p a, .alert-message.info p a { + color: #404040; +} +.alert-message h5 { + line-height: 18px; +} +.alert-message p { + margin-bottom: 0; +} +.alert-message div { + margin-top: 5px; + margin-bottom: 2px; + line-height: 28px; +} + +.alert-message.block-message.error { + background: #FDDFDE; + border-color: #FBC7C6; +} + diff --git a/resque.sh b/resque.sh index 7c9850d0..84a1066f 100755 --- a/resque.sh +++ b/resque.sh @@ -1,2 +1,2 @@ mkdir tmp/pids -nohup bundle exec rake environment resque:work QUEUE=* VVERBOSE=1 RAILS_ENV=production PIDFILE=tmp/pids/resque_worker_QUEUE.pid & >> log/resque_worker_QUEUE.log 2>&1 +nohup bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production PIDFILE=tmp/pids/resque_worker_QUEUE.pid & >> log/resque_worker_QUEUE.log 2>&1 diff --git a/resque_dev.sh b/resque_dev.sh new file mode 100755 index 00000000..9df4dc1d --- /dev/null +++ b/resque_dev.sh @@ -0,0 +1 @@ +bundle exec rake environment resque:work QUEUE=* VVERBOSE=1 diff --git a/spec/factories.rb b/spec/factories.rb index 15e54ed2..2ca8d764 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -32,10 +32,14 @@ end Factory.add(:issue, Issue) do |obj| obj.title = Faker::Lorem.sentence + obj.author = Factory :user + obj.assignee = Factory :user end Factory.add(:merge_request, MergeRequest) do |obj| obj.title = Faker::Lorem.sentence + obj.author = Factory :user + obj.assignee = Factory :user obj.source_branch = "master" obj.target_branch = "master" obj.closed = false @@ -59,3 +63,13 @@ end Factory.add(:web_hook, WebHook) do |obj| obj.url = Faker::Internet.url end + +Factory.add(:wikis, WebHook) do |obj| + obj.title = Faker::Lorem.sentence + obj.content = Faker::Lorem.sentence +end + +Factory.add(:event, Event) do |obj| + obj.title = Faker::Lorem.sentence + obj.project = Factory(:project) +end diff --git a/spec/models/activity_observer_spec.rb b/spec/models/activity_observer_spec.rb new file mode 100644 index 00000000..9cd0dfb6 --- /dev/null +++ b/spec/models/activity_observer_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe ActivityObserver do + let(:project) { Factory :project } + + def self.it_should_be_valid_event + it { @event.should_not be_nil } + it { @event.project.should == project } + end + + describe "Merge Request created" do + before do + @merge_request = Factory :merge_request, :project => project + @event = Event.last + end + + it_should_be_valid_event + it { @event.action.should == Event::Created } + it { @event.target.should == @merge_request } + end + + describe "Issue created" do + before do + @issue = Factory :issue, :project => project + @event = Event.last + end + + it_should_be_valid_event + it { @event.action.should == Event::Created } + it { @event.target.should == @issue } + end + + describe "Issue commented" do + before do + @issue = Factory :issue, :project => project + @note = Factory :note, :noteable => @issue, :project => project + @event = Event.last + end + + it_should_be_valid_event + it { @event.action.should == Event::Commented } + it { @event.target.should == @note } + end +end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb new file mode 100644 index 00000000..50266fcf --- /dev/null +++ b/spec/models/event_spec.rb @@ -0,0 +1,32 @@ +# == Schema Information +# +# Table name: events +# +# id :integer not null, primary key +# target_type :string(255) +# target_id :integer +# title :string(255) +# data :text +# project_id :integer +# created_at :datetime not null +# updated_at :datetime not null +# action :integer +# + +require 'spec_helper' + +describe Event do + describe "Associations" do + it { should belong_to(:project) } + end + + describe "Creation" do + before do + @event = Factory :event + end + + it "should create a valid event" do + @event.should be_valid + end + end +end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 75503fd9..70eba5cc 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -42,27 +42,13 @@ describe Note do :project => project, :noteable_id => commit.id, :noteable_type => "Commit", - :line_code => "OLD_1_23" + :line_code => "0_16_1" end it "should save a valid note" do @note.noteable_id.should == commit.id @note.target.id.should == commit.id end - - it { @note.line_type_id.should == "OLD" } - it { @note.line_file_id.should == 1 } - it { @note.line_number.should == 23 } - - it { @note.for_line?(1, 23, 34).should be_true } - it { @note.for_line?(1, 23, nil).should be_true } - it { @note.for_line?(1, 23, 0).should be_true } - it { @note.for_line?(1, 23, 23).should be_true } - - it { @note.for_line?(1, nil, 34).should be_false } - it { @note.for_line?(1, 24, nil).should be_false } - it { @note.for_line?(1, 24, 0).should be_false } - it { @note.for_line?(1, 24, 23).should be_false } end describe :authorization do @@ -78,9 +64,8 @@ describe Note do describe :read do before do - @p1.users_projects.create(:user => @u1, :project_access => Project::PROJECT_N) - @p1.users_projects.create(:user => @u2, :project_access => Project::PROJECT_R) - @p2.users_projects.create(:user => @u3, :project_access => Project::PROJECT_R) + @p1.users_projects.create(:user => @u2, :project_access => UsersProject::GUEST) + @p2.users_projects.create(:user => @u3, :project_access => UsersProject::GUEST) end it { @abilities.allowed?(@u1, :read_note, @p1).should be_false } @@ -90,9 +75,8 @@ describe Note do describe :write do before do - @p1.users_projects.create(:user => @u1, :project_access => Project::PROJECT_R) - @p1.users_projects.create(:user => @u2, :project_access => Project::PROJECT_RW) - @p2.users_projects.create(:user => @u3, :project_access => Project::PROJECT_RW) + @p1.users_projects.create(:user => @u2, :project_access => UsersProject::DEVELOPER) + @p2.users_projects.create(:user => @u3, :project_access => UsersProject::DEVELOPER) end it { @abilities.allowed?(@u1, :write_note, @p1).should be_false } @@ -102,9 +86,9 @@ describe Note do describe :admin do before do - @p1.users_projects.create(:user => @u1, :project_access => Project::PROJECT_R) - @p1.users_projects.create(:user => @u2, :project_access => Project::PROJECT_RWA) - @p2.users_projects.create(:user => @u3, :project_access => Project::PROJECT_RWA) + @p1.users_projects.create(:user => @u1, :project_access => UsersProject::REPORTER) + @p1.users_projects.create(:user => @u2, :project_access => UsersProject::MASTER) + @p2.users_projects.create(:user => @u3, :project_access => UsersProject::MASTER) end it { @abilities.allowed?(@u1, :admin_note, @p1).should be_false } diff --git a/spec/models/project_hooks_spec.rb b/spec/models/project_hooks_spec.rb new file mode 100644 index 00000000..5a03b01f --- /dev/null +++ b/spec/models/project_hooks_spec.rb @@ -0,0 +1,121 @@ +require 'spec_helper' + +describe Project, "Hooks" do + let(:project) { Factory :project } + before do + @key = Factory :key, :user => project.owner + @key_id = @key.identifier + end + + describe "Post Receive Event" do + it "should create push event" do + oldrev, newrev, ref = '00000000000000000000000000000000', 'newrev', 'refs/heads/master' + project.observe_push(oldrev, newrev, ref, @key_id) + event = Event.last + + event.should_not be_nil + event.project.should == project + event.action.should == Event::Pushed + event.data == project.web_hook_data(oldrev, newrev, ref, @key_id) + end + end + + describe "Web hooks" do + context "with no web hooks" do + it "raises no errors" do + lambda { + project.execute_web_hooks('oldrev', 'newrev', 'ref', @key_id) + }.should_not raise_error + end + end + + context "with web hooks" do + before do + @webhook = Factory(:web_hook) + @webhook_2 = Factory(:web_hook) + project.web_hooks << [@webhook, @webhook_2] + end + + it "executes multiple web hook" do + @webhook.should_receive(:execute).once + @webhook_2.should_receive(:execute).once + + project.execute_web_hooks('oldrev', 'newrev', 'refs/heads/master', @key_id) + end + end + + context "does not execute web hooks" do + before do + @webhook = Factory(:web_hook) + project.web_hooks << [@webhook] + end + + it "when pushing a branch for the first time" do + @webhook.should_not_receive(:execute) + project.execute_web_hooks('00000000000000000000000000000000', 'newrev', 'refs/heads/master', @key_id) + end + + it "when pushing tags" do + @webhook.should_not_receive(:execute) + project.execute_web_hooks('oldrev', 'newrev', 'refs/tags/v1.0.0', @key_id) + end + end + + context "when pushing new branches" do + + end + + context "when gathering commit data" do + before do + @oldrev, @newrev, @ref = project.fresh_commits(2).last.sha, project.fresh_commits(2).first.sha, 'refs/heads/master' + @commit = project.fresh_commits(2).first + + # Fill nil/empty attributes + project.description = "This is a description" + + @data = project.web_hook_data(@oldrev, @newrev, @ref, @key_id) + end + + subject { @data } + + it { should include(before: @oldrev) } + it { should include(after: @newrev) } + it { should include(ref: @ref) } + it { should include(user_id: project.owner.id) } + it { should include(user_name: project.owner.name) } + + context "with repository data" do + subject { @data[:repository] } + + it { should include(name: project.name) } + it { should include(url: project.web_url) } + it { should include(description: project.description) } + it { should include(homepage: project.web_url) } + it { should include(private: project.private?) } + end + + context "with commits" do + subject { @data[:commits] } + + it { should be_an(Array) } + it { should have(1).element } + + context "the commit" do + subject { @data[:commits].first } + + it { should include(id: @commit.id) } + it { should include(message: @commit.safe_message) } + it { should include(timestamp: @commit.date.xmlschema) } + it { should include(url: "http://localhost/#{project.code}/commits/#{@commit.id}") } + + context "with a author" do + subject { @data[:commits].first[:author] } + + it { should include(name: @commit.author_name) } + it { should include(email: @commit.author_email) } + end + end + end + end + end +end diff --git a/spec/models/project_security_spec.rb b/spec/models/project_security_spec.rb index 1899e8aa..bd697af9 100644 --- a/spec/models/project_security_spec.rb +++ b/spec/models/project_security_spec.rb @@ -12,8 +12,7 @@ describe Project do describe "read access" do before do - @p1.users_projects.create(:project => @p1, :user => @u1, :project_access => Project::PROJECT_N) - @p1.users_projects.create(:project => @p1, :user => @u2, :project_access => Project::PROJECT_R) + @p1.users_projects.create(:project => @p1, :user => @u2, :project_access => UsersProject::REPORTER) end it { @abilities.allowed?(@u1, :read_project, @p1).should be_false } @@ -22,8 +21,7 @@ describe Project do describe "write access" do before do - @p1.users_projects.create(:project => @p1, :user => @u1, :project_access => Project::PROJECT_R) - @p1.users_projects.create(:project => @p1, :user => @u2, :project_access => Project::PROJECT_RW) + @p1.users_projects.create(:project => @p1, :user => @u2, :project_access => UsersProject::DEVELOPER) end it { @abilities.allowed?(@u1, :write_project, @p1).should be_false } @@ -32,8 +30,8 @@ describe Project do describe "admin access" do before do - @p1.users_projects.create(:project => @p1, :user => @u1, :project_access => Project::PROJECT_RW) - @p1.users_projects.create(:project => @p1, :user => @u2, :project_access => Project::PROJECT_RWA) + @p1.users_projects.create(:project => @p1, :user => @u1, :project_access => UsersProject::DEVELOPER) + @p1.users_projects.create(:project => @p1, :user => @u2, :project_access => UsersProject::MASTER) end it { @abilities.allowed?(@u1, :admin_project, @p1).should be_false } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 68bc82de..f53b833f 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe Project do describe "Associations" do + it { should have_many(:events) } it { should have_many(:users) } it { should have_many(:users_projects) } it { should have_many(:issues) } @@ -69,106 +70,6 @@ describe Project do end end - describe "web hooks" do - let(:project) { Factory :project } - - context "with no web hooks" do - it "raises no errors" do - lambda { - project.execute_web_hooks('oldrev', 'newrev', 'ref') - }.should_not raise_error - end - end - - context "with web hooks" do - before do - @webhook = Factory(:web_hook) - @webhook_2 = Factory(:web_hook) - project.web_hooks << [@webhook, @webhook_2] - end - - it "executes multiple web hook" do - @webhook.should_receive(:execute).once - @webhook_2.should_receive(:execute).once - - project.execute_web_hooks('oldrev', 'newrev', 'refs/heads/master') - end - end - - context "does not execute web hooks" do - before do - @webhook = Factory(:web_hook) - project.web_hooks << [@webhook] - end - - it "when pushing a branch for the first time" do - @webhook.should_not_receive(:execute) - project.execute_web_hooks('00000000000000000000000000000000', 'newrev', 'refs/heads/master') - end - - it "when pushing tags" do - @webhook.should_not_receive(:execute) - project.execute_web_hooks('oldrev', 'newrev', 'refs/tags/v1.0.0') - end - end - - context "when pushing new branches" do - - end - - context "when gathering commit data" do - before do - @oldrev, @newrev, @ref = project.fresh_commits(2).last.sha, project.fresh_commits(2).first.sha, 'refs/heads/master' - @commit = project.fresh_commits(2).first - - # Fill nil/empty attributes - project.description = "This is a description" - - @data = project.web_hook_data(@oldrev, @newrev, @ref) - end - - subject { @data } - - it { should include(before: @oldrev) } - it { should include(after: @newrev) } - it { should include(ref: @ref) } - - context "with repository data" do - subject { @data[:repository] } - - it { should include(name: project.name) } - it { should include(url: project.web_url) } - it { should include(description: project.description) } - it { should include(homepage: project.web_url) } - it { should include(private: project.private?) } - end - - context "with commits" do - subject { @data[:commits] } - - it { should be_an(Array) } - it { should have(1).element } - - context "the commit" do - subject { @data[:commits].first } - - it { should include(id: @commit.id) } - it { should include(message: @commit.safe_message) } - it { should include(timestamp: @commit.date.xmlschema) } - it { should include(url: "http://localhost/#{project.code}/commits/#{@commit.id}") } - - context "with a author" do - subject { @data[:commits].first[:author] } - - it { should include(name: @commit.author_name) } - it { should include(email: @commit.author_email) } - end - end - end - - end - end - describe "updates" do let(:project) { Factory :project } @@ -290,15 +191,19 @@ end # # Table name: projects # -# id :integer not null, primary key -# name :string(255) -# path :string(255) -# description :text -# created_at :datetime -# updated_at :datetime -# private_flag :boolean default(TRUE), not null -# code :string(255) -# owner_id :integer -# default_branch :string(255) default("master"), not null +# id :integer not null, primary key +# name :string(255) +# path :string(255) +# description :text +# created_at :datetime +# updated_at :datetime +# private_flag :boolean default(TRUE), not null +# code :string(255) +# owner_id :integer +# default_branch :string(255) default("master"), not null +# issues_enabled :boolean default(TRUE), not null +# wall_enabled :boolean default(TRUE), not null +# merge_requests_enabled :boolean default(TRUE), not null +# wiki_enabled :boolean default(TRUE), not null # diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb new file mode 100644 index 00000000..a0b0032a --- /dev/null +++ b/spec/models/protected_branch_spec.rb @@ -0,0 +1,16 @@ +# == Schema Information +# +# Table name: protected_branches +# +# id :integer not null, primary key +# project_id :integer not null +# name :string(255) not null +# created_at :datetime not null +# updated_at :datetime not null +# + +require 'spec_helper' + +describe ProtectedBranch do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/users_project_spec.rb b/spec/models/users_project_spec.rb index 41e36b57..85bc4d34 100644 --- a/spec/models/users_project_spec.rb +++ b/spec/models/users_project_spec.rb @@ -25,7 +25,6 @@ end # project_id :integer not null # created_at :datetime # updated_at :datetime -# repo_access :integer default(0), not null # project_access :integer default(0), not null # diff --git a/spec/requests/admin/admin_projects_spec.rb b/spec/requests/admin/admin_projects_spec.rb index ffa65fc2..ceaf7245 100644 --- a/spec/requests/admin/admin_projects_spec.rb +++ b/spec/requests/admin/admin_projects_spec.rb @@ -18,7 +18,6 @@ describe "Admin::Projects" do end it "should have projects list" do - page.should have_content(@project.code) page.should have_content(@project.name) end end @@ -103,4 +102,18 @@ describe "Admin::Projects" do page.should have_content(@project.description) end end + + describe "Add new team member" do + before do + @new_user = Factory :user + visit admin_project_path(@project) + end + + it "should create new user" do + select @new_user.name, :from => "user_ids" + expect { click_button "Add" }.to change { UsersProject.count }.by(1) + page.should have_content @new_user.name + current_path.should == admin_project_path(@project) + end + end end diff --git a/spec/requests/admin/admin_users_spec.rb b/spec/requests/admin/admin_users_spec.rb index aa78db99..91082a64 100644 --- a/spec/requests/admin/admin_users_spec.rb +++ b/spec/requests/admin/admin_users_spec.rb @@ -99,4 +99,18 @@ describe "Admin::Users" do end end end + + describe "Add new project" do + before do + @new_project = Factory :project + visit admin_user_path(@user) + end + + it "should create new user" do + select @new_project.name, :from => "project_ids" + expect { click_button "Add" }.to change { UsersProject.count }.by(1) + page.should have_content @new_project.name + current_path.should == admin_user_path(@user) + end + end end diff --git a/spec/requests/admin/security_spec.rb b/spec/requests/admin/security_spec.rb index 27b60196..0b0edb85 100644 --- a/spec/requests/admin/security_spec.rb +++ b/spec/requests/admin/security_spec.rb @@ -13,12 +13,6 @@ describe "Admin::Projects" do it { admin_users_path.should be_denied_for :visitor } end - describe "GET /admin/team_members" do - it { admin_team_members_path.should be_allowed_for :admin } - it { admin_team_members_path.should be_denied_for :user } - it { admin_team_members_path.should be_denied_for :visitor } - end - describe "GET /admin/emails" do it { admin_emails_path.should be_allowed_for :admin } it { admin_emails_path.should be_denied_for :user } diff --git a/spec/requests/commits_spec.rb b/spec/requests/commits_spec.rb index f79e9753..00b69379 100644 --- a/spec/requests/commits_spec.rb +++ b/spec/requests/commits_spec.rb @@ -22,8 +22,8 @@ describe "Commits" do end it "should list commits" do - page.should have_content(commit.author) page.should have_content(commit.message) + page.should have_content(commit.id.to_s[0..5]) end it "should render atom feed" do @@ -55,4 +55,14 @@ describe "Commits" do current_path.should == project_commit_path(project, commit.id) end end + + describe "GET /commits/compare" do + before do + visit compare_project_commits_path(project) + end + + it "should have valid path" do + current_path.should == compare_project_commits_path(project) + end + end end diff --git a/spec/requests/dashboard_issues_spec.rb b/spec/requests/dashboard_issues_spec.rb index 46c5553e..29c79313 100644 --- a/spec/requests/dashboard_issues_spec.rb +++ b/spec/requests/dashboard_issues_spec.rb @@ -34,11 +34,9 @@ describe "User Issues Dashboard" do it { should have_content(@issue1.title[0..10]) } it { should have_content(@issue1.project.name) } - it { should have_content(@issue1.assignee.name) } it { should have_content(@issue2.title[0..10]) } it { should have_content(@issue2.project.name) } - it { should have_content(@issue2.assignee.name) } describe "atom feed", :js => false do it "should render atom feed via private token" do diff --git a/spec/requests/dashboard_merge_requests_spec.rb b/spec/requests/dashboard_merge_requests_spec.rb index e5916095..f345a858 100644 --- a/spec/requests/dashboard_merge_requests_spec.rb +++ b/spec/requests/dashboard_merge_requests_spec.rb @@ -34,14 +34,7 @@ describe "User MergeRequests" do it { should have_content(@merge_request1.title[0..10]) } it { should have_content(@merge_request1.project.name) } - it { should have_content(@merge_request1.target_branch) } - it { should have_content(@merge_request1.source_branch) } - it { should have_content(@merge_request1.assignee.name) } - it { should have_content(@merge_request2.title[0..10]) } it { should have_content(@merge_request2.project.name) } - it { should have_content(@merge_request2.target_branch) } - it { should have_content(@merge_request2.source_branch) } - it { should have_content(@merge_request2.assignee.name) } end end diff --git a/spec/requests/dashboard_spec.rb b/spec/requests/dashboard_spec.rb index 69ddd175..98de046f 100644 --- a/spec/requests/dashboard_spec.rb +++ b/spec/requests/dashboard_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' - +__END__ +# Disabled for now describe "Dashboard" do before do @project = Factory :project diff --git a/spec/requests/issues_spec.rb b/spec/requests/issues_spec.rb index 62daf168..bff99531 100644 --- a/spec/requests/issues_spec.rb +++ b/spec/requests/issues_spec.rb @@ -51,17 +51,17 @@ describe "Issues" do # admin access to remove issue @user.users_projects.destroy_all project.add_access(@user, :read, :write, :admin) - visit project_issues_path(project) + visit edit_project_issue_path(project, @issue) end it "should remove entry" do expect { - click_link "destroy_issue_#{@issue.id}" + click_link "Remove" }.to change { Issue.count }.by(-1) end end - describe "statuses", :js => true do + describe "statuses" do before do @closed_issue = Factory :issue, :author => @user, @@ -76,13 +76,13 @@ describe "Issues" do end it "should show only closed" do - choose "closed_issues" + click_link "Closed" should have_no_content(@issue.title) should have_content(@closed_issue.title[0..25]) end it "should show all" do - choose "all_issues" + click_link "All" should have_content(@issue.title[0..25]) should have_content(@closed_issue.title[0..25]) end @@ -182,7 +182,6 @@ describe "Issues" do :assignee => @user, :project => project visit project_issues_path(project) - page.execute_script("$('.action-links').css('display', 'block');") click_link "Edit" end @@ -200,7 +199,6 @@ describe "Issues" do it "should update issue fields" do click_button "Save" - page.should_not have_content("Issue ##{@issue.id}") page.should have_content @user.name page.should have_content "bug 345" page.should have_content project.name @@ -226,7 +224,7 @@ describe "Issues" do @issue.save visit project_issues_path(project) - choose 'closed_issues' + click_link 'Closed' fill_in 'issue_search', :with => 'foobar' page.should have_content 'foobar' diff --git a/spec/requests/keys_spec.rb b/spec/requests/keys_spec.rb index be1f42a4..2bc7c75b 100644 --- a/spec/requests/keys_spec.rb +++ b/spec/requests/keys_spec.rb @@ -26,14 +26,14 @@ describe "Issues" do end end - describe "New key", :js => true do + describe "New key" do before do visit keys_path click_link "Add new" end it "should open new key popup" do - page.should have_content("Add new public key") + page.should have_content("New key") end describe "fill in" do @@ -47,7 +47,7 @@ describe "Issues" do it "should add new key to table" do click_button "Save" - page.should_not have_content("Add new public key") + page.should_not have_content("New key") page.should have_content "laptop" end end diff --git a/spec/requests/merge_requests_spec.rb b/spec/requests/merge_requests_spec.rb index 7d9fd67b..f7b7e919 100644 --- a/spec/requests/merge_requests_spec.rb +++ b/spec/requests/merge_requests_spec.rb @@ -42,9 +42,7 @@ describe "MergeRequests" do it { should have_content(@merge_request.title[0..10]) } it "Show page should inform user that merge request closed" do - within ".merge-tabs" do - page.should have_content "Reopen" - end + page.should have_content "Reopen" end end end diff --git a/spec/requests/projects_security_spec.rb b/spec/requests/projects_security_spec.rb index f8942978..cf97716c 100644 --- a/spec/requests/projects_security_spec.rb +++ b/spec/requests/projects_security_spec.rb @@ -20,11 +20,9 @@ describe "Projects" do @u2 = Factory :user @u3 = Factory :user # full access - @project.users_projects.create(:user => @u1, :project_access => Project::PROJECT_RWA) - # no access - @project.users_projects.create(:user => @u2, :project_access => Project::PROJECT_N) + @project.users_projects.create(:user => @u1, :project_access => UsersProject::MASTER) # readonly - @project.users_projects.create(:user => @u3, :project_access => Project::PROJECT_R) + @project.users_projects.create(:user => @u3, :project_access => UsersProject::REPORTER) end describe "GET /project_code" do diff --git a/spec/requests/projects_spec.rb b/spec/requests/projects_spec.rb index 6db900c0..e6b6f19c 100644 --- a/spec/requests/projects_spec.rb +++ b/spec/requests/projects_spec.rb @@ -5,7 +5,7 @@ describe "Projects" do describe "GET /projects" do before do - @project = Factory :project + @project = Factory :project, :owner => @user @project.add_access(@user, :read) visit projects_path end @@ -15,7 +15,7 @@ describe "Projects" do end it "should have link to new project" do - page.should have_content("Create new project") + page.should have_content("New Project") end it "should have project" do @@ -26,7 +26,7 @@ describe "Projects" do describe "GET /projects/new" do before do visit projects_path - click_link "Create new project" + click_link "New Project" end it "should be correct path" do @@ -68,7 +68,7 @@ describe "Projects" do describe "GET /projects/show" do before do - @project = Factory :project + @project = Factory :project, :owner => @user @project.add_access(@user, :read) visit project_path(@project) @@ -128,7 +128,7 @@ describe "Projects" do describe "PUT /projects/:id" do before do - @project = Factory :project + @project = Factory :project, :owner => @user @project.add_access(@user, :admin, :read) visit edit_project_path(@project) @@ -141,7 +141,7 @@ describe "Projects" do end it "should be correct path" do - current_path.should == info_project_path(@project) + current_path.should == edit_project_path(@project) end it "should show project" do diff --git a/spec/requests/projects_wall_spec.rb b/spec/requests/projects_wall_spec.rb index bb734bda..b0ea6e62 100644 --- a/spec/requests/projects_wall_spec.rb +++ b/spec/requests/projects_wall_spec.rb @@ -8,7 +8,7 @@ describe "Projects", "Wall" do project.add_access(@user, :read, :write) end - describe "View notes on wall" do + describe "View notes on wall", :js => true do before do Factory :note, :project => project, :note => "Project specs", :author => @user visit wall_project_path(project) diff --git a/spec/requests/repositories_spec.rb b/spec/requests/repositories_spec.rb index 0b5d378d..3fb5371b 100644 --- a/spec/requests/repositories_spec.rb +++ b/spec/requests/repositories_spec.rb @@ -18,17 +18,8 @@ describe "Repository" do current_path.should == project_repository_path(@project) end - it "should have link to repo activities" do - page.should have_content("Activities") - end - it "should have link to last commit for activities tab" do page.should have_content(@project.commit.safe_message[0..20]) - page.should have_content(@project.commit.author_name) - end - - it "should show commits list" do - page.all(:css, ".project-update").size.should == @project.repo.branches.size end end diff --git a/spec/requests/snippets_spec.rb b/spec/requests/snippets_spec.rb index f0531a0a..9b9bb0e9 100644 --- a/spec/requests/snippets_spec.rb +++ b/spec/requests/snippets_spec.rb @@ -21,7 +21,6 @@ describe "Snippets" do it { should have_content(@snippet.title[0..10]) } it { should have_content(@snippet.project.name) } - it { should have_content(@snippet.author.name) } describe "Destroy" do before do @@ -73,7 +72,7 @@ describe "Snippets" do :author => @user, :project => project visit project_snippet_path(project, @snippet) - click_link "Edit Snippet" + click_link "Edit" end it "should open edit page" do diff --git a/spec/requests/team_members_spec.rb b/spec/requests/team_members_spec.rb index 997de8b8..78385725 100644 --- a/spec/requests/team_members_spec.rb +++ b/spec/requests/team_members_spec.rb @@ -10,9 +10,7 @@ describe "TeamMembers" do describe "View profile" do it "should be available" do visit(team_project_path(@project)) - within "#team-table" do - click_link(@user.name) - end + click_link(@user.name) page.should have_content @user.skype page.should_not have_content 'Twitter' end @@ -31,10 +29,9 @@ describe "TeamMembers" do describe "fill in" do before do - within "#team_member_new" do + within "#new_team_member" do select @user_1.name, :from => "team_member_user_id" - select "Report", :from => "team_member_project_access" - select "Pull", :from => "team_member_repo_access" + select "Reporter", :from => "team_member_project_access" end end @@ -47,16 +44,15 @@ describe "TeamMembers" do page.should have_content @user_1.name @member.reload - @member.project_access.should == Project::PROJECT_RW - @member.repo_access.should == Repository::REPO_R + @member.project_access.should == UsersProject::REPORTER end end end describe "Cancel membership" do it "should cancel membership" do - visit team_project_path(@project) - expect { click_link "Cancel" }.to change { UsersProject.count }.by(-1) + visit project_team_member_path(@project, @project.users_projects.last) + expect { click_link "Remove from team" }.to change { UsersProject.count }.by(-1) end end end diff --git a/spec/requests/wikis_spec.rb b/spec/requests/wikis_spec.rb new file mode 100644 index 00000000..fd66b5e4 --- /dev/null +++ b/spec/requests/wikis_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe "Wiki" do + let(:project) { Factory :project } + + before do + login_as :user + project.add_access(@user, :read, :write) + end + + describe "Add pages" do + before do + visit project_wiki_path(project, :index) + end + + it "should see form" do + page.should have_content("Editing page") + end + + it "should see added page" do + fill_in "Title", :with => 'Test title' + fill_in "Content", :with => '[link test](test)' + click_on "Save" + + page.should have_content("Test title") + page.should have_content("link test") + + click_link "link test" + + page.should have_content("Editing page") + end + + end + +end diff --git a/spec/support/shared_examples.rb b/spec/support/shared_examples.rb index 22699b0c..9fd207d0 100644 --- a/spec/support/shared_examples.rb +++ b/spec/support/shared_examples.rb @@ -2,8 +2,7 @@ shared_examples_for :project_side_pane do subject { page } it { should have_content((@project || project).name) } it { should have_content("Commits") } - it { should have_content("Team") } - it { should have_content("Tree") } + it { should have_content("Files") } end shared_examples_for :tree_view do diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 500a6998..c28273d5 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -10,17 +10,22 @@ describe PostReceive do context "web hooks" do let(:project) { Factory :project } + before do + @key = Factory :key, :user => project.owner + @key_id = @key.identifier + end it "it retrieves the correct project" do Project.should_receive(:find_by_path).with(project.path) - PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master') + Key.should_receive(:find_by_identifier).with(project.path) + PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', @key_id) end it "asks the project to execute web hooks" do Project.stub(find_by_path: project) - project.should_receive(:execute_web_hooks).with('sha-old', 'sha-new', 'refs/heads/master') + project.should_receive(:execute_web_hooks).with('sha-old', 'sha-new', 'refs/heads/master', @key_id) - PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master') + PostReceive.perform(project.path, 'sha-old', 'sha-new', 'refs/heads/master', @key_id) end end end diff --git a/vendor/assets/javascripts/bootstrap-modal.js b/vendor/assets/javascripts/bootstrap-modal.js new file mode 100644 index 00000000..b328217f --- /dev/null +++ b/vendor/assets/javascripts/bootstrap-modal.js @@ -0,0 +1,260 @@ +/* ========================================================= + * bootstrap-modal.js v1.4.0 + * http://twitter.github.com/bootstrap/javascript.html#modal + * ========================================================= + * Copyright 2011 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================= */ + + +!function( $ ){ + + "use strict" + + /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) + * ======================================================= */ + + var transitionEnd + + $(document).ready(function () { + + $.support.transition = (function () { + var thisBody = document.body || document.documentElement + , thisStyle = thisBody.style + , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined + return support + })() + + // set CSS transition event type + if ( $.support.transition ) { + transitionEnd = "TransitionEnd" + if ( $.browser.webkit ) { + transitionEnd = "webkitTransitionEnd" + } else if ( $.browser.mozilla ) { + transitionEnd = "transitionend" + } else if ( $.browser.opera ) { + transitionEnd = "oTransitionEnd" + } + } + + }) + + + /* MODAL PUBLIC CLASS DEFINITION + * ============================= */ + + var Modal = function ( content, options ) { + this.settings = $.extend({}, $.fn.modal.defaults, options) + this.$element = $(content) + .delegate('.close', 'click.modal', $.proxy(this.hide, this)) + + if ( this.settings.show ) { + this.show() + } + + return this + } + + Modal.prototype = { + + toggle: function () { + return this[!this.isShown ? 'show' : 'hide']() + } + + , show: function () { + var that = this + this.isShown = true + this.$element.trigger('show') + + escape.call(this) + backdrop.call(this, function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + that.$element + .appendTo(document.body) + .show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element.addClass('in') + + transition ? + that.$element.one(transitionEnd, function () { that.$element.trigger('shown') }) : + that.$element.trigger('shown') + + }) + + return this + } + + , hide: function (e) { + e && e.preventDefault() + + if ( !this.isShown ) { + return this + } + + var that = this + this.isShown = false + + escape.call(this) + + this.$element + .trigger('hide') + .removeClass('in') + + $.support.transition && this.$element.hasClass('fade') ? + hideWithTransition.call(this) : + hideModal.call(this) + + return this + } + + } + + + /* MODAL PRIVATE METHODS + * ===================== */ + + function hideWithTransition() { + // firefox drops transitionEnd events :{o + var that = this + , timeout = setTimeout(function () { + that.$element.unbind(transitionEnd) + hideModal.call(that) + }, 500) + + this.$element.one(transitionEnd, function () { + clearTimeout(timeout) + hideModal.call(that) + }) + } + + function hideModal (that) { + this.$element + .hide() + .trigger('hidden') + + backdrop.call(this) + } + + function backdrop ( callback ) { + var that = this + , animate = this.$element.hasClass('fade') ? 'fade' : '' + if ( this.isShown && this.settings.backdrop ) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('