Commit bfe0906f authored by Ariejan de Vroom's avatar Ariejan de Vroom

Merge remote-tracking branch 'upstream/master'

parents 4587ab6f df6f7481
......@@ -9,5 +9,10 @@ coverage/*
*.swp
public/uploads/
.rvmrc
.rbenv-version
.directory
nohup.out
Vagrantfile
.vagrant
config/gitlab.yml
config/database.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"
......
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
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
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=*
app/assets/images/Info-UI.PNG

800 Bytes | W: | H:

app/assets/images/Info-UI.PNG

801 Bytes | W: | H:

app/assets/images/Info-UI.PNG
app/assets/images/Info-UI.PNG
app/assets/images/Info-UI.PNG
app/assets/images/Info-UI.PNG
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/blueprint_add.png

518 Bytes | W: | H:

app/assets/images/blueprint_add.png

177 Bytes | W: | H:

app/assets/images/blueprint_add.png
app/assets/images/blueprint_add.png
app/assets/images/blueprint_add.png
app/assets/images/blueprint_add.png
  • 2-up
  • Swipe
  • Onion skin
app/assets/images/blueprint_delete.png

469 Bytes | W: | H:

app/assets/images/blueprint_delete.png

295 Bytes | W: | H:

app/assets/images/blueprint_delete.png
app/assets/images/blueprint_delete.png
app/assets/images/blueprint_delete.png
app/assets/images/blueprint_delete.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -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");
}
......@@ -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();
}
});
......
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();
});
});
}
......@@ -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"});
}
......
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();
},
getOld:
function() {
$('.loading').show();
$.ajax({
type: "GET",
url: location.href,
data: "first_id=" + this.first_id,
complete: function(){ $('.loading').hide()},
dataType: "script"});
$('.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();
});
},
append:
function(id, html) {
this.first_id = id;
$("#notes-list").append(html);
this.initLoadMore();
/**
* 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() {
// 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,23 +79,83 @@ 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:
/**
* Init load of notes:
* 1. Get content with ajax call
* 2. Set content of notes list with loaded one
*/
getContent:
function() {
// init timer
var intNew = setInterval("NoteList.getNew()", 15000);
var intRefresh = setInterval("NoteList.refresh()", 90000);
$.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();
}
});
......
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,20 +24,26 @@ 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();
}
});
}
......
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();
});
});
......
......@@ -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"); }
});
......
......@@ -7,5 +7,5 @@
*= require jquery-ui/jquery.tagify
*= require chosen
*= require_self
*= require common
*= require main
*/
/* 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;
}
}
}
}
$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;
/** 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;
}
@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;
a {
color: $link_color;
&:hover {
text-decoration:none;
color: $style_color;
}
&.btn {
color: $style_color;
}
}
.vlink {
color: $link_color !important;
}
.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;
}
/** LAYOUT **/
/* General */
.container {
width:$min_app_width;
padding-top:0;
z-index:5;
}
body.collapsed {
background-color: $bg_color;
.container .content {
margin:0 $app_padding;
}
#container{
margin: auto;
margin-top:51px;
width: $app_width;
border-top: 0;
background-color: $bg_color;
.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 {
.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;
}
}
}
.visible_link,
.author_link {
color: $link_color;
}
.entry {
position: relative;
padding: 7px 15px;
margin-bottom: 18px;
color: #404040;
filter:none;
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;
}
}
@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";
/**
*
* COMMIT SHOw
*
*/
.diff_file {
border:1px solid #CCC;
margin-bottom:1em;
@import "top_panel.scss";
@import "dashboard.scss";
@import "tree.scss";
.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;
}
}
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 */
.black .highlighttable {
background: #333;
td.linenos { border:none; }
pre { color: #eee }
.highlight { background: #333; border-left:1px solid #555; }
......
......@@ -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;}
}
......
.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;
}
}
}
/* 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}
@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";
// 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;
}
}
/** 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;
}
/**
* 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);
}
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{
.sidebar aside a{
display: block;
position: relative;
padding: 15px 10px;
margin: 10px 0 0 0;
font-size:13px;
font-weight:bold;
color:#333;
}
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 {
&.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;
......@@ -62,16 +23,12 @@ body.project-page .project-sidebar aside a.current {
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; }
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 {
......@@ -122,37 +79,6 @@ input.ssh_project_url {
}
/** 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;
......@@ -177,7 +103,7 @@ input.ssh_project_url {
.filter .left { margin-right:15px; }
body.project-page table .commit {
body table .commit {
a.tree-commit-link {
color:#444;
&:hover {
......@@ -218,76 +144,6 @@ body.project-page table .commit {
}
}
/** 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;
......@@ -299,31 +155,19 @@ body.project-page table .commit {
/* 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;}
.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 */
/** 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%; }
......@@ -337,19 +181,19 @@ a.update-item span.update-author{color: #999; font-weight: normal; font-style: i
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 .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 {
body 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{
body table.no-borders tr,
body table.no-borders td{
border:none;
}
......@@ -503,31 +347,6 @@ h4.dash-tabs {
}
.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 {
......@@ -564,9 +383,3 @@ a.project-update.titled {
font-size:11px;
margin: 10px 0;
}
.new-project-hodler {
padding:20px;
}
/** 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;
}
}
}
/* 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;
}
}
}
.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;
}
.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;
}
#tree-breadcrumbs {
div {
margin:0;
margin-bottom:20px;
#tree-holder {
#tree-content-holder {
float:left;
font-size:14px;
width:100%;
}
}
.tree_progress {
#tree-readme-holder {
float:left;
width:16px;
height:16px;
margin:2px 6px;
width:100%;
.readme {
@include round-borders-all(4px);
padding:4px 15px;
background: #F7F7F7;
}
}
.tree_progress {
display:none;
margin:20px;
&.loading {
background-position: 0px 0px;
background: url("ajax-loader-facebook.gif") no-repeat;
display:block;
}
}
}
/** FILE CONTENT VIEW **/
.view_file_content{
/** FILE CONTENT VIEW **/
.view_file_content{
.old_line, .new_line {
background:#ECECEC;
color:#777;
......@@ -32,37 +35,26 @@
.old_line{
display:none;
}
}
}
.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);
.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 {
.view_file {
border:1px solid #CCC;
margin-bottom:1em;
......@@ -79,43 +71,108 @@
max-width:300px;
}
}
}
}
td.code {
td.code {
width: 100%;
.highlight {
margin-left: 55px;
overflow:auto;
overflow-y:hidden;
border-left: 1px solid #DEE2E3;
background: white;
}
}
.highlight pre {
}
.highlight pre {
white-space: pre;
word-wrap:normal;
}
}
table.highlighttable {
table.highlighttable {
border: none;
background: #F7F7F7;
}
body.project-page table.highlighttable td { border: none }
table.highlighttable tr:hover { background:none;}
}
body.project-page table.highlighttable td { border: none }
table.highlighttable tr:hover { background:none;}
table.highlighttable pre{
table.highlighttable pre{
line-height:16px !important;
font-size:12px !important;
}
}
table.highlighttable .linenodiv pre {
table.highlighttable .linenodiv pre {
text-align: right;
padding-right: 4px;
color:#888;
}
}
.tree-item {
.tree-item {
&:hover {
background: #FFFFCF;
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;
}
}
/**
* 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
*
*/
}
/**
* 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
*
*/
}
......@@ -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
......
......@@ -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
......@@ -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
......
......@@ -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
......@@ -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)
@note = @project.build_commit_note(@commit)
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
......@@ -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
......
class ErrorsController < ApplicationController
layout "error"
def githost
render :file => File.join(Rails.root, "public", "githost_error"), :layout => false
render "errors/gitolite"
end
end
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
class KeysController < ApplicationController
layout "profile"
respond_to :js
respond_to :js, :html
def index
@keys = current_user.keys.all
......
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
......@@ -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
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
......@@ -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
......
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
......@@ -4,13 +4,18 @@ 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
respond_to do |format|
format.html do
new_path = if params[:destination] == "tree"
tree_project_ref_path(@project, params[:ref])
else
......@@ -19,6 +24,13 @@ class RefsController < ApplicationController
redirect_to new_path
end
format.js do
@ref = params[:ref]
define_tree_vars
render "tree"
end
end
end
#
# Repository preview
......@@ -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])
......
......@@ -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
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
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
......@@ -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
......
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
......@@ -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
......@@ -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 diff_line_class(line)
if line[0] == "+"
"new"
elsif line[0] == "-"
"old"
else
nil
end
end
def build_line_code(line, index, line_new, line_old)
if diff_line_class(line) == "new"
"NEW_#{index}_#{line_new}"
"#{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
"OLD_#{index}_#{line_old}"
line_new += 1
line_old += 1
end
end
end
end
......@@ -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
......
......@@ -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
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
......@@ -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"
#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
module WikisHelper
def markdown_to_html(text)
RDiscount.new(text).to_html.html_safe
end
end
......@@ -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
......
......@@ -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) : []
......
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
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
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
#
......@@ -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
......
......@@ -27,7 +27,8 @@ class MailerObserver < ActiveRecord::Observer
end
def new_note(note)
return unless note.notify or note.notify_author
# 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
......@@ -42,6 +43,10 @@ class MailerObserver < ActiveRecord::Observer
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
def new_merge_request(merge_request)
......
......@@ -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
......
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 guest_access_for?(user)
!users_projects.where(:user_id => user.id).empty?
end
def report_access_for?(user)
!users_projects.where(:user_id => user.id, :project_access => [UsersProject::REPORTER, UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
end
def allow_write_for?(user)
!users_projects.where(:user_id => user.id, :project_access => [PROJECT_RW, PROJECT_RWA]).empty?
def dev_access_for?(user)
!users_projects.where(:user_id => user.id, :project_access => [UsersProject::DEVELOPER, UsersProject::MASTER]).empty?
end
def allow_admin_for?(user)
!users_projects.where(:user_id => user.id, :project_access => [PROJECT_RWA]).empty? || owner_id == user.id
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
......@@ -345,5 +376,9 @@ end
# 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
#
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
#
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
......
......@@ -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
#
......
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
#
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
#
= 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] }
- 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;")
.form-row
.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();
})
%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 => ""
%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"
- unless notice.nil?
%p#notice= notice
%h3
= @admin_project.name
= link_to 'Edit', edit_admin_project_path(@admin_project), :class => "btn right small"
%h2= @admin_project.name
%hr
%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 {
......
= 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] }
.span-6
%b Project Access:
.span-6
.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 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 {
......
= render 'form'
%h3
Edit access
%small
= @admin_team_member.project.name
&ndash;
= @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'
- @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"
%h1 New team member
= render 'form'
%br
= link_to 'Back', admin_team_members_path
#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
......@@ -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"
%h3= @admin_user.name
%hr
= render 'form'
%br
= link_to 'Back', admin_users_path, :class => ""
|
= link_to 'Show', [:admin, @admin_user], :class => ""
%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"
%h1 New user
%h2 New user
%hr
= render 'form'
%br
= link_to 'Back', admin_users_path, :class => ""
%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,18 +43,14 @@
Twitter:
%td
= @admin_user.twitter
%tr
%td{:colspan => 2}
= link_to 'Edit', edit_admin_user_path(@admin_user), :class => "grey-button"
.span-14
%h2 Projects
%h3 Projects
%hr
%table.round-borders
%table.zebra-striped
%tr
%thead
%th Name
%th Added
%th Project Access
%th Repository Access
%th
......@@ -60,10 +60,38 @@
- project = tm.project
%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
%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"
= form_tag team_update_admin_user_path(@admin_user), :class => "bulk_import", :method => :put do
%table
%thead
%tr
%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"
%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
&ndash;
= 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
&nbsp;
- @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
%ul.bordered-list
- @commit.diffs.each do |diff|
- diffs.each do |diff|
%li
- if diff.deleted_file
%span.removed_file
......
.file_stats
= render "commits/diff_head"
= render "commits/diff_head", :diffs => diffs
- @commit.diffs.each_with_index do |diff, i|
- 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
%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();
});
= 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/
%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?
- each_diff_line(diff.diff.lines.to_a, index) do |line, type, line_code, line_new, line_old|
%tr.line_holder
- if type == "match"
%td.old_line= "..."
%td.new_line= "..."
%td.line_content &nbsp;
- 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/, ''))
%tr.line_holder
%td.line_content.matched= line
- else
%td.old_line
= link_to raw(diff_line_class(line) == "new" ? "&nbsp;" : line_old), "#OLD#{index}-#{line_old}", :id => "OLD#{index}-#{line_old}"
%td.new_line
= link_to raw(diff_line_class(line) == "old" ? "&nbsp;" : 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} &nbsp;"
- comments = @line_notes.select { |n| n.for_line?(index, line_old, line_new) }.sort_by(&:created_at).reverse
= link_to raw(type == "new" ? "&nbsp;" : 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" ? "&nbsp;" : line_new) , "##{line_code}", :id => line_code
%td.line_content{:class => "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} &nbsp;"
- if @comments_allowed
- comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at).reverse
- unless comments.empty?
- comments.each do |note|
- 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
- if line[0] == "+"
- line_new += 1
- elsif line[0] == "-"
- line_old += 1
- else
- line_new += 1
- line_old += 1
- @line_notes.reject!{ |n| n == note }
= render "head"
%h3
Compare View
%hr
%div
%p
Fill input field with commit id like
%code '4eedf23'
or branch/tag name like
%code master
&amp; 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
});
});
- 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
%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)}
......@@ -21,5 +19,6 @@
- if @commits.count == @limit
:javascript
$(function(){
CommitsList.init("#{@ref}", 20);
CommitsList.init("#{@ref}", #{@limit});
});
- 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
&ndash;
%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;
});
});
- @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
#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
&ndash;
Issue #
= issue.id
= truncate issue.title, :length => 50
-#%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();
});
});
#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
&rarr;
%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
&ndash;
Merge Request #
= merge_request.id
= truncate merge_request.title, :length => 50
#feeds_content_holder
- @active_projects.first(3).each do |project|
.project-box.project-updates.ui-box.ui-box-small.ui-box-big
- @active_projects.first(5).each do |project|
.wll
= 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
%h4
= project.name
%small
last activity at
= project.last_activity_date_cached.stamp("Aug 25, 2011")
%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"
- 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 &rarr;
%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 &rarr;
%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 &rarr;
%hr
.row
.dashboard_block= render "dashboard/issues_feed"
- unless @events.blank?
%div.dashboard_category
%h3
Activities
%hr
.row
.dashboard_block= render "dashboard/events_feed"
- 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"
- 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"
%div
= form_for [@project, @key], :url => project_deploy_keys_path do |f|
-if @key.errors.any?
%ul.errors_holder
.alert-message.block-message.error
%ul
- @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"
.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"
%a.update-item{:href => project_deploy_key_path(key.project, key)}
%span.update-title
= key.title
%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"
= 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
%table.zebra-striped.borders
- @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(); });
= render "repositories/head"
%h2 New Deploy key
%h3 New Deploy key
%hr
= render 'form'
.ui-box.width-100p
%h3= @key.title
.data
%pre= @key.key
= 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
.buttons
= link_to 'Remove', project_deploy_key_path(@key.project, @key), :confirm => 'Are you sure?', :method => :delete, :class => "red-button delete-key right"
.clear
<h2>Change your password</h2>
<%= 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 %>
<div><%= f.label :password, "New password" %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Change my password" %></div>
<% end %>
<%= render :partial => "devise/shared/links" %>
= 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"
<%= 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" %>
<br/>
<%= f.submit "Reset password", :class => "grey-button" %>
<br/>
<%= f.submit "Reset password", :class => "primary btn" %>
<div class="right"> <%= render :partial => "devise/shared/links" %></div>
<% end %>
......@@ -4,9 +4,12 @@
<%= f.password_field :password, :class => "text bottom", :placeholder => "Password" %>
<% if devise_mapping.rememberable? -%>
<div><%= f.check_box :remember_me %> <%= f.label :remember_me %></div>
<div class="clearfix inputs-list"> <label for="user_remember_me"><%= f.check_box :remember_me %><span>Remember me</span></label></div>
<% end -%>
<br/>
<%= f.submit "Sign in", :class => "grey-button" %>
<%= f.submit "Sign in", :class => "primary btn" %>
<div class="right"> <%= render :partial => "devise/shared/links" %></div>
<% if ldap_enable? -%>
<p><%= link_to "via LDAP", user_omniauth_authorize_path(:ldap)%></p>
<% end -%>
<% end %>
<%- if controller_name != 'sessions' %>
<%= link_to "Sign in", new_session_path(resource_name) %><br />
<%= link_to "Sign in", new_session_path(resource_name), :class => "btn" %><br />
<% 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) %><br />
<%= link_to "Forgot your password?", new_password_path(resource_name), :class => "btn" %><br />
<% end -%>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
......
.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"}
.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
.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/
.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.
- bash_lexer = Pygments::Lexer[:bash]
%div.help_content
%h2
%h3
Gitlabhq
%span.right v2.1
%hr
%h3 Self Hosted Git Management
%h3 Fast, secure and stable solution based on Ruby on Rails & Gitolite.
%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 &amp; merge it to main branch
%li
= link_to "Permissions", help_permissions_path
%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
- 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 &amp; merge it to main branch
= render "repositories/head"
- unless @hooks.empty?
%div.update-data.ui-box.ui-box-small
.data
= render "projects/project_head"
- 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
%table.zebra-striped.borders
- @hooks.each do |hook|
%a.update-item{:href => project_hook_path(@project, hook)}
%span.update-title{:style => "margin-bottom:0px;"}
%tr
%td
= link_to project_hook_path(@project, hook) do
= hook.url
%span.update-author.right
Added
= time_ago_in_words(hook.created_at)
ago
- else
%h3 No hooks
%td
= link_to 'Remove', project_hook_path(@project, hook), :confirm => 'Are you sure?', :method => :delete, :class => "danger btn small"
.clear
%hr
%p
Post receive hooks. For now only POST request allowed. We send some data with request. Example below
.alert-message.block-message
We send some data with POST request when someone makes git push
.view_file
.view_file_header
%strong POST data passed
.data.no-padding
= render "data_ex"
.well= render "data_ex"
......@@ -4,10 +4,9 @@
%ul
- @hook.errors.full_messages.each do |msg|
%li= msg
.clearfix
= f.label :url, "URL:"
= f.text_field :url, :class => "text_field"
.clear
%br
.merge-tabs
= f.submit "Save", :class => "grey-button"
.input= f.text_field :url, :class => "text_field"
.actions
= f.submit "Save", :class => "btn"
= 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"
%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}"
%h3= @issue.new_record? ? "New Issue" : "Edit Issue ##{@issue.id}"
%hr
-if @issue.errors.any?
%ul.errors_holder
.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
.clearfix
= f.label :critical, "Critical"
.input= f.check_box :critical
- unless @issue.new_record?
%tr
%td= f.label :closed
%td= f.check_box :closed
.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"
= f.text_area :title, :style => "width:718px; height:100px", :maxlength => 255
%br
%br
.merge-tabs
= f.submit 'Save', :class => "positive-button"
&nbsp;
- 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"
.top-tabs
= link_to project_issues_path(@project), :class => "tab #{'active' if current_page?(project_issues_path(@project)) }" do
%span
.tabs
%li{:class => "#{'active' if current_page?(project_issues_path(@project))}"}
= link_to project_issues_path(@project), :class => "tab" do
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
%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
%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 => "cgray", :remote => true
= 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 => "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}"
= 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)
= 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
- 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' }
.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"
%ul#issues-table.unstyled= render "issues"
.clear
%hr
%table.no-borders#issues-table
= render "issues"
%br
: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)}"})
}
......
:plain
$('#issues-table tbody').html("#{escape_javascript(render('issues'))}");
$('#issues-table').html("#{escape_javascript(render('issues'))}");
setSortable();
%div
%span.entity-info
- 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
&rarr;
= link_to project_team_member_path(@project, @project.team_member_by_id(@issue.assignee.id)) do
%span.author= @issue.assignee_name
&nbsp;
&nbsp;
= @issue.created_at.stamp("Aug 21, 2011 9:23pm")
%h3
Issue ##{@issue.id}
%small
created at
= @issue.created_at.stamp("Aug 21, 2011")
%hr
%br
%h3
= simple_format @issue.title
.clear
%br
%br
.merge-tabs
= link_to "#notes", :class => "merge-notes-tab active tab" do
%span
Notes
.right
%span.right
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
- if @issue.closed
= link_to 'Reopen', project_issue_path(@project, @issue, :issue => {:closed => false }, :status_only => true), :method => :put, :class => "red-button"
= 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 => "positive-button"
= 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
.back_link
= link_to project_issues_path(@project) do
&larr; To issues list
%hr
- if @issue.closed
.alert-message.error Closed
- else
.alert-message.success Open
%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
.merge-request-notes
.issue_notes= render "notes/notes"
.loading{ :style => "display:none;"}
%center= image_tag "ajax-loader.gif"
.clear
.issue_notes= render "notes/notes", :tid => @issue.id, :tt => "issue"
-# 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
-# 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')
-# 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}
-# 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
-# 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}
-# 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?
-# 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
%div
= form_for @key, :remote => true do |f|
= form_for @key do |f|
-if @key.errors.any?
.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"
%a.update-item{:href => key_path(key)}
%span.update-title
= key.title
%span.update-author
%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"
%h2.icon
%span>
%h3
SSH Keys
%div#new-key-holder.right
= link_to "Add new", new_key_path, :remote => true, :class => "grey-button"
%br
= link_to "Add new", new_key_path, :class => "btn small right"
%div#keys-table{ :class => "update-data ui-box ui-box-small ui-box-big" }
.data
%hr
%table#keys-table.zebra-striped.borders
- @keys.each do |key|
= render(:partial => 'show', :locals => {:key => key})
:javascript
$('.delete-key').live('ajax:success', function() {
$(this).closest('.update-item').fadeOut(); });
%h1 New key
%h3 New key
%hr
= render 'form'
= link_to 'Back', keys_path
.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"
%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"}"
= link_to "Home", root_path, :class => "home #{"current" if current_page?(dashboard_path) || current_page?(root_path)}", :title => "Home"
- if alert || notice
- text = alert || notice
%div{:style => "display:none", :id => "flash_container"}
.container
%center
%h4= text
:javascript
......@@ -10,7 +9,7 @@
$("#flash_container").click(function(){
$(this).slideUp("slow");
});
setTimeout("hideFlash()",2000);
setTimeout("hideFlash()",3000);
});
function hideFlash(){
......
%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
......@@ -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
- 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"
= 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"
.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
: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();
}
});
});
-#- 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!
%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
.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
%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"
%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"
!!!
%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
!!! 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 "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"
.project-content
= yield
.content= yield
!!!
%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"
!!! 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
!!!
%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
!!! 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
!!!
%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
!!! 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
Keys
- unless current_user.keys.empty?
%span{ :class => "number" }= current_user.keys.count
.project-content
= yield
SSH Keys
.content
.row
.span12= yield
.sidebar= render "layouts/projects_side"
!!!
%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"
- 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
- @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
= 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
%h2= @merge_request.new_record? ? "New Merge Request" : "Edit Merge Request ##{@merge_request.id}"
%hr
%table.no-borders
-if @merge_request.errors.any?
%tr
%td{:colspan => 2}
#error_explanation
.alert-message.block-message.error
%ul
- @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"
%li= msg
.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")
.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
&nbsp;
- 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"
......
......@@ -3,10 +3,3 @@
%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
%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();
})
})
%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
&rarr;
%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)
%h3
= "Edit merge request #{@merge_request.id}"
%hr
= render 'form'
= 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
%h3 New Merge Request
%hr
= render 'form'
%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
%h3
= "Merge Request ##{@merge_request.id}:"
&nbsp;
.tag.commit.inline= @merge_request.source_branch
%span.label= @merge_request.source_branch
&rarr;
.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
&rarr;
= link_to project_team_member_path(@project, @project.team_member_by_id(@merge_request.assignee.id)) do
%span.author= @merge_request.assignee_name
%span.label= @merge_request.target_branch
&nbsp;
&nbsp;
= @merge_request.created_at.stamp("Aug 21, 2011 9:23pm")
%small
created at
= @merge_request.created_at.stamp("Aug 21, 2011")
%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 => "btn"
- else
= 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
&larr; 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
%br
%h3
= simple_format @merge_request.title
.clear
%br
%br
.merge-tabs
= link_to "#notes", :class => "merge-notes-tab active tab" do
%span
%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
= link_to "#commits", "data-url" => commits_project_merge_request_path(@project, @merge_request), :class => "merge-commits-tab tab" do
%span
Commits
%li
= 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
- 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"
- 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"}
.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;
});
});
- 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'))}");
- 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})}");
%div
= form_for [@project, @note], :remote => "true", :multipart => true do |f|
= form_for [@project, @note], :remote => "true", :multipart => true do |f|
%h3 Leave a note
-if @note.errors.any?
.errors.error
.alert-message.block-message.error
- @note.errors.full_messages.each do |msg|
%div= msg
= f.hidden_field :noteable_id
= f.hidden_field :noteable_type
%div
= f.label :note
%cite.cgray markdown supported
%br
%br
= f.text_area :note, :size => 255
%div.attach_holder
%br
= f.label :attachment
%cite.cgray (less than 10 MB)
%br
%br
= f.file_field :attachment
%p.notify_controls
%span Notify:
.row
.span4
%h5 Notify via email:
.clearfix
= label_tag :notify do
= check_box_tag :notify, 1, @note.noteable_type != "Commit"
= label_tag :notify, "Project team"
%span Project team
-if @note.noteable_type == "Commit"
- if @note.notify_only_author?(current_user)
= label_tag :notify_author do
= check_box_tag :notify_author, 1 , @note.noteable_type == "Commit"
= label_tag :notify_author, "Commit author"
%span Commit author
.span4
%h5 Attachment:
.clearfix
= f.label :attachment, "Any file, < 10 MB"
.input= f.file_field :attachment, :class => "input-file"
.clear
%br
= f.submit 'Add note', :class => "positive-button", :id => "submit_note"
= f.submit 'Add note', :class => "btn primary", :id => "submit_note"
- unless @notes.blank?
- if params[:last_id] && params[:first_id]
:plain
NoteList.replace(#{@notes.last.id}, #{@notes.first.id}, "#{escape_javascript(render(:partial => 'notes/notes_list'))}");
- elsif params[:last_id]
- if 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]}, "");
......@@ -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");
})
:javascript
$(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)}");
});
%table{:style => "display:none;"}
%tr.per_line_form
%td{:colspan => 3 }
%div
= form_for [@project, @note], :remote => "true", :multipart => true do |f|
%h3 Leave a note
.row
.span16
-if @note.errors.any?
.errors.error
.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.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(){
......
%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"
......@@ -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)
......
- 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})}");
- if @note.line_code
= render "create_line", :note => @note
- else
- unless @note.line_code
:plain
$("#new_note").replaceWith("#{escape_javascript(render('form'))}");
= render "create_common", :note => @note
-# Enable submit button
:plain
$("#submit_note").removeAttr("disabled");
......@@ -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"}
......@@ -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"}
......@@ -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"}
......@@ -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"}
.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
%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
.right.dark_scheme_box
%label{:for => "user_dark_scheme_true"}
= image_tag "dark.png", :width => 310, :height => 212
%label.span4{:for => "user_dark_scheme_true"}
= image_tag "dark.png", :width => 210
%center
%h4
= f.radio_button :dark_scheme, true
Dark code preview
.clear
.buttons
= f.submit 'Save', :class => "grey-button"
.clearfix
.actions
= f.submit 'Save', :class => "btn"
.ui-box.width-100p.append-bottom-20
%h3 Password
= form_for @user, :url => profile_password_path, :method => :put do |f|
%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
.alert-message.block-message.error
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
.form-row
.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
.buttons
= f.submit 'Save', :class => "grey-button"
.clear
.input= f.password_field :password_confirmation
.actions
= f.submit 'Save', :class => "btn"
.ui-box.width-100p
%h3
%h3
Private token
%em.cred.right
%span.cred.right
keep it in secret!
= form_for @user, :url => profile_reset_private_token_path, :method => :put do |f|
%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.
......@@ -36,9 +34,9 @@
= text_field_tag "token", current_user.private_token
- else
You don`t have one yet. Click generate to fix it.
.buttons
.actions
- if current_user.private_token
= f.submit 'Reset', :confirm => "Are you sure?", :class => "grey-button"
= f.submit 'Reset', :confirm => "Are you sure?", :class => "btn"
- else
= f.submit 'Generate', :class => "positive-button"
= f.submit 'Generate', :class => "btn"
.ui-box.width-100p
%h3= @user.name
= form_for @user, :url => profile_update_path, :method => :put do |f|
.data
.left
.media-grid
= link_to "#" do
= image_tag gravatar_icon(@user.email, 90), :class => "thumbnail"
%h3.media_h= @user.name
%hr
= form_for @user, :url => profile_update_path, :method => :put do |f|
-if @user.errors.any?
#error_explanation
%div.alert-message.block-message.error
%ul
- @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 :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
.input= f.text_field :twitter
.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"
.actions
= f.submit 'Save', :class => "primary btn"
- 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
&rarr;
%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
- @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
.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
&rarr;
%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
Project wall
&ndash;
= 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
&ndash;
= image_tag gravatar_icon(update.author_email), :class => "", :width => 16
= truncate dashboard_feed_title(update), :length => 50
= 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
.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
.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?
%tr
%td
.left= f.label :code
%cite.right= "http://#{GIT_HOST["host"]}/"
%td= f.text_field :code, :placeholder => "example"
.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;")
.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 &amp; repository. Please wait for few minutes
- else
%h3.prepend-top Updating project &amp; repository. Please wait for few minutes
.clearfix
= f.label :issues_enabled, "Issues"
.input= f.check_box :issues_enabled
.merge-tabs
= f.submit 'Save', :class => "grey-button"
&nbsp;
- unless @project.new_record?
.right
= link_to 'Remove', @project, :confirm => 'Are you sure?', :method => :delete, :class => "red-button"
.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
:javascript
$(function(){
$('.new_project, .edit_project').bind('ajax:before', function() {
$(this).find(".form_content").hide();
$('.ajax_loader').show();
});
.clearfix
= f.label :wiki_enabled, "Wiki"
.input= f.check_box :wiki_enabled
taggifyForm();
.clearfix
= f.label :description
.input= f.text_area :description, :placeholder => "project description", :class => "xlarge", :rows => 4
$('form #project_default_branch').chosen();
})
%br
.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 => "btn danger"
.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
%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
= 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
%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
%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(); });
- @projects.in_groups_of(3, false) do |projects|
.row
- projects.each_with_index do |project, i|
%div.grid_1.projects_selector
%div{ :class => "project-box ui-box ui-box-big" }
%div.project_tile
.title
= link_to project_path(project) do
%h3= truncate(project.name, :length => 20)
%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
......@@ -4,3 +4,4 @@
- else
:plain
$("#new_project").replaceWith("#{escape_javascript(render('form'))}");
$('.ajax_loader').hide();
= 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"
&nbsp;
- 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 &amp; repository. Please wait for few minutes
%h3.prepend-top Saving project &amp; repository. Please wait...
:javascript
$('.edit_project').bind('ajax:before', function() {
$(".edit_project").hide();
$('.ajax_loader').show();
$(function(){
$("#project_name").live("change", function(){
var slug = slugify($(this).val());
$("#project_code").val(slug);
$("#project_path").val(slug);
});
});
:javascript
function slugify(text) {
return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase();
}
$(function(){
$('#project_default_branch').chosen();
$('.edit_project').live('ajax:before', function() {
$(this).hide();
$('.ajax_loader').show();
});
$('form #project_default_branch').chosen();
})
- if current_user.require_ssh_key?
%ul.errors_holder
%li You have no ssh keys added yo tour profile.
.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 &rarr; keys and add public key of every machine you want to use for work with gitlabhq.
%ul.alert_holder
.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.
......@@ -14,7 +15,7 @@
%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
......
= render "project_head"
- unless @notes.empty?
%div.update-data.ui-box.ui-box-small
.data
%table.zebra-striped.borders
- @notes.each do |note|
%a.update-item{:href => note.attachment.url}
%tr
%td
%a{:href => note.attachment.url}
= image_tag gravatar_icon(note.author_email), :class => "left", :width => 16
%span.update-title{:style => "margin-bottom:0px;"}
&nbsp;
= note.attachment_identifier
%span.update-author.right
%td
Added
= time_ago_in_words(note.created_at)
ago
......
.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}};
......
- 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
%h3
Projects
%div.clear
- unless @projects.empty?
%div{:class => "tile"}
= render "tile"
%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"
-# 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);
Pager.init(#{@limit});
});
- else
%center.prepend-top
%h2
%cite Nothing here
- else
%h2 Nothing here
:plain
ProjectsList.append(#{@projects.count}, "#{escape_javascript(render(:partial => 'projects/tile'))}");
Pager.append(#{@projects.count}, "#{escape_javascript(render(:partial => 'projects/tile'))}");
= 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
- 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 &amp; 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();
})
- 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
&larr; 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);
= 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}
- 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();
%div.wall_page
= render "notes/notes"
.loading{ :style => "display:none;"}
%center= image_tag "ajax-loader.gif"
= render "notes/notes", :tid => nil, :tt => "wall"
= 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();
- 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
#tree-breadcrumbs
%div
%ul.breadcrumb
%li
%span.arrow
= link_to tree_project_ref_path(@project, @ref, :path => nil), :remote => true do
= @project.code
= @project.name
- tree.breadcrumbs(6) do |link|
\/
= link
&nbsp;
%span.tree_progress
%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');
......
:css
.view_file
.view_file_header
%strong
%span.file_icon= image_tag "txt.png"
%span.mode_text= file.mode
%span.file_name= name
.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;"
%br/
- if file.text?
.view_file_content
- unless file.empty?
......
......@@ -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"
%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
......
%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"
= 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
%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
.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"
= 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
- content_for(:body_class, "project-page dashboard")
= render "head"
= render "branches_head"
#news-feed.news-feed
.project-box.project-updates
%table.zebra-striped.borders
- @activities.each do |update|
= render "repositories/feed", :update => update, :project => @project
= render "repositories/branch", :branch => update.head
= render "head"
= render "commits/head"
- unless @tags.empty?
%div.update-data.ui-box.ui-box-small
.data
%table.zebra-striped.borders
- @tags.each do |tag|
%a.update-item{:href => project_commits_path(@project, :ref => tag.name)}
%span.update-title{:style => "margin-bottom:0px;"}
= tag.name
%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
&nbsp;
%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
%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
.alert-message.block-message.error
%ul
- @snippet.errors.full_messages.each do |msg|
%span= msg
%br
%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}
.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"
%br
%br
= f.text_area :content
= 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}"
......
%a.update-item{:href => project_snippet_path(snippet.project, snippet)}
= image_tag gravatar_icon(snippet.author_email), :class => "left", :width => 40
%span.update-title
%tr
%td
%a{:href => project_snippet_path(snippet.project, snippet)}
= 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
%span.right.cgray
= snippet.file_name
= render "projects/project_head"
= render "snippets/form"
= render "projects/project_head"
- 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
- 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?
%table.zebra-striped.borders= render @snippets.fresh
= render "projects/project_head"
= render "snippets/form"
%div
%span.entity-info
= 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_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")
= 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"
- 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)
%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
.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" })
.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"
.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"
: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();
- 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
- 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();
- 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
= image_tag gravatar_icon(user.email), :class => "left", :width => 40, :style => "padding-right:5px;"
%span.commit-title
%strong
.media-grid
= link_to "#" do
= image_tag gravatar_icon(user.email, 60), :class => "thumbnail", :width => 60
%h3.media_h
= user.name
%span.commit-author
%strong
= user.email
%hr
%br
%small= user.email
.back_link
= link_to team_project_path(@project), :class => "" do
&larr; To team list
%table.no-borders
%br
%table.zebra-striped.borders
%tr
%td Name
%td= user.name
......@@ -31,17 +27,13 @@
%td= @team_member.created_at.stamp("Aug 21, 2011")
%tr
%td Project Access
%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
Project Access
(#{link_to "read more", help_permissions_path, :class => "vlink"})
%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
= f.select :project_access, options_for_select(Project.access_options, @team_member.project_access), {}, :class => "project-access-select", :disabled => !allow_admin
- unless user.skype.empty?
%tr
......@@ -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(){
......
- 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 »
- 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
= 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"
%h3 Editing page
%hr
= render 'form'
%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
%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
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
......@@ -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.
......
......@@ -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
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
......@@ -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.
......
Resque.watch_queue(PostReceive.instance_variable_get("@queue"))
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
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
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
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
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
class AddSlugToWiki < ActiveRecord::Migration
def change
add_column :wikis, :slug, :string
end
end
class AddWikiEnabledToProject < ActiveRecord::Migration
def change
add_column :projects, :wiki_enabled, :boolean, :default => true, :null => false
end
end
class AddUserToWiki < ActiveRecord::Migration
def change
add_column :wikis, :user_id, :integer
end
end
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
class AddActionToEvent < ActiveRecord::Migration
def change
add_column :events, :action, :integer, :null => true
end
end
......@@ -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|
......@@ -89,6 +88,17 @@ ActiveRecord::Schema.define(:version => 20120121122616) do
t.string "code"
t.integer "owner_id"
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
......@@ -64,19 +64,7 @@ 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
......@@ -89,6 +77,14 @@ module Gitlabhq
conf = ga_repo.config
projects.each do |project|
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)
......@@ -99,15 +95,25 @@ module Gitlabhq
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?
conf.add_repo(repo, true)
end
repo.add_permission("RW+", "", name_masters) unless name_masters.blank?
ga_repo.save
repo
end
end
end
......@@ -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
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
......@@ -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)$/
......
......@@ -2,22 +2,12 @@
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<style type="text/css">
body { background-color: #EAEAEA; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 600px;
padding: 0 4em;
margin: 4em auto 0 auto;
}
h1 { font-size: 48px; color: #444; line-height: 1.5em; }
h2 { font-size: 24px; color: #666; line-height: 1.5em; }
</style>
<link href="static.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<!-- This file lives in public/404.html -->
<div class="dialog">
<h1>404</h1>
<div class="alert-message block-message error">
<h2>The page you were looking for doesn't exist.</h2>
<p>You may have mistyped the address or the page may have moved.</p>
</div>
......
......@@ -2,22 +2,13 @@
<html>
<head>
<title>The change you wanted was rejected (422)</title>
<style type="text/css">
body { background-color: #EAEAEA; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 600px;
padding: 0 4em;
margin: 4em auto 0 auto;
}
h1 { font-size: 48px; color: #444; line-height: 1.5em; }
h2 { font-size: 24px; color: #666; line-height: 1.5em; }
</style>
<link href="static.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<!-- This file lives in public/422.html -->
<div class="dialog">
<h1>422</h1>
<div class="alert-message block-message error">
<h2>The change you wanted was rejected.</h2>
<p>Maybe you tried to change something you didn't have access to.</p>
</div>
......
......@@ -2,22 +2,13 @@
<html>
<head>
<title>We're sorry, but something went wrong (500)</title>
<style type="text/css">
body { background-color: #EAEAEA; color: #666; text-align: center; font-family: arial, sans-serif; }
div.dialog {
width: 600px;
padding: 0 4em;
margin: 4em auto 0 auto;
}
h1 { font-size: 48px; color: #444; line-height: 1.5em; }
h2 { font-size: 24px; color: #666; line-height: 1.5em; }
</style>
<link href="static.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<!-- This file lives in public/500.html -->
<div class="dialog">
<h1>500</h1>
<div class="alert-message block-message error">
<h2>We're sorry, but something went wrong.</h2>
<p>We've been notified about this issue and we'll take a look at it shortly.</p>
</div>
......
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;
}
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
bundle exec rake environment resque:work QUEUE=* VVERBOSE=1
......@@ -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
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
# == 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
......@@ -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 }
......
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
......@@ -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 }
......
......@@ -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 }
......@@ -300,5 +201,9 @@ end
# 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
#
# == 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
......@@ -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
#
......@@ -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
......@@ -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
......@@ -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 }
......
......@@ -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
......@@ -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
......
......@@ -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
require 'spec_helper'
__END__
# Disabled for now
describe "Dashboard" do
before do
@project = Factory :project
......
......@@ -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'
......
......@@ -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
......
......@@ -42,12 +42,10 @@ 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
end
end
end
describe "GET /merge_requests/new" do
before do
......
......@@ -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
......
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -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
......
......@@ -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
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
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
......@@ -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
......
......@@ -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
/* =========================================================
* 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 = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)
if ( this.settings.backdrop != 'static' ) {
this.$backdrop.click($.proxy(this.hide, this))
}
if ( doAnimate ) {
this.$backdrop[0].offsetWidth // force reflow
}
this.$backdrop.addClass('in')
doAnimate ?
this.$backdrop.one(transitionEnd, callback) :
callback()
} else if ( !this.isShown && this.$backdrop ) {
this.$backdrop.removeClass('in')
$.support.transition && this.$element.hasClass('fade')?
this.$backdrop.one(transitionEnd, $.proxy(removeBackdrop, this)) :
removeBackdrop.call(this)
} else if ( callback ) {
callback()
}
}
function removeBackdrop() {
this.$backdrop.remove()
this.$backdrop = null
}
function escape() {
var that = this
if ( this.isShown && this.settings.keyboard ) {
$(document).bind('keyup.modal', function ( e ) {
if ( e.which == 27 ) {
that.hide()
}
})
} else if ( !this.isShown ) {
$(document).unbind('keyup.modal')
}
}
/* MODAL PLUGIN DEFINITION
* ======================= */
$.fn.modal = function ( options ) {
var modal = this.data('modal')
if (!modal) {
if (typeof options == 'string') {
options = {
show: /show|toggle/.test(options)
}
}
return this.each(function () {
$(this).data('modal', new Modal(this, options))
})
}
if ( options === true ) {
return modal
}
if ( typeof options == 'string' ) {
modal[options]()
} else if ( modal ) {
modal.toggle()
}
return this
}
$.fn.modal.Modal = Modal
$.fn.modal.defaults = {
backdrop: false
, keyboard: false
, show: false
}
/* MODAL DATA- IMPLEMENTATION
* ========================== */
$(document).ready(function () {
$('body').delegate('[data-controls-modal]', 'click', function (e) {
e.preventDefault()
var $this = $(this).data('show', true)
$('#' + $this.attr('data-controls-modal')).modal( $this.data() )
})
})
}( window.jQuery || window.ender );
/* ===========================================================
* bootstrap-popover.js v1.4.0
* http://twitter.github.com/bootstrap/javascript.html#popover
* ===========================================================
* 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"
var Popover = function ( element, options ) {
this.$element = $(element)
this.options = options
this.enabled = true
this.fixTitle()
}
/* NOTE: POPOVER EXTENDS BOOTSTRAP-TWIPSY.js
========================================= */
Popover.prototype = $.extend({}, $.fn.twipsy.Twipsy.prototype, {
setContent: function () {
var $tip = this.tip()
$tip.find('.title')[this.options.html ? 'html' : 'text'](this.getTitle())
$tip.find('.content p')[this.options.html ? 'html' : 'text'](this.getContent())
$tip[0].className = 'popover'
}
, hasContent: function () {
return this.getTitle() || this.getContent()
}
, getContent: function () {
var content
, $e = this.$element
, o = this.options
if (typeof this.options.content == 'string') {
content = this.options.content
} else if (typeof this.options.content == 'function') {
content = this.options.content.call(this.$element[0])
}
return content
}
, tip: function() {
if (!this.$tip) {
this.$tip = $('<div class="popover" />')
.html(this.options.template)
}
return this.$tip
}
})
/* POPOVER PLUGIN DEFINITION
* ======================= */
$.fn.popover = function (options) {
if (typeof options == 'object') options = $.extend({}, $.fn.popover.defaults, options)
$.fn.twipsy.initWith.call(this, options, Popover, 'popover')
return this
}
$.fn.popover.defaults = $.extend({} , $.fn.twipsy.defaults, {
placement: 'right'
, template: '<div class="arrow"></div><div class="inner"><h3 class="title"></h3><div class="content"><p></p></div></div>'
})
}( window.jQuery || window.ender );
\ No newline at end of file
/**
* Endless Scroll plugin for jQuery
*
* v1.4.8
*
* Copyright (c) 2008 Fred Wu
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*/
/**
* Usage:
*
* // using default options
* $(document).endlessScroll();
*
* // using some custom options
* $(document).endlessScroll({
* fireOnce: false,
* fireDelay: false,
* loader: "<div class=\"loading\"><div>",
* callback: function(){
* alert("test");
* }
* });
*
* Configuration options:
*
* bottomPixels integer the number of pixels from the bottom of the page that triggers the event
* fireOnce boolean only fire once until the execution of the current event is completed
* fireDelay integer delay the subsequent firing, in milliseconds, 0 or false to disable delay
* loader string the HTML to be displayed during loading
* data string|function plain HTML data, can be either a string or a function that returns a string,
* when passed as a function it accepts one argument: fire sequence (the number
* of times the event triggered during the current page session)
* insertAfter string jQuery selector syntax: where to put the loader as well as the plain HTML data
* callback function callback function, accepts one argument: fire sequence (the number of times
* the event triggered during the current page session)
* resetCounter function resets the fire sequence counter if the function returns true, this function
* could also perform hook actions since it is applied at the start of the event
* ceaseFire function stops the event (no more endless scrolling) if the function returns true
*
* Usage tips:
*
* The plugin is more useful when used with the callback function, which can then make AJAX calls to retrieve content.
* The fire sequence argument (for the callback function) is useful for 'pagination'-like features.
*/
(function($){
$.fn.endlessScroll = function(options) {
var defaults = {
bottomPixels : 50,
fireOnce : true,
fireDelay : 150,
loader : "<br />Loading...<br />",
data : "",
insertAfter : "div:last",
resetCounter : function() { return false; },
callback : function() { return true; },
ceaseFire : function() { return false; }
};
var options = $.extend({}, defaults, options),
firing = true,
fired = false,
fireSequence = 0,
is_scrollable;
if (options.ceaseFire.apply(this) === true)
firing = false;
if (firing === true) {
$(this).scroll(function() {
if (options.ceaseFire.apply(this) === true) {
firing = false;
return; // Scroll will still get called, but nothing will happen
}
if (this == document || this == window) {
is_scrollable = $(document).height() - $(window).height() <= $(window).scrollTop() + options.bottomPixels;
} else {
// calculates the actual height of the scrolling container
var inner_wrap = $(".endless_scroll_inner_wrap", this);
if (inner_wrap.length == 0)
inner_wrap = $(this).wrapInner("<div class=\"endless_scroll_inner_wrap\" />").find(".endless_scroll_inner_wrap");
is_scrollable = inner_wrap.length > 0 &&
(inner_wrap.height() - $(this).height() <= $(this).scrollTop() + options.bottomPixels);
}
if (is_scrollable && (options.fireOnce == false || (options.fireOnce == true && fired != true))) {
if (options.resetCounter.apply(this) === true) fireSequence = 0;
fired = true;
fireSequence++;
$(options.insertAfter).after("<div id=\"endless_scroll_loader\">" + options.loader + "</div>");
data = typeof options.data == 'function' ? options.data.apply(this, [fireSequence]) : options.data;
if (data !== false) {
$(options.insertAfter).after("<div id=\"endless_scroll_data\">" + data + "</div>");
$("#endless_scroll_data").hide().fadeIn(250, function() {$(this).removeAttr("id");});
options.callback.apply(this, [fireSequence]);
if (options.fireDelay !== false || options.fireDelay !== 0) {
$("body").after("<div id=\"endless_scroll_marker\"></div>");
// slight delay for preventing event firing twice
$("#endless_scroll_marker").fadeTo(options.fireDelay, 1, function() {
$(this).remove();
fired = false;
});
}
else
fired = false;
}
$("#endless_scroll_loader").remove();
}
});
}
};
})(jQuery);
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment