master merged
This commit is contained in:
commit
e6ce47291b
30
CONTRIBUTING.md
Normal file
30
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
## Contribute to GitLab
|
||||||
|
|
||||||
|
If you want to contribute to GitLab, follow this process:
|
||||||
|
|
||||||
|
1. Fork the project
|
||||||
|
2. Create a feature branch
|
||||||
|
3. Code
|
||||||
|
4. Create a pull request
|
||||||
|
|
||||||
|
We only accept pull requests if:
|
||||||
|
|
||||||
|
* Your code has proper tests and all tests pass
|
||||||
|
* Your code can be merged w/o problems
|
||||||
|
* It wont broke existing functionality
|
||||||
|
* Its a quality code
|
||||||
|
* We like it :)
|
||||||
|
|
||||||
|
## [You may need a developer VM](https://github.com/gitlabhq/developer-vm)
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
To run the specs for GitLab, you need to run seeds for test db.
|
||||||
|
|
||||||
|
cd gitlabhq
|
||||||
|
rake db:seed_fu RAILS_ENV=test
|
||||||
|
|
||||||
|
Then you can run the test suite with rake:
|
||||||
|
|
||||||
|
rake gitlab:test
|
||||||
|
|
25
Gemfile
25
Gemfile
|
@ -1,5 +1,13 @@
|
||||||
source "http://rubygems.org"
|
source "http://rubygems.org"
|
||||||
|
|
||||||
|
def darwin_only(require_as)
|
||||||
|
RUBY_PLATFORM.include?('darwin') && require_as
|
||||||
|
end
|
||||||
|
|
||||||
|
def linux_only(require_as)
|
||||||
|
RUBY_PLATFORM.include?('linux') && require_as
|
||||||
|
end
|
||||||
|
|
||||||
gem "rails", "3.2.8"
|
gem "rails", "3.2.8"
|
||||||
|
|
||||||
# Supported DBs
|
# Supported DBs
|
||||||
|
@ -8,6 +16,10 @@ gem "mysql2"
|
||||||
|
|
||||||
# Auth
|
# Auth
|
||||||
gem "devise", "~> 2.1.0"
|
gem "devise", "~> 2.1.0"
|
||||||
|
gem 'omniauth'
|
||||||
|
gem 'omniauth-google-oauth2'
|
||||||
|
gem 'omniauth-twitter'
|
||||||
|
gem 'omniauth-github'
|
||||||
|
|
||||||
# GITLAB patched libs
|
# GITLAB patched libs
|
||||||
gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
|
gem "grit", :git => "https://github.com/gitlabhq/grit.git", :ref => "7f35cb98ff17d534a07e3ce6ec3d580f67402837"
|
||||||
|
@ -98,21 +110,28 @@ group :development do
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
|
gem 'spinach-rails'
|
||||||
gem "rspec-rails"
|
gem "rspec-rails"
|
||||||
gem "capybara"
|
gem "capybara"
|
||||||
gem "capybara-webkit"
|
gem "capybara-webkit"
|
||||||
gem "headless"
|
gem "headless"
|
||||||
gem "autotest"
|
|
||||||
gem "autotest-rails"
|
|
||||||
gem "pry"
|
gem "pry"
|
||||||
gem "awesome_print"
|
gem "awesome_print"
|
||||||
gem "database_cleaner"
|
gem "database_cleaner"
|
||||||
gem "launchy"
|
gem "launchy"
|
||||||
gem 'factory_girl_rails'
|
gem 'factory_girl_rails'
|
||||||
|
|
||||||
|
# Guard
|
||||||
|
gem 'guard-rspec'
|
||||||
|
gem 'guard-spinach'
|
||||||
|
|
||||||
|
# Notification
|
||||||
|
gem 'rb-fsevent', :require => darwin_only('rb-fsevent')
|
||||||
|
gem 'growl', :require => darwin_only('growl')
|
||||||
|
gem 'rb-inotify', :require => linux_only('rb-inotify')
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'cucumber-rails', :require => false
|
|
||||||
gem "simplecov", :require => false
|
gem "simplecov", :require => false
|
||||||
gem "shoulda-matchers"
|
gem "shoulda-matchers"
|
||||||
gem 'email_spec'
|
gem 'email_spec'
|
||||||
|
|
79
Gemfile.lock
79
Gemfile.lock
|
@ -68,7 +68,6 @@ GIT
|
||||||
GEM
|
GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
ZenTest (4.8.1)
|
|
||||||
actionmailer (3.2.8)
|
actionmailer (3.2.8)
|
||||||
actionpack (= 3.2.8)
|
actionpack (= 3.2.8)
|
||||||
mail (~> 2.4.4)
|
mail (~> 2.4.4)
|
||||||
|
@ -100,10 +99,6 @@ GEM
|
||||||
rails (~> 3.0)
|
rails (~> 3.0)
|
||||||
addressable (2.2.8)
|
addressable (2.2.8)
|
||||||
arel (3.0.2)
|
arel (3.0.2)
|
||||||
autotest (4.4.6)
|
|
||||||
ZenTest (>= 4.4.1)
|
|
||||||
autotest-rails (4.1.2)
|
|
||||||
ZenTest (~> 4.5)
|
|
||||||
awesome_print (1.0.2)
|
awesome_print (1.0.2)
|
||||||
bcrypt-ruby (3.0.1)
|
bcrypt-ruby (3.0.1)
|
||||||
blankslate (2.1.2.4)
|
blankslate (2.1.2.4)
|
||||||
|
@ -137,16 +132,8 @@ GEM
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.3.3)
|
coffee-script-source (1.3.3)
|
||||||
colored (1.2)
|
colored (1.2)
|
||||||
|
colorize (0.5.8)
|
||||||
crack (0.3.1)
|
crack (0.3.1)
|
||||||
cucumber (1.2.1)
|
|
||||||
builder (>= 2.1.2)
|
|
||||||
diff-lcs (>= 1.1.3)
|
|
||||||
gherkin (~> 2.11.0)
|
|
||||||
json (>= 1.4.6)
|
|
||||||
cucumber-rails (1.3.0)
|
|
||||||
capybara (>= 1.1.2)
|
|
||||||
cucumber (>= 1.1.8)
|
|
||||||
nokogiri (>= 1.5.0)
|
|
||||||
daemons (1.1.8)
|
daemons (1.1.8)
|
||||||
database_cleaner (0.8.0)
|
database_cleaner (0.8.0)
|
||||||
devise (2.1.2)
|
devise (2.1.2)
|
||||||
|
@ -171,12 +158,13 @@ GEM
|
||||||
factory_girl_rails (4.0.0)
|
factory_girl_rails (4.0.0)
|
||||||
factory_girl (~> 4.0.0)
|
factory_girl (~> 4.0.0)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
|
faraday (0.8.4)
|
||||||
|
multipart-post (~> 1.1)
|
||||||
ffaker (1.14.0)
|
ffaker (1.14.0)
|
||||||
ffi (1.0.11)
|
ffi (1.0.11)
|
||||||
foreman (0.47.0)
|
foreman (0.47.0)
|
||||||
thor (>= 0.13.6)
|
thor (>= 0.13.6)
|
||||||
gherkin (2.11.0)
|
gherkin-ruby (0.2.1)
|
||||||
json (>= 1.4.6)
|
|
||||||
git (1.2.5)
|
git (1.2.5)
|
||||||
github-markup (0.7.4)
|
github-markup (0.7.4)
|
||||||
gitlab_meta (2.9)
|
gitlab_meta (2.9)
|
||||||
|
@ -186,6 +174,15 @@ GEM
|
||||||
multi_xml
|
multi_xml
|
||||||
rack
|
rack
|
||||||
rack-mount
|
rack-mount
|
||||||
|
growl (1.0.3)
|
||||||
|
guard (1.3.2)
|
||||||
|
listen (>= 0.4.2)
|
||||||
|
thor (>= 0.14.6)
|
||||||
|
guard-rspec (1.2.1)
|
||||||
|
guard (>= 1.1)
|
||||||
|
guard-spinach (0.0.2)
|
||||||
|
guard (>= 1.1)
|
||||||
|
spinach
|
||||||
haml (3.1.6)
|
haml (3.1.6)
|
||||||
haml-rails (0.3.4)
|
haml-rails (0.3.4)
|
||||||
actionpack (~> 3.0)
|
actionpack (~> 3.0)
|
||||||
|
@ -199,6 +196,7 @@ GEM
|
||||||
httparty (0.8.3)
|
httparty (0.8.3)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
multi_xml
|
multi_xml
|
||||||
|
httpauth (0.1)
|
||||||
i18n (0.6.1)
|
i18n (0.6.1)
|
||||||
journey (1.0.4)
|
journey (1.0.4)
|
||||||
jquery-rails (2.0.2)
|
jquery-rails (2.0.2)
|
||||||
|
@ -208,6 +206,8 @@ GEM
|
||||||
jquery-rails
|
jquery-rails
|
||||||
railties (>= 3.1.0)
|
railties (>= 3.1.0)
|
||||||
json (1.7.5)
|
json (1.7.5)
|
||||||
|
jwt (0.1.5)
|
||||||
|
multi_json (>= 1.0)
|
||||||
kaminari (0.14.0)
|
kaminari (0.14.0)
|
||||||
actionpack (>= 3.0.0)
|
actionpack (>= 3.0.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
|
@ -219,6 +219,7 @@ GEM
|
||||||
libv8 (3.3.10.4)
|
libv8 (3.3.10.4)
|
||||||
libwebsocket (0.1.3)
|
libwebsocket (0.1.3)
|
||||||
addressable
|
addressable
|
||||||
|
listen (0.5.0)
|
||||||
mail (2.4.4)
|
mail (2.4.4)
|
||||||
i18n (>= 0.4.0)
|
i18n (>= 0.4.0)
|
||||||
mime-types (~> 1.16)
|
mime-types (~> 1.16)
|
||||||
|
@ -229,12 +230,35 @@ GEM
|
||||||
sprockets (~> 2.0)
|
sprockets (~> 2.0)
|
||||||
multi_json (1.3.6)
|
multi_json (1.3.6)
|
||||||
multi_xml (0.5.1)
|
multi_xml (0.5.1)
|
||||||
|
multipart-post (1.1.5)
|
||||||
mysql2 (0.3.11)
|
mysql2 (0.3.11)
|
||||||
net-ldap (0.2.2)
|
net-ldap (0.2.2)
|
||||||
nokogiri (1.5.3)
|
nokogiri (1.5.3)
|
||||||
|
oauth (0.4.7)
|
||||||
|
oauth2 (0.8.0)
|
||||||
|
faraday (~> 0.8)
|
||||||
|
httpauth (~> 0.1)
|
||||||
|
jwt (~> 0.1.4)
|
||||||
|
multi_json (~> 1.0)
|
||||||
|
rack (~> 1.2)
|
||||||
omniauth (1.1.0)
|
omniauth (1.1.0)
|
||||||
hashie (~> 1.2)
|
hashie (~> 1.2)
|
||||||
rack
|
rack
|
||||||
|
omniauth-github (1.0.3)
|
||||||
|
omniauth (~> 1.0)
|
||||||
|
omniauth-oauth2 (~> 1.1)
|
||||||
|
omniauth-google-oauth2 (0.1.13)
|
||||||
|
omniauth (~> 1.0)
|
||||||
|
omniauth-oauth2
|
||||||
|
omniauth-oauth (1.0.1)
|
||||||
|
oauth
|
||||||
|
omniauth (~> 1.0)
|
||||||
|
omniauth-oauth2 (1.1.0)
|
||||||
|
oauth2 (~> 0.8.0)
|
||||||
|
omniauth (~> 1.0)
|
||||||
|
omniauth-twitter (0.0.13)
|
||||||
|
multi_json (~> 1.3)
|
||||||
|
omniauth-oauth (~> 1.0)
|
||||||
orm_adapter (0.3.0)
|
orm_adapter (0.3.0)
|
||||||
polyglot (0.3.3)
|
polyglot (0.3.3)
|
||||||
posix-spawn (0.3.6)
|
posix-spawn (0.3.6)
|
||||||
|
@ -274,6 +298,9 @@ GEM
|
||||||
raindrops (0.9.0)
|
raindrops (0.9.0)
|
||||||
rake (0.9.2.2)
|
rake (0.9.2.2)
|
||||||
raphael-rails (1.5.2)
|
raphael-rails (1.5.2)
|
||||||
|
rb-fsevent (0.9.1)
|
||||||
|
rb-inotify (0.8.8)
|
||||||
|
ffi (>= 0.5.0)
|
||||||
rdoc (3.12)
|
rdoc (3.12)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
redcarpet (2.1.1)
|
redcarpet (2.1.1)
|
||||||
|
@ -336,6 +363,13 @@ GEM
|
||||||
tilt (~> 1.3, >= 1.3.3)
|
tilt (~> 1.3, >= 1.3.3)
|
||||||
six (0.2.0)
|
six (0.2.0)
|
||||||
slop (2.4.4)
|
slop (2.4.4)
|
||||||
|
spinach (0.5.2)
|
||||||
|
colorize
|
||||||
|
gherkin-ruby (~> 0.2.0)
|
||||||
|
spinach-rails (0.1.8)
|
||||||
|
capybara (~> 1)
|
||||||
|
railties (>= 3)
|
||||||
|
spinach (>= 0.4)
|
||||||
sprockets (2.1.3)
|
sprockets (2.1.3)
|
||||||
hike (~> 1.2)
|
hike (~> 1.2)
|
||||||
rack (~> 1.0)
|
rack (~> 1.0)
|
||||||
|
@ -378,8 +412,6 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
acts-as-taggable-on (= 2.3.1)
|
acts-as-taggable-on (= 2.3.1)
|
||||||
annotate!
|
annotate!
|
||||||
autotest
|
|
||||||
autotest-rails
|
|
||||||
awesome_print
|
awesome_print
|
||||||
bootstrap-sass (= 2.0.4)
|
bootstrap-sass (= 2.0.4)
|
||||||
capybara
|
capybara
|
||||||
|
@ -389,7 +421,6 @@ DEPENDENCIES
|
||||||
chosen-rails
|
chosen-rails
|
||||||
coffee-rails (= 3.2.2)
|
coffee-rails (= 3.2.2)
|
||||||
colored
|
colored
|
||||||
cucumber-rails
|
|
||||||
database_cleaner
|
database_cleaner
|
||||||
devise (~> 2.1.0)
|
devise (~> 2.1.0)
|
||||||
draper
|
draper
|
||||||
|
@ -404,6 +435,9 @@ DEPENDENCIES
|
||||||
grack!
|
grack!
|
||||||
grape (~> 0.2.1)
|
grape (~> 0.2.1)
|
||||||
grit!
|
grit!
|
||||||
|
growl
|
||||||
|
guard-rspec
|
||||||
|
guard-spinach
|
||||||
haml-rails
|
haml-rails
|
||||||
headless
|
headless
|
||||||
httparty
|
httparty
|
||||||
|
@ -415,12 +449,18 @@ DEPENDENCIES
|
||||||
linguist (~> 1.0.0)!
|
linguist (~> 1.0.0)!
|
||||||
modernizr (= 2.5.3)
|
modernizr (= 2.5.3)
|
||||||
mysql2
|
mysql2
|
||||||
|
omniauth
|
||||||
|
omniauth-github
|
||||||
|
omniauth-google-oauth2
|
||||||
omniauth-ldap!
|
omniauth-ldap!
|
||||||
|
omniauth-twitter
|
||||||
pry
|
pry
|
||||||
pygments.rb!
|
pygments.rb!
|
||||||
rack-mini-profiler
|
rack-mini-profiler
|
||||||
rails (= 3.2.8)
|
rails (= 3.2.8)
|
||||||
raphael-rails (= 1.5.2)
|
raphael-rails (= 1.5.2)
|
||||||
|
rb-fsevent
|
||||||
|
rb-inotify
|
||||||
redcarpet (~> 2.1.1)
|
redcarpet (~> 2.1.1)
|
||||||
resque (~> 1.20.0)
|
resque (~> 1.20.0)
|
||||||
resque_mailer
|
resque_mailer
|
||||||
|
@ -432,6 +472,7 @@ DEPENDENCIES
|
||||||
shoulda-matchers
|
shoulda-matchers
|
||||||
simplecov
|
simplecov
|
||||||
six
|
six
|
||||||
|
spinach-rails
|
||||||
sqlite3
|
sqlite3
|
||||||
stamp
|
stamp
|
||||||
test_after_commit
|
test_after_commit
|
||||||
|
|
26
Guardfile
Normal file
26
Guardfile
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# A sample Guardfile
|
||||||
|
# More info at https://github.com/guard/guard#readme
|
||||||
|
|
||||||
|
guard 'rspec', :version => 2, :all_on_start => false, :all_after_pass => false do
|
||||||
|
watch(%r{^spec/.+_spec\.rb$})
|
||||||
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
||||||
|
watch('spec/spec_helper.rb') { "spec" }
|
||||||
|
|
||||||
|
# Rails example
|
||||||
|
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
||||||
|
watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
||||||
|
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
||||||
|
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
||||||
|
watch('config/routes.rb') { "spec/routing" }
|
||||||
|
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
||||||
|
|
||||||
|
# Capybara request specs
|
||||||
|
watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
|
||||||
|
end
|
||||||
|
|
||||||
|
guard 'spinach' do
|
||||||
|
watch(%r|^features/(.*)\.feature|)
|
||||||
|
watch(%r|^features/steps/(.*)([^/]+)\.rb|) do |m|
|
||||||
|
"features/#{m[1]}#{m[2]}.feature"
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,3 +6,7 @@ $ ->
|
||||||
elems.val('').attr 'disabled', true
|
elems.val('').attr 'disabled', true
|
||||||
else
|
else
|
||||||
elems.removeAttr 'disabled'
|
elems.removeAttr 'disabled'
|
||||||
|
|
||||||
|
$('.log-tabs a').click (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
$(this).tab('show')
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
//= require jquery.endless-scroll
|
//= require jquery.endless-scroll
|
||||||
//= require jquery.highlight
|
//= require jquery.highlight
|
||||||
//= require jquery.waitforimages
|
//= require jquery.waitforimages
|
||||||
//= require bootstrap-modal
|
//= require bootstrap
|
||||||
//= require modernizr
|
//= require modernizr
|
||||||
//= require chosen-jquery
|
//= require chosen-jquery
|
||||||
//= require raphael
|
//= require raphael
|
||||||
|
|
|
@ -24,6 +24,9 @@ $ ->
|
||||||
# Click a .one_click_select field, select the contents
|
# Click a .one_click_select field, select the contents
|
||||||
$(".one_click_select").live 'click', -> $(this).select()
|
$(".one_click_select").live 'click', -> $(this).select()
|
||||||
|
|
||||||
|
# Initialize chosen selects
|
||||||
|
$('select.chosen').chosen()
|
||||||
|
|
||||||
# Disable form buttons while a form is submitting
|
# Disable form buttons while a form is submitting
|
||||||
$('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
|
$('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->
|
||||||
buttons = $('[type="submit"]', this)
|
buttons = $('[type="submit"]', this)
|
||||||
|
|
|
@ -1,182 +0,0 @@
|
||||||
var NoteList = {
|
|
||||||
|
|
||||||
notes_path: null,
|
|
||||||
target_params: null,
|
|
||||||
target_id: 0,
|
|
||||||
target_type: null,
|
|
||||||
first_id: 0,
|
|
||||||
last_id: 0,
|
|
||||||
disable:false,
|
|
||||||
|
|
||||||
init:
|
|
||||||
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();
|
|
||||||
|
|
||||||
$('.delete-note').live('ajax:success', function() {
|
|
||||||
$(this).closest('li').fadeOut(); });
|
|
||||||
|
|
||||||
$(".note-form-holder").live("ajax:before", function(){
|
|
||||||
$(".submit_note").disable()
|
|
||||||
})
|
|
||||||
|
|
||||||
$(".note-form-holder").live("ajax:complete", function(){
|
|
||||||
$(".submit_note").enable()
|
|
||||||
})
|
|
||||||
|
|
||||||
disableButtonIfEmptyField(".note-text", ".submit_note");
|
|
||||||
|
|
||||||
$(".note-text").live("focus", function(){
|
|
||||||
$(this).css("height", "80px");
|
|
||||||
$('.note_advanced_opts').show();
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#note_attachment").change(function(e){
|
|
||||||
var val = $('.input-file').val();
|
|
||||||
var filename = val.replace(/^.*[\\\/]/, '');
|
|
||||||
$(".file_name").text(filename);
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(html) {
|
|
||||||
$("#new_notes_list").html(html);
|
|
||||||
},
|
|
||||||
|
|
||||||
prepend:
|
|
||||||
function(id, html) {
|
|
||||||
if(id != this.last_id) {
|
|
||||||
$("#new_notes_list").prepend(html);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getNew:
|
|
||||||
function() {
|
|
||||||
// refersh notes list
|
|
||||||
$.ajax({
|
|
||||||
type: "GET",
|
|
||||||
url: this.notes_path,
|
|
||||||
data: "last_id=" + this.last_id + this.target_params,
|
|
||||||
dataType: "script"});
|
|
||||||
},
|
|
||||||
|
|
||||||
refresh:
|
|
||||||
function() {
|
|
||||||
// refersh notes list
|
|
||||||
$.ajax({
|
|
||||||
type: "GET",
|
|
||||||
url: this.notes_path,
|
|
||||||
data: "first_id=" + this.first_id + "&last_id=" + this.last_id + this.target_params,
|
|
||||||
dataType: "script"});
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init load of notes:
|
|
||||||
* 1. Get content with ajax call
|
|
||||||
* 2. Set content of notes list with loaded one
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
getContent:
|
|
||||||
function() {
|
|
||||||
$.ajax({
|
|
||||||
type: "GET",
|
|
||||||
url: this.notes_path,
|
|
||||||
data: "?" + this.target_params,
|
|
||||||
complete: function(){ $('.status').removeClass("loading")},
|
|
||||||
beforeSend: function() { $('.status').addClass("loading") },
|
|
||||||
dataType: "script"});
|
|
||||||
},
|
|
||||||
|
|
||||||
setContent:
|
|
||||||
function(fid, lid, html) {
|
|
||||||
this.last_id = lid;
|
|
||||||
this.first_id = fid;
|
|
||||||
$("#notes-list").html(html);
|
|
||||||
|
|
||||||
// Init infinite scrolling
|
|
||||||
this.initLoadMore();
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Paging for old notes when scroll to bottom:
|
|
||||||
* 1. Init scroll events with 'initLoadMore'
|
|
||||||
* 2. Load onlder notes with 'getOld' method
|
|
||||||
* 3. append old notes to bottom of list with 'append'
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
getOld:
|
|
||||||
function() {
|
|
||||||
$('.loading').show();
|
|
||||||
$.ajax({
|
|
||||||
type: "GET",
|
|
||||||
url: this.notes_path,
|
|
||||||
data: "first_id=" + this.first_id + this.target_params,
|
|
||||||
complete: function(){ $('.status').removeClass("loading")},
|
|
||||||
beforeSend: function() { $('.status').addClass("loading") },
|
|
||||||
dataType: "script"});
|
|
||||||
},
|
|
||||||
|
|
||||||
append:
|
|
||||||
function(id, html) {
|
|
||||||
if(this.first_id == id) {
|
|
||||||
this.disable = true;
|
|
||||||
} else {
|
|
||||||
this.first_id = id;
|
|
||||||
$("#notes-list").append(html);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
initLoadMore:
|
|
||||||
function() {
|
|
||||||
$(document).endlessScroll({
|
|
||||||
bottomPixels: 400,
|
|
||||||
fireDelay: 1000,
|
|
||||||
fireOnce:true,
|
|
||||||
ceaseFire: function() {
|
|
||||||
return NoteList.disable;
|
|
||||||
},
|
|
||||||
callback: function(i) {
|
|
||||||
NoteList.getOld();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var PerLineNotes = {
|
|
||||||
init:
|
|
||||||
function() {
|
|
||||||
$(".line_note_link, .line_note_reply_link").live("click", function(e) {
|
|
||||||
var form = $(".per_line_form");
|
|
||||||
$(this).closest("tr").after(form);
|
|
||||||
form.find("#note_line_code").val($(this).attr("line_code"));
|
|
||||||
form.show();
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
|
|
||||||
}
|
|
||||||
}
|
|
293
app/assets/javascripts/notes.js
Normal file
293
app/assets/javascripts/notes.js
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
var NoteList = {
|
||||||
|
|
||||||
|
notes_path: null,
|
||||||
|
target_params: null,
|
||||||
|
target_id: 0,
|
||||||
|
target_type: null,
|
||||||
|
top_id: 0,
|
||||||
|
bottom_id: 0,
|
||||||
|
loading_more_disabled: false,
|
||||||
|
reversed: false,
|
||||||
|
|
||||||
|
init:
|
||||||
|
function(tid, tt, path) {
|
||||||
|
this.notes_path = path + ".js";
|
||||||
|
this.target_id = tid;
|
||||||
|
this.target_type = tt;
|
||||||
|
this.reversed = $("#notes-list").hasClass("reversed");
|
||||||
|
this.target_params = "&target_type=" + this.target_type + "&target_id=" + this.target_id;
|
||||||
|
|
||||||
|
// get initial set of notes
|
||||||
|
this.getContent();
|
||||||
|
|
||||||
|
$("#notes-list, #new-notes-list").on("ajax:success", ".delete-note", function() {
|
||||||
|
$(this).closest('li').fadeOut(function() {
|
||||||
|
$(this).remove();
|
||||||
|
NoteList.updateVotes();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".note-form-holder").on("ajax:before", function(){
|
||||||
|
$(".submit_note").disable();
|
||||||
|
})
|
||||||
|
|
||||||
|
$(".note-form-holder").on("ajax:complete", function(){
|
||||||
|
$(".submit_note").enable();
|
||||||
|
})
|
||||||
|
|
||||||
|
disableButtonIfEmptyField(".note-text", ".submit_note");
|
||||||
|
|
||||||
|
$("#note_attachment").change(function(e){
|
||||||
|
var val = $('.input-file').val();
|
||||||
|
var filename = val.replace(/^.*[\\\/]/, '');
|
||||||
|
$(".file_name").text(filename);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(this.reversed) {
|
||||||
|
var textarea = $(".note-text");
|
||||||
|
$('.note_advanced_opts').hide();
|
||||||
|
textarea.css("height", "40px");
|
||||||
|
textarea.on("focus", function(){
|
||||||
|
$(this).css("height", "80px");
|
||||||
|
$('.note_advanced_opts').show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle loading the initial set of notes.
|
||||||
|
* And set up loading more notes when scrolling to the bottom of the page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an inital set of notes.
|
||||||
|
*/
|
||||||
|
getContent:
|
||||||
|
function() {
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: this.notes_path,
|
||||||
|
data: "?" + this.target_params,
|
||||||
|
complete: function(){ $('.notes-status').removeClass("loading")},
|
||||||
|
beforeSend: function() { $('.notes-status').addClass("loading") },
|
||||||
|
dataType: "script"});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called in response to getContent().
|
||||||
|
* Replaces the content of #notes-list with the given html.
|
||||||
|
*/
|
||||||
|
setContent:
|
||||||
|
function(first_id, last_id, html) {
|
||||||
|
this.top_id = first_id;
|
||||||
|
this.bottom_id = last_id;
|
||||||
|
$("#notes-list").html(html);
|
||||||
|
|
||||||
|
// init infinite scrolling
|
||||||
|
this.initLoadMore();
|
||||||
|
|
||||||
|
// init getting new notes
|
||||||
|
if (this.reversed) {
|
||||||
|
this.initRefreshNew();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle loading more notes when scrolling to the bottom of the page.
|
||||||
|
* The id of the last note in the list is in this.bottom_id.
|
||||||
|
*
|
||||||
|
* Set up refreshing only new notes after all notes have been loaded.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes loading more notes when scrolling to the bottom of the page.
|
||||||
|
*/
|
||||||
|
initLoadMore:
|
||||||
|
function() {
|
||||||
|
$(document).endlessScroll({
|
||||||
|
bottomPixels: 400,
|
||||||
|
fireDelay: 1000,
|
||||||
|
fireOnce:true,
|
||||||
|
ceaseFire: function() {
|
||||||
|
return NoteList.loading_more_disabled;
|
||||||
|
},
|
||||||
|
callback: function(i) {
|
||||||
|
NoteList.getMore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an additional set of notes.
|
||||||
|
*/
|
||||||
|
getMore:
|
||||||
|
function() {
|
||||||
|
// only load more notes if there are no "new" notes
|
||||||
|
$('.loading').show();
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: this.notes_path,
|
||||||
|
data: "loading_more=1&" + (this.reversed ? "before_id" : "after_id") + "=" + this.bottom_id + this.target_params,
|
||||||
|
complete: function(){ $('.notes-status').removeClass("loading")},
|
||||||
|
beforeSend: function() { $('.notes-status').addClass("loading") },
|
||||||
|
dataType: "script"});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called in response to getMore().
|
||||||
|
* Append notes to #notes-list.
|
||||||
|
*/
|
||||||
|
appendMoreNotes:
|
||||||
|
function(id, html) {
|
||||||
|
if(id != this.bottom_id) {
|
||||||
|
this.bottom_id = id;
|
||||||
|
$("#notes-list").append(html);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called in response to getMore().
|
||||||
|
* Disables loading more notes when scrolling to the bottom of the page.
|
||||||
|
* Initalizes refreshing new notes.
|
||||||
|
*/
|
||||||
|
finishedLoadingMore:
|
||||||
|
function() {
|
||||||
|
this.loading_more_disabled = true;
|
||||||
|
|
||||||
|
// from now on only get new notes
|
||||||
|
if (!this.reversed) {
|
||||||
|
this.initRefreshNew();
|
||||||
|
}
|
||||||
|
// make sure we are up to date
|
||||||
|
this.updateVotes();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle refreshing and adding of new notes.
|
||||||
|
*
|
||||||
|
* New notes are all notes that are created after the site has been loaded.
|
||||||
|
* The "old" notes are in #notes-list the "new" ones will be in #new-notes-list.
|
||||||
|
* The id of the last "old" note is in this.bottom_id.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes getting new notes every n seconds.
|
||||||
|
*/
|
||||||
|
initRefreshNew:
|
||||||
|
function() {
|
||||||
|
setInterval("NoteList.getNew()", 10000);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the new set of notes.
|
||||||
|
*/
|
||||||
|
getNew:
|
||||||
|
function() {
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: this.notes_path,
|
||||||
|
data: "loading_new=1&after_id=" + (this.reversed ? this.top_id : this.bottom_id) + this.target_params,
|
||||||
|
dataType: "script"});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called in response to getNew().
|
||||||
|
* Replaces the content of #new-notes-list with the given html.
|
||||||
|
*/
|
||||||
|
replaceNewNotes:
|
||||||
|
function(html) {
|
||||||
|
$("#new-notes-list").html(html);
|
||||||
|
this.updateVotes();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a single note to #new-notes-list.
|
||||||
|
*/
|
||||||
|
appendNewNote:
|
||||||
|
function(id, html) {
|
||||||
|
if (this.reversed) {
|
||||||
|
$("#new-notes-list").prepend(html);
|
||||||
|
} else {
|
||||||
|
$("#new-notes-list").append(html);
|
||||||
|
}
|
||||||
|
this.updateVotes();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculates the votes and updates them (if they are displayed at all).
|
||||||
|
*
|
||||||
|
* Assumes all relevant notes are displayed (i.e. there are no more notes to
|
||||||
|
* load via getMore()).
|
||||||
|
* Might produce inaccurate results when not all notes have been loaded and a
|
||||||
|
* recalculation is triggered (e.g. when deleting a note).
|
||||||
|
*/
|
||||||
|
updateVotes:
|
||||||
|
function() {
|
||||||
|
var votes = $("#votes .votes");
|
||||||
|
var notes = $("#notes-list, #new-notes-list").find(".note.vote");
|
||||||
|
|
||||||
|
// only update if there is a vote display
|
||||||
|
if (votes.size()) {
|
||||||
|
var upvotes = notes.filter(".upvote").size();
|
||||||
|
var downvotes = notes.filter(".downvote").size();
|
||||||
|
var votesCount = upvotes + downvotes;
|
||||||
|
var upvotesPercent = votesCount ? (100.0 / votesCount * upvotes) : 0;
|
||||||
|
var downvotesPercent = votesCount ? (100.0 - upvotesPercent) : 0;
|
||||||
|
|
||||||
|
// change vote bar lengths
|
||||||
|
votes.find(".bar-success").css("width", upvotesPercent+"%");
|
||||||
|
votes.find(".bar-danger").css("width", downvotesPercent+"%");
|
||||||
|
// replace vote numbers
|
||||||
|
votes.find(".upvotes").text(votes.find(".upvotes").text().replace(/\d+/, upvotes));
|
||||||
|
votes.find(".downvotes").text(votes.find(".downvotes").text().replace(/\d+/, downvotes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var PerLineNotes = {
|
||||||
|
init:
|
||||||
|
function() {
|
||||||
|
/**
|
||||||
|
* Called when clicking on the "add note" or "reply" button for a diff line.
|
||||||
|
*
|
||||||
|
* Shows the note form below the line.
|
||||||
|
* Sets some hidden fields in the form.
|
||||||
|
*/
|
||||||
|
$(".diff_file_content").on("click", ".line_note_link, .line_note_reply_link", function(e) {
|
||||||
|
var form = $(".per_line_form");
|
||||||
|
$(this).closest("tr").after(form);
|
||||||
|
form.find("#note_line_code").val($(this).data("lineCode"));
|
||||||
|
form.show();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
disableButtonIfEmptyField(".line-note-text", ".submit_inline_note");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called in response to successfully deleting a note on a diff line.
|
||||||
|
*
|
||||||
|
* Removes the actual note from view.
|
||||||
|
* Removes the reply button if the last note for that line has been removed.
|
||||||
|
*/
|
||||||
|
$(".diff_file_content").on("ajax:success", ".delete-note", function() {
|
||||||
|
var trNote = $(this).closest("tr");
|
||||||
|
trNote.fadeOut(function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// check if this is the last note for this line
|
||||||
|
// elements must really be removed for this to work reliably
|
||||||
|
var trLine = trNote.prev();
|
||||||
|
var trRpl = trNote.next();
|
||||||
|
if (trLine.hasClass("line_holder") && trRpl.hasClass("reply")) {
|
||||||
|
trRpl.fadeOut(function() { $(this).remove(); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,11 +10,15 @@ window.Projects = ->
|
||||||
$('form #project_default_branch').chosen()
|
$('form #project_default_branch').chosen()
|
||||||
disableButtonIfEmptyField '#project_name', '.project-submit'
|
disableButtonIfEmptyField '#project_name', '.project-submit'
|
||||||
|
|
||||||
# Git clone panel switcher
|
|
||||||
$ ->
|
$ ->
|
||||||
|
# Git clone panel switcher
|
||||||
scope = $ '.project_clone_holder'
|
scope = $ '.project_clone_holder'
|
||||||
if scope.length > 0
|
if scope.length > 0
|
||||||
$('a, button', scope).click ->
|
$('a, button', scope).click ->
|
||||||
$('a, button', scope).removeClass 'active'
|
$('a, button', scope).removeClass 'active'
|
||||||
$(@).addClass 'active'
|
$(@).addClass 'active'
|
||||||
$('#project_clone', scope).val $(@).data 'clone'
|
$('#project_clone', scope).val $(@).data 'clone'
|
||||||
|
|
||||||
|
# Ref switcher
|
||||||
|
$('.project-refs-select').on 'change', ->
|
||||||
|
$(@).parents('form').submit()
|
||||||
|
|
|
@ -145,6 +145,19 @@ span.update-author {
|
||||||
.label {
|
.label {
|
||||||
background-color: #474D57;
|
background-color: #474D57;
|
||||||
|
|
||||||
|
&.label-tag {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding:4px 6px;
|
||||||
|
color:#444;
|
||||||
|
text-shadow:0 0 1px #fff;
|
||||||
|
|
||||||
|
&.grouped {
|
||||||
|
float: left;
|
||||||
|
margin-right: 6px;
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
&.label-issue {
|
&.label-issue {
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
|
@ -158,6 +171,18 @@ span.update-author {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.label-success {
|
||||||
|
background-color: #8D8;
|
||||||
|
color: #333;
|
||||||
|
text-shadow: 0 1px 1px white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.label-error {
|
||||||
|
background-color: #D88;
|
||||||
|
color: #333;
|
||||||
|
text-shadow: 0 1px 1px white;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.event_label {
|
.event_label {
|
||||||
|
@ -181,11 +206,12 @@ span.update-author {
|
||||||
}
|
}
|
||||||
|
|
||||||
&.joined {
|
&.joined {
|
||||||
background-color: #1cb9ff;
|
background-color: #1ca9dd;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.left {
|
&.left {
|
||||||
background-color: #ff5057;
|
background-color: #888;
|
||||||
|
float:none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,13 +440,48 @@ p.time {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.upvotes {
|
.votes {
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
font-weight: bold;
|
line-height: 15px;
|
||||||
color: #468847;
|
.progress {
|
||||||
text-align: right;
|
height: 4px;
|
||||||
padding: 4px;
|
margin: 0;
|
||||||
margin: 2px;
|
.bar {
|
||||||
|
float: left;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.bar-success {
|
||||||
|
background-color: #468847;
|
||||||
|
@include bg-gradient(#62C462, #51A351);
|
||||||
|
}
|
||||||
|
.bar-danger {
|
||||||
|
background-color: #B94A48;
|
||||||
|
@include bg-gradient(#EE5F5B, #BD362F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.upvotes {
|
||||||
|
display: inline-block;
|
||||||
|
color: #468847;
|
||||||
|
}
|
||||||
|
.downvotes {
|
||||||
|
display: inline-block;
|
||||||
|
color: #B94A48;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.votes-block {
|
||||||
|
margin: 14px 6px 6px 0;
|
||||||
|
.downvotes {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.votes-inline {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 8px;
|
||||||
|
.progress {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 0 2px;
|
||||||
|
width: 45px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix for readme code (stopped it from being yellow) */
|
/* Fix for readme code (stopped it from being yellow) */
|
||||||
|
@ -624,7 +685,7 @@ li.note {
|
||||||
margin-right:40px;
|
margin-right:40px;
|
||||||
|
|
||||||
.prev {
|
.prev {
|
||||||
@extend .borders;
|
@extend .thumbnail;
|
||||||
height:120px;
|
height:120px;
|
||||||
width:175px;
|
width:175px;
|
||||||
margin-bottom:10px;
|
margin-bottom:10px;
|
||||||
|
@ -653,3 +714,31 @@ li.note {
|
||||||
text-align:center;
|
text-align:center;
|
||||||
margin-bottom:10px;
|
margin-bottom:10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.oauth_select_holder {
|
||||||
|
padding:20px;
|
||||||
|
img {
|
||||||
|
padding:5px;
|
||||||
|
margin-right:10px;
|
||||||
|
}
|
||||||
|
.active {
|
||||||
|
img {
|
||||||
|
border:1px solid #ccc;
|
||||||
|
background:$hover;
|
||||||
|
@include border-radius(5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-build-token {
|
||||||
|
float: left;
|
||||||
|
padding: 6px 20px;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gitlab-promo {
|
||||||
|
a {
|
||||||
|
color:#aaa;
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -65,6 +65,10 @@
|
||||||
border-color: #CCC;
|
border-color: #CCC;
|
||||||
@include solid_shade;
|
@include solid_shade;
|
||||||
|
|
||||||
|
&.white {
|
||||||
|
background:#fff;
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
margin:0;
|
margin:0;
|
||||||
}
|
}
|
||||||
|
@ -142,4 +146,8 @@
|
||||||
border:none;
|
border:none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-box-body {
|
||||||
|
padding:10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,29 @@
|
||||||
.nav-pills a:hover { background-color:#888; }
|
.nav-pills a:hover { background-color:#888; }
|
||||||
.nav-pills .active a { background-color: $style_color; }
|
.nav-pills .active a { background-color: $style_color; }
|
||||||
.nav-tabs > li > a, .nav-pills > li > a { color:$style_color; }
|
.nav-tabs > li > a, .nav-pills > li > a { color:$style_color; }
|
||||||
.nav-tabs > .active > a { font-weight:bold; }
|
.nav.nav-tabs {
|
||||||
|
li {
|
||||||
|
> a {
|
||||||
|
padding:8px 20px;
|
||||||
|
margin-right: 7px;
|
||||||
|
border-color: #EEE;
|
||||||
|
color:#888;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
.badge {
|
||||||
|
background-color: #eee;
|
||||||
|
color:#888;
|
||||||
|
text-shadow:0 1px 1px #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
> a {
|
||||||
|
border-color: #CCC;
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
color:#333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** ALERT MESSAGES **/
|
/** ALERT MESSAGES **/
|
||||||
.alert-message { @extend .alert; }
|
.alert-message { @extend .alert; }
|
||||||
|
@ -50,3 +72,13 @@ img.lil_av { padding-left: 4px; padding-right:3px; }
|
||||||
/** HELPERS **/
|
/** HELPERS **/
|
||||||
.nothing_here_message { text-align:center; padding:20px; color:#777; }
|
.nothing_here_message { text-align:center; padding:20px; color:#777; }
|
||||||
p.slead { color:#456; font-size:16px; margin-bottom: 12px; font-weight: 200; line-height: 24px; }
|
p.slead { color:#456; font-size:16px; margin-bottom: 12px; font-weight: 200; line-height: 24px; }
|
||||||
|
|
||||||
|
/** FORMS **/
|
||||||
|
input[type='search'].search-text-input {
|
||||||
|
background-image: url("icon-search.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 10px;
|
||||||
|
padding-left:25px;
|
||||||
|
@include border-radius(4px);
|
||||||
|
border:1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
|
@ -135,7 +135,6 @@ $hover: #fdf5d9;
|
||||||
*/
|
*/
|
||||||
@import "common.scss";
|
@import "common.scss";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Styles related to specific part of app
|
* Styles related to specific part of app
|
||||||
*/
|
*/
|
||||||
|
@ -161,6 +160,11 @@ $hover: #fdf5d9;
|
||||||
*/
|
*/
|
||||||
@import "sections/notes.scss";
|
@import "sections/notes.scss";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file represent profile styles
|
||||||
|
*/
|
||||||
|
@import "sections/profile.scss";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Devise styles
|
* Devise styles
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,15 +20,25 @@
|
||||||
|
|
||||||
.chzn-drop {
|
.chzn-drop {
|
||||||
margin:7px 0;
|
margin:7px 0;
|
||||||
border: 1px solid #CCC;
|
min-width: 400px;
|
||||||
min-width: 300px;
|
border: 2px solid $blue_link;
|
||||||
|
@include border-radius(4px);
|
||||||
|
|
||||||
.chzn-results {
|
.chzn-results {
|
||||||
max-height:300px;
|
max-height:300px;
|
||||||
|
|
||||||
|
.group-result {
|
||||||
|
color: $blue_link;
|
||||||
|
}
|
||||||
|
.active-result {
|
||||||
|
&.highlighted {
|
||||||
|
background: $blue_link;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chzn-search input {
|
.chzn-search input {
|
||||||
min-width:200px;
|
min-width:365px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ input.check_all_issues {
|
||||||
width:100px;
|
width:100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Milestones list
|
* Milestones list
|
||||||
*
|
*
|
||||||
|
|
|
@ -88,11 +88,10 @@ li.merge_request {
|
||||||
@include round-borders-all(4px);
|
@include round-borders-all(4px);
|
||||||
padding:2px 4px;
|
padding:2px 4px;
|
||||||
border:none;
|
border:none;
|
||||||
font-size:13px;
|
font-size:14px;
|
||||||
background: #474D57;
|
background: #474D57;
|
||||||
color:#fff;
|
color:#fff;
|
||||||
font-weight:bold;
|
font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
|
||||||
font-family: monospace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr_source_commit,
|
.mr_source_commit,
|
||||||
|
|
|
@ -55,7 +55,6 @@ ul.main_menu {
|
||||||
|
|
||||||
&.current {
|
&.current {
|
||||||
background-color:#D5D5D5;
|
background-color:#D5D5D5;
|
||||||
border-bottom: 1px solid #AAA;
|
|
||||||
border-right: 1px solid #BBB;
|
border-right: 1px solid #BBB;
|
||||||
border-left: 1px solid #BBB;
|
border-left: 1px solid #BBB;
|
||||||
border-radius: 0 0 1px 1px;
|
border-radius: 0 0 1px 1px;
|
||||||
|
|
|
@ -3,17 +3,13 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#notes-list,
|
#notes-list,
|
||||||
#new_notes_list {
|
#new-notes-list {
|
||||||
display:block;
|
display:block;
|
||||||
list-style:none;
|
list-style:none;
|
||||||
margin:0px;
|
margin:0px;
|
||||||
padding:0px;
|
padding:0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#new_notes_list li:last-child{
|
|
||||||
border-bottom:1px solid #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.issue_notes,
|
.issue_notes,
|
||||||
.wiki_notes {
|
.wiki_notes {
|
||||||
.note_content {
|
.note_content {
|
||||||
|
@ -30,9 +26,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#new_note {
|
#new_note {
|
||||||
.note-text {
|
|
||||||
height:40px;
|
|
||||||
}
|
|
||||||
.attach_holder {
|
.attach_holder {
|
||||||
display:none;
|
display:none;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +41,6 @@
|
||||||
|
|
||||||
.note {
|
.note {
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: block;
|
display: block;
|
||||||
img {float: left; margin-right: 10px;}
|
img {float: left; margin-right: 10px;}
|
||||||
|
@ -70,6 +62,23 @@
|
||||||
.delete-note { display:block; }
|
.delete-note { display:block; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#notes-list:not(.reversed) .note,
|
||||||
|
#new-notes-list:not(.reversed) .note {
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
#notes-list.reversed .note,
|
||||||
|
#new-notes-list.reversed .note {
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark vote notes */
|
||||||
|
.voting_notes .note {
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notes-status {
|
||||||
|
margin: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
p.notify_controls input{
|
p.notify_controls input{
|
||||||
|
|
8
app/assets/stylesheets/sections/profile.scss
Normal file
8
app/assets/stylesheets/sections/profile.scss
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.profile_history {
|
||||||
|
.event_feed {
|
||||||
|
min-height:20px;
|
||||||
|
.avatar {
|
||||||
|
width:20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,29 +3,30 @@ module Notes
|
||||||
def execute
|
def execute
|
||||||
target_type = params[:target_type]
|
target_type = params[:target_type]
|
||||||
target_id = params[:target_id]
|
target_id = params[:target_id]
|
||||||
first_id = params[:first_id]
|
after_id = params[:after_id]
|
||||||
last_id = params[:last_id]
|
before_id = params[:before_id]
|
||||||
|
|
||||||
|
|
||||||
@notes = case target_type
|
@notes = case target_type
|
||||||
when "commit"
|
when "commit"
|
||||||
then project.commit_notes(project.commit(target_id)).fresh.limit(20)
|
project.commit_notes(project.commit(target_id)).fresh.limit(20)
|
||||||
when "snippet"
|
|
||||||
then project.snippets.find(target_id).notes
|
|
||||||
when "wall"
|
|
||||||
then project.common_notes.order("created_at DESC").fresh.limit(50)
|
|
||||||
when "issue"
|
when "issue"
|
||||||
then project.issues.find(target_id).notes.inc_author.order("created_at DESC").limit(20)
|
project.issues.find(target_id).notes.inc_author.fresh.limit(20)
|
||||||
when "merge_request"
|
when "merge_request"
|
||||||
then project.merge_requests.find(target_id).notes.inc_author.order("created_at DESC").limit(20)
|
project.merge_requests.find(target_id).notes.inc_author.fresh.limit(20)
|
||||||
|
when "snippet"
|
||||||
|
project.snippets.find(target_id).notes.fresh
|
||||||
|
when "wall"
|
||||||
|
# this is the only case, where the order is DESC
|
||||||
|
project.common_notes.order("created_at DESC, id DESC").limit(50)
|
||||||
when "wiki"
|
when "wiki"
|
||||||
then project.wikis.reverse.map {|w| w.notes.fresh }.flatten[0..20]
|
project.wiki_notes.limit(20)
|
||||||
end
|
end
|
||||||
|
|
||||||
@notes = if last_id
|
@notes = if after_id
|
||||||
@notes.where("id > ?", last_id)
|
@notes.where("id > ?", after_id)
|
||||||
elsif first_id
|
elsif before_id
|
||||||
@notes.where("id < ?", first_id)
|
@notes.where("id < ?", before_id)
|
||||||
else
|
else
|
||||||
@notes
|
@notes
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
class Admin::DashboardController < ApplicationController
|
class Admin::DashboardController < AdminController
|
||||||
layout "admin"
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
before_filter :authenticate_admin!
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@workers = Resque.workers
|
@workers = Resque.workers
|
||||||
@pending_jobs = Resque.size(:post_receive)
|
@pending_jobs = Resque.size(:post_receive)
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
class Admin::HooksController < ApplicationController
|
class Admin::HooksController < AdminController
|
||||||
layout "admin"
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
before_filter :authenticate_admin!
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@hooks = SystemHook.all
|
@hooks = SystemHook.all
|
||||||
@hook = SystemHook.new
|
@hook = SystemHook.new
|
||||||
|
|
|
@ -1,6 +1,2 @@
|
||||||
class Admin::LogsController < ApplicationController
|
class Admin::LogsController < AdminController
|
||||||
layout "admin"
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
before_filter :authenticate_admin!
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
class Admin::ProjectsController < ApplicationController
|
class Admin::ProjectsController < AdminController
|
||||||
layout "admin"
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
before_filter :authenticate_admin!
|
|
||||||
before_filter :admin_project, only: [:edit, :show, :update, :destroy, :team_update]
|
before_filter :admin_project, only: [:edit, :show, :update, :destroy, :team_update]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
class Admin::ResqueController < ApplicationController
|
class Admin::ResqueController < AdminController
|
||||||
layout 'admin'
|
|
||||||
def show
|
def show
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -1,8 +1,4 @@
|
||||||
class Admin::TeamMembersController < ApplicationController
|
class Admin::TeamMembersController < AdminController
|
||||||
layout "admin"
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
before_filter :authenticate_admin!
|
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
@admin_team_member = UsersProject.find(params[:id])
|
@admin_team_member = UsersProject.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
class Admin::UsersController < ApplicationController
|
class Admin::UsersController < AdminController
|
||||||
layout "admin"
|
|
||||||
before_filter :authenticate_user!
|
|
||||||
before_filter :authenticate_admin!
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@admin_users = User.scoped
|
@admin_users = User.scoped
|
||||||
@admin_users = @admin_users.filter(params[:filter])
|
@admin_users = @admin_users.filter(params[:filter])
|
||||||
|
|
11
app/controllers/admin_controller.rb
Normal file
11
app/controllers/admin_controller.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Provides a base class for Admin controllers to subclass
|
||||||
|
#
|
||||||
|
# Automatically sets the layout and ensures an administrator is logged in
|
||||||
|
class AdminController < ApplicationController
|
||||||
|
layout 'admin'
|
||||||
|
before_filter :authenticate_admin!
|
||||||
|
|
||||||
|
def authenticate_admin!
|
||||||
|
return render_404 unless current_user.is_admin?
|
||||||
|
end
|
||||||
|
end
|
|
@ -84,10 +84,6 @@ class ApplicationController < ActionController::Base
|
||||||
abilities << Ability
|
abilities << Ability
|
||||||
end
|
end
|
||||||
|
|
||||||
def authenticate_admin!
|
|
||||||
return render_404 unless current_user.is_admin?
|
|
||||||
end
|
|
||||||
|
|
||||||
def authorize_project!(action)
|
def authorize_project!(action)
|
||||||
return access_denied! unless can?(current_user, action, project)
|
return access_denied! unless can?(current_user, action, project)
|
||||||
end
|
end
|
||||||
|
|
|
@ -64,7 +64,7 @@ class CommitsController < ApplicationController
|
||||||
@commit.to_patch,
|
@commit.to_patch,
|
||||||
type: "text/plain",
|
type: "text/plain",
|
||||||
disposition: 'attachment',
|
disposition: 'attachment',
|
||||||
filename: "#{@commit.id.patch}"
|
filename: "#{@commit.id}.patch"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ class IssuesController < ApplicationController
|
||||||
before_filter :authorize_write_issue!, only: [:new, :create]
|
before_filter :authorize_write_issue!, only: [:new, :create]
|
||||||
|
|
||||||
# Allow modify issue
|
# Allow modify issue
|
||||||
before_filter :authorize_modify_issue!, only: [:close, :edit, :update]
|
before_filter :authorize_modify_issue!, only: [:edit, :update]
|
||||||
|
|
||||||
# Allow destroy issue
|
# Allow destroy issue
|
||||||
before_filter :authorize_admin_issue!, only: [:destroy]
|
before_filter :authorize_admin_issue!, only: [:destroy]
|
||||||
|
@ -87,8 +87,6 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
return access_denied! unless can?(current_user, :admin_issue, @issue)
|
|
||||||
|
|
||||||
@issue.destroy
|
@issue.destroy
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
|
Gitlab.config.omniauth_providers.each do |provider|
|
||||||
|
define_method provider['name'] do
|
||||||
|
handle_omniauth
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Extend the standard message generation to accept our custom exception
|
# Extend the standard message generation to accept our custom exception
|
||||||
def failure_message
|
def failure_message
|
||||||
|
@ -19,4 +24,27 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||||
sign_in_and_redirect @user
|
sign_in_and_redirect @user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def handle_omniauth
|
||||||
|
oauth = request.env['omniauth.auth']
|
||||||
|
provider, uid = oauth['provider'], oauth['uid']
|
||||||
|
|
||||||
|
if current_user
|
||||||
|
# Change a logged-in user's authentication method:
|
||||||
|
current_user.extern_uid = uid
|
||||||
|
current_user.provider = provider
|
||||||
|
current_user.save
|
||||||
|
redirect_to profile_path
|
||||||
|
else
|
||||||
|
@user = User.find_or_new_for_omniauth(oauth)
|
||||||
|
|
||||||
|
if @user
|
||||||
|
sign_in_and_redirect @user
|
||||||
|
else
|
||||||
|
flash[:notice] = "There's no such user!"
|
||||||
|
redirect_to new_user_session_path
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,9 +16,6 @@ class ProfileController < ApplicationController
|
||||||
def token
|
def token
|
||||||
end
|
end
|
||||||
|
|
||||||
def password
|
|
||||||
end
|
|
||||||
|
|
||||||
def password_update
|
def password_update
|
||||||
params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
|
params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
|
||||||
|
|
||||||
|
@ -32,7 +29,11 @@ class ProfileController < ApplicationController
|
||||||
|
|
||||||
def reset_private_token
|
def reset_private_token
|
||||||
current_user.reset_authentication_token!
|
current_user.reset_authentication_token!
|
||||||
redirect_to profile_token_path
|
redirect_to profile_account_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def history
|
||||||
|
@events = current_user.recent_events.page(params[:page]).per(20)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -5,7 +5,10 @@ class TeamMembersController < ApplicationController
|
||||||
# Authorize
|
# Authorize
|
||||||
before_filter :add_project_abilities
|
before_filter :add_project_abilities
|
||||||
before_filter :authorize_read_project!
|
before_filter :authorize_read_project!
|
||||||
before_filter :authorize_admin_project!, except: [:show]
|
before_filter :authorize_admin_project!, except: [:index, :show]
|
||||||
|
|
||||||
|
def index
|
||||||
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@team_member = project.users_projects.find(params[:id])
|
@team_member = project.users_projects.find(params[:id])
|
||||||
|
@ -22,7 +25,7 @@ class TeamMembersController < ApplicationController
|
||||||
params[:project_access]
|
params[:project_access]
|
||||||
)
|
)
|
||||||
|
|
||||||
redirect_to team_project_path(@project)
|
redirect_to project_team_index_path(@project)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
@ -32,7 +35,7 @@ class TeamMembersController < ApplicationController
|
||||||
unless @team_member.valid?
|
unless @team_member.valid?
|
||||||
flash[:alert] = "User should have at least one role"
|
flash[:alert] = "User should have at least one role"
|
||||||
end
|
end
|
||||||
redirect_to team_project_path(@project)
|
redirect_to project_team_index_path(@project)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
@ -40,7 +43,7 @@ class TeamMembersController < ApplicationController
|
||||||
@team_member.destroy
|
@team_member.destroy
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to team_project_path(@project) }
|
format.html { redirect_to project_team_index_path(@project) }
|
||||||
format.js { render nothing: true }
|
format.js { render nothing: true }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ class CommitDecorator < ApplicationDecorator
|
||||||
# In case this first line is longer than 80 characters, it is cut off
|
# In case this first line is longer than 80 characters, it is cut off
|
||||||
# after 70 characters and ellipses (`&hellp;`) are appended.
|
# after 70 characters and ellipses (`&hellp;`) are appended.
|
||||||
def title
|
def title
|
||||||
return no_commit_message unless safe_message
|
return no_commit_message if safe_message.blank?
|
||||||
|
|
||||||
title_end = safe_message.index(/\n/)
|
title_end = safe_message.index(/\n/)
|
||||||
if (!title_end && safe_message.length > 80) || (title_end && title_end > 80)
|
if (!title_end && safe_message.length > 80) || (title_end && title_end > 80)
|
||||||
|
|
|
@ -62,7 +62,7 @@ module ApplicationHelper
|
||||||
{ label: "#{@project.name} / Wall", url: wall_project_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} / Tree", url: tree_project_ref_path(@project, @project.root_ref) },
|
||||||
{ label: "#{@project.name} / Commits", url: project_commits_path(@project) },
|
{ label: "#{@project.name} / Commits", url: project_commits_path(@project) },
|
||||||
{ label: "#{@project.name} / Team", url: team_project_path(@project) }
|
{ label: "#{@project.name} / Team", url: project_team_index_path(@project) }
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -104,7 +104,8 @@ module ApplicationHelper
|
||||||
|
|
||||||
# Profile Area
|
# Profile Area
|
||||||
when :profile; current_page?(controller: "profile", action: :show)
|
when :profile; current_page?(controller: "profile", action: :show)
|
||||||
when :password; current_page?(controller: "profile", action: :password)
|
when :history; current_page?(controller: "profile", action: :history)
|
||||||
|
when :account; current_page?(controller: "profile", action: :account)
|
||||||
when :token; current_page?(controller: "profile", action: :token)
|
when :token; current_page?(controller: "profile", action: :token)
|
||||||
when :design; current_page?(controller: "profile", action: :design)
|
when :design; current_page?(controller: "profile", action: :design)
|
||||||
when :ssh_keys; controller.controller_name == "keys"
|
when :ssh_keys; controller.controller_name == "keys"
|
||||||
|
@ -135,4 +136,10 @@ module ApplicationHelper
|
||||||
"Never"
|
"Never"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def authbutton(provider, size = 64)
|
||||||
|
file_name = "#{provider.to_s.split('_').first}_#{size}.png"
|
||||||
|
image_tag("authbuttons/#{file_name}",
|
||||||
|
alt: "Sign in with #{provider.to_s.titleize}")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,9 @@ module GitlabMarkdownHelper
|
||||||
# explicitly produce the correct linking behavior (i.e.
|
# explicitly produce the correct linking behavior (i.e.
|
||||||
# "<a>outer text </a><a>gfm ref</a><a> more outer text</a>").
|
# "<a>outer text </a><a>gfm ref</a><a> more outer text</a>").
|
||||||
def link_to_gfm(body, url, html_options = {})
|
def link_to_gfm(body, url, html_options = {})
|
||||||
gfm_body = gfm(body, html_options)
|
return "" if body.blank?
|
||||||
|
|
||||||
|
gfm_body = gfm(escape_once(body), html_options)
|
||||||
|
|
||||||
gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match|
|
gfm_body.gsub!(%r{<a.*?>.*?</a>}m) do |match|
|
||||||
"</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1
|
"</a>#{match}#{link_to("", url, html_options)[0..-5]}" # "</a>".length +1
|
||||||
|
|
17
app/helpers/notes_helper.rb
Normal file
17
app/helpers/notes_helper.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
module NotesHelper
|
||||||
|
def loading_more_notes?
|
||||||
|
params[:loading_more].present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def loading_new_notes?
|
||||||
|
params[:loading_new].present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def note_vote_class(note)
|
||||||
|
if note.upvote?
|
||||||
|
"vote upvote"
|
||||||
|
elsif note.downvote?
|
||||||
|
"vote downvote"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
7
app/helpers/profile_helper.rb
Normal file
7
app/helpers/profile_helper.rb
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
module ProfileHelper
|
||||||
|
def oauth_active_class provider
|
||||||
|
if current_user.provider == provider.to_s
|
||||||
|
'active'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,5 +2,9 @@ module ProjectsHelper
|
||||||
def grouper_project_members(project)
|
def grouper_project_members(project)
|
||||||
@project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
|
@project.users_projects.sort_by(&:project_access).reverse.group_by(&:project_access)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_from_team_message(project, member)
|
||||||
|
"You are going to remove #{member.user_name} from #{project.name}. Are you sure?"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ module TabHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def project_tab_class
|
def project_tab_class
|
||||||
[:show, :files, :team, :edit, :update].each do |action|
|
[:show, :files, :edit, :update].each do |action|
|
||||||
return "current" if current_page?(controller: "projects", action: action, id: @project)
|
return "current" if current_page?(controller: "projects", action: action, id: @project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ module TreeHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def tree_full_path(content)
|
def tree_full_path(content)
|
||||||
|
content.name.force_encoding('utf-8')
|
||||||
if params[:path]
|
if params[:path]
|
||||||
File.join(params[:path], content.name)
|
File.join(params[:path], content.name)
|
||||||
else
|
else
|
||||||
|
|
|
@ -42,6 +42,14 @@ class Event < ActiveRecord::Base
|
||||||
push? || issue? || merge_request? || membership_changed?
|
push? || issue? || merge_request? || membership_changed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def project_name
|
||||||
|
if project
|
||||||
|
project.name
|
||||||
|
else
|
||||||
|
"(deleted)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def push?
|
def push?
|
||||||
action == self.class::Pushed && valid_push?
|
action == self.class::Pushed && valid_push?
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Issue < ActiveRecord::Base
|
class Issue < ActiveRecord::Base
|
||||||
include IssueCommonality
|
include IssueCommonality
|
||||||
include Upvote
|
include Votes
|
||||||
|
|
||||||
acts_as_taggable_on :labels
|
acts_as_taggable_on :labels
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ require File.join(Rails.root, "app/models/commit")
|
||||||
|
|
||||||
class MergeRequest < ActiveRecord::Base
|
class MergeRequest < ActiveRecord::Base
|
||||||
include IssueCommonality
|
include IssueCommonality
|
||||||
include Upvote
|
include Votes
|
||||||
|
|
||||||
BROKEN_DIFF = "--broken-diff"
|
BROKEN_DIFF = "--broken-diff"
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class Note < ActiveRecord::Base
|
||||||
scope :today, where("created_at >= :date", date: Date.today)
|
scope :today, where("created_at >= :date", date: Date.today)
|
||||||
scope :last_week, where("created_at >= :date", date: (Date.today - 7.days))
|
scope :last_week, where("created_at >= :date", date: (Date.today - 7.days))
|
||||||
scope :since, lambda { |day| where("created_at >= :date", date: (day)) }
|
scope :since, lambda { |day| where("created_at >= :date", date: (day)) }
|
||||||
scope :fresh, order("created_at DESC")
|
scope :fresh, order("created_at ASC, id ASC")
|
||||||
scope :inc_author_project, includes(:project, :author)
|
scope :inc_author_project, includes(:project, :author)
|
||||||
scope :inc_author, includes(:author)
|
scope :inc_author, includes(:author)
|
||||||
|
|
||||||
|
@ -105,6 +105,12 @@ class Note < ActiveRecord::Base
|
||||||
def upvote?
|
def upvote?
|
||||||
note.start_with?('+1') || note.start_with?(':+1:')
|
note.start_with?('+1') || note.start_with?(':+1:')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if this is a downvote note,
|
||||||
|
# otherwise false is returned
|
||||||
|
def downvote?
|
||||||
|
note.start_with?('-1') || note.start_with?(':-1:')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
#
|
#
|
||||||
|
|
|
@ -171,6 +171,10 @@ class Project < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def wiki_notes
|
||||||
|
Note.where(noteable_id: wikis.map(&:id), noteable_type: 'Wiki', project_id: self.id)
|
||||||
|
end
|
||||||
|
|
||||||
def project_id
|
def project_id
|
||||||
self.id
|
self.id
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Tree
|
||||||
def initialize(raw_tree, project, ref = nil, path = nil)
|
def initialize(raw_tree, project, ref = nil, path = nil)
|
||||||
@project, @ref, @path = project, ref, path,
|
@project, @ref, @path = project, ref, path,
|
||||||
@tree = if path
|
@tree = if path
|
||||||
raw_tree / path
|
raw_tree / path.dup.force_encoding('ascii-8bit')
|
||||||
else
|
else
|
||||||
raw_tree
|
raw_tree
|
||||||
end
|
end
|
||||||
|
|
|
@ -86,33 +86,20 @@ class User < ActiveRecord::Base
|
||||||
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
|
where('id NOT IN (SELECT DISTINCT(user_id) FROM users_projects)')
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_for_ldap_auth(auth, signed_in_resource=nil)
|
def self.create_from_omniauth(auth, ldap = false)
|
||||||
uid = auth.info.uid
|
gitlab_auth.create_from_omniauth(auth, ldap)
|
||||||
provider = auth.provider
|
end
|
||||||
name = auth.info.name.force_encoding("utf-8")
|
|
||||||
email = auth.info.email.downcase unless auth.info.email.nil?
|
|
||||||
raise OmniAuth::Error, "LDAP accounts must provide an uid and email address" if uid.nil? or email.nil?
|
|
||||||
|
|
||||||
if @user = User.find_by_extern_uid_and_provider(uid, provider)
|
def self.find_or_new_for_omniauth(auth)
|
||||||
@user
|
gitlab_auth.find_or_new_for_omniauth(auth)
|
||||||
# workaround for backward compatibility
|
end
|
||||||
elsif @user = User.find_by_email(email)
|
|
||||||
logger.info "Updating legacy LDAP user #{email} with extern_uid => #{uid}"
|
def self.find_for_ldap_auth(auth, signed_in_resource = nil)
|
||||||
@user.update_attributes(:extern_uid => uid, :provider => provider)
|
gitlab_auth.find_for_ldap_auth(auth, signed_in_resource)
|
||||||
@user
|
end
|
||||||
else
|
|
||||||
logger.info "Creating user from LDAP login {uid => #{uid}, name => #{name}, email => #{email}}"
|
def self.gitlab_auth
|
||||||
password = Devise.friendly_token[0, 8].downcase
|
Gitlab::Auth.new
|
||||||
@user = User.create(
|
|
||||||
:extern_uid => uid,
|
|
||||||
:provider => provider,
|
|
||||||
:name => name,
|
|
||||||
:email => email,
|
|
||||||
:password => password,
|
|
||||||
:password_confirmation => password,
|
|
||||||
:projects_limit => Gitlab.config.default_projects_limit
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.search query
|
def self.search query
|
||||||
|
@ -148,4 +135,3 @@ end
|
||||||
# bio :string(255)
|
# bio :string(255)
|
||||||
# blocked :boolean(1) default(FALSE), not null
|
# blocked :boolean(1) default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ class Wiki < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
new_wiki
|
new_wiki
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
|
|
|
@ -4,6 +4,18 @@ class ProjectObserver < ActiveRecord::Observer
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_destroy(project)
|
def after_destroy(project)
|
||||||
|
log_info("Project \"#{project.name}\" was removed")
|
||||||
|
|
||||||
project.destroy_repository
|
project.destroy_repository
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_create project
|
||||||
|
log_info("#{project.owner.name} created a new project \"#{project.name}\"")
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def log_info message
|
||||||
|
Gitlab::AppLogger.info message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
class UserObserver < ActiveRecord::Observer
|
class UserObserver < ActiveRecord::Observer
|
||||||
def after_create(user)
|
def after_create(user)
|
||||||
|
log_info("User \"#{user.name}\" (#{user.email}) was created")
|
||||||
|
|
||||||
Notify.new_user_email(user.id, user.password).deliver
|
Notify.new_user_email(user.id, user.password).deliver
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def after_destroy user
|
||||||
|
log_info("User \"#{user.name}\" (#{user.email}) was removed")
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def log_info message
|
||||||
|
Gitlab::AppLogger.info message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
module Upvote
|
|
||||||
# Return the number of +1 comments (upvotes)
|
|
||||||
def upvotes
|
|
||||||
notes.select(&:upvote?).size
|
|
||||||
end
|
|
||||||
end
|
|
32
app/roles/votes.rb
Normal file
32
app/roles/votes.rb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
module Votes
|
||||||
|
# Return the number of +1 comments (upvotes)
|
||||||
|
def upvotes
|
||||||
|
notes.select(&:upvote?).size
|
||||||
|
end
|
||||||
|
|
||||||
|
def upvotes_in_percent
|
||||||
|
if votes_count.zero?
|
||||||
|
0
|
||||||
|
else
|
||||||
|
100.0 / votes_count * upvotes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return the number of -1 comments (downvotes)
|
||||||
|
def downvotes
|
||||||
|
notes.select(&:downvote?).size
|
||||||
|
end
|
||||||
|
|
||||||
|
def downvotes_in_percent
|
||||||
|
if votes_count.zero?
|
||||||
|
0
|
||||||
|
else
|
||||||
|
100.0 - upvotes_in_percent
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return the total number of votes
|
||||||
|
def votes_count
|
||||||
|
upvotes + downvotes
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,9 +1,26 @@
|
||||||
.file_holder#README
|
%ul.nav.nav-tabs.log-tabs
|
||||||
.file_title
|
%li.active
|
||||||
%i.icon-file
|
= link_to "githost.log", "#githost", 'data-toggle' => 'tab'
|
||||||
githost.log
|
%li
|
||||||
.file_content.logs
|
= link_to "application.log", "#application", 'data-toggle' => 'tab'
|
||||||
%ol
|
.tab-content
|
||||||
- Gitlab::Logger.read_latest.each do |line|
|
.tab-pane.active#githost
|
||||||
%li
|
.file_holder#README
|
||||||
%p= line
|
.file_title
|
||||||
|
%i.icon-file
|
||||||
|
githost.log
|
||||||
|
.file_content.logs
|
||||||
|
%ol
|
||||||
|
- Gitlab::GitLogger.read_latest.each do |line|
|
||||||
|
%li
|
||||||
|
%p= line
|
||||||
|
.tab-pane#application
|
||||||
|
.file_holder#README
|
||||||
|
.file_title
|
||||||
|
%i.icon-file
|
||||||
|
application.log
|
||||||
|
.file_content.logs
|
||||||
|
%ol
|
||||||
|
- Gitlab::AppLogger.read_latest.each do |line|
|
||||||
|
%li
|
||||||
|
%p= line
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
- unless project.new_record?
|
- unless project.new_record?
|
||||||
.clearfix
|
.clearfix
|
||||||
= f.label :owner_id
|
= f.label :owner_id
|
||||||
.input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }
|
.input= f.select :owner_id, User.all.map { |user| [user.name, user.id] }, {}, {class: 'chosen'}
|
||||||
|
|
||||||
- if project.repo_exists?
|
- if project.repo_exists?
|
||||||
.clearfix
|
.clearfix
|
||||||
|
@ -69,7 +69,6 @@
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
$(function(){
|
$(function(){
|
||||||
$('#project_owner_id').chosen();
|
|
||||||
new Projects();
|
new Projects();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -71,25 +71,11 @@
|
||||||
%th Project Access:
|
%th Project Access:
|
||||||
|
|
||||||
%tr
|
%tr
|
||||||
%td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true
|
%td= select_tag :user_ids, options_from_collection_for_select(@users , :id, :name), multiple: true, data: {placeholder: 'Select users'}, class: 'chosen span5'
|
||||||
%td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
|
%td= select_tag :project_access, options_for_select(Project.access_options), {class: "project-access-select chosen span3"}
|
||||||
|
|
||||||
%tr
|
%tr
|
||||||
%td= submit_tag 'Add', class: "btn primary"
|
%td= submit_tag 'Add', class: "btn primary"
|
||||||
%td
|
%td
|
||||||
Read more about project permissions
|
Read more about project permissions
|
||||||
%strong= link_to "here", help_permissions_path, class: "vlink"
|
%strong= link_to "here", help_permissions_path, class: "vlink"
|
||||||
|
|
||||||
:css
|
|
||||||
form select {
|
|
||||||
width:150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#user_ids {
|
|
||||||
width:300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:javascript
|
|
||||||
$('select#user_ids').chosen();
|
|
||||||
$('select#repo_access').chosen();
|
|
||||||
$('select#project_access').chosen();
|
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
%h3 Resque
|
%h3.page_title Resque
|
||||||
%iframe{src: resque_url, width: 1168, height: 600, style: "border: none"}
|
%br
|
||||||
|
.ui-box
|
||||||
|
%iframe{src: resque_url, width: '100%', height: 600, style: "border: none"}
|
||||||
|
|
|
@ -8,20 +8,9 @@
|
||||||
.clearfix
|
.clearfix
|
||||||
%label Project Access:
|
%label Project Access:
|
||||||
.input
|
.input
|
||||||
= f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select"
|
= f.select :project_access, options_for_select(Project.access_options, @admin_team_member.project_access), {}, class: "project-access-select chosen span3"
|
||||||
|
|
||||||
%br
|
%br
|
||||||
.actions
|
.actions
|
||||||
= f.submit 'Save', class: "btn primary"
|
= f.submit 'Save', class: "btn primary"
|
||||||
= link_to 'Cancel', :back, class: "btn"
|
= link_to 'Cancel', :back, class: "btn"
|
||||||
|
|
||||||
:css
|
|
||||||
form select {
|
|
||||||
width:300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:javascript
|
|
||||||
$('select#team_member_user_id').chosen();
|
|
||||||
$('select#team_member_project_id').chosen();
|
|
||||||
$('select#team_member_repo_access').chosen();
|
|
||||||
$('select#team_member_project_access').chosen();
|
|
||||||
|
|
|
@ -68,8 +68,8 @@
|
||||||
%th Project Access:
|
%th Project Access:
|
||||||
|
|
||||||
%tr
|
%tr
|
||||||
%td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true
|
%td= select_tag :project_ids, options_from_collection_for_select(@projects , :id, :name), multiple: true, data: {placeholder: 'Select projects'}, class: 'chosen span5'
|
||||||
%td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select"
|
%td= select_tag :project_access, options_for_select(Project.access_options), class: "project-access-select chosen span3"
|
||||||
|
|
||||||
%tr
|
%tr
|
||||||
%td= submit_tag 'Add', class: "btn primary"
|
%td= submit_tag 'Add', class: "btn primary"
|
||||||
|
@ -97,17 +97,3 @@
|
||||||
%td= select_tag :tm_project_access, options_for_select(Project.access_options, tm.project_access), class: "medium project-access-select", disabled: :disabled
|
%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 '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"
|
%td= link_to 'Remove from team', admin_team_member_path(tm), confirm: 'Are you sure?', method: :delete, class: "btn small danger"
|
||||||
|
|
||||||
:css
|
|
||||||
form select {
|
|
||||||
width:150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#project_ids {
|
|
||||||
width:300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:javascript
|
|
||||||
$('select#project_ids').chosen();
|
|
||||||
$('select#repo_access').chosen();
|
|
||||||
$('select#project_access').chosen();
|
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
= link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do
|
= link_to tree_project_ref_path(@project, @commit.id), class: "browse-button primary grouped" do
|
||||||
%strong Browse Code »
|
%strong Browse Code »
|
||||||
%h3.commit-title.page_title
|
%h3.commit-title.page_title
|
||||||
= gfm @commit.title
|
= gfm escape_once(@commit.title)
|
||||||
- if @commit.description.present?
|
- if @commit.description.present?
|
||||||
%pre.commit-description
|
%pre.commit-description
|
||||||
= gfm @commit.description
|
= gfm escape_once(@commit.description)
|
||||||
.commit-info
|
.commit-info
|
||||||
.row
|
.row
|
||||||
.span4
|
.span4
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
%ul.nav.nav-tabs
|
%ul.nav.nav-tabs
|
||||||
%li
|
%li= render partial: 'shared/ref_switcher', locals: {destination: 'commits'}
|
||||||
= 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)) }"}
|
%li{class: "#{'active' if current_page?(project_commits_path(@project)) }"}
|
||||||
= link_to project_commits_path(@project) do
|
= link_to project_commits_path(@project) do
|
||||||
Commits
|
Commits
|
||||||
|
@ -20,14 +16,8 @@
|
||||||
Tags
|
Tags
|
||||||
%span.badge= @project.repo.tag_count
|
%span.badge= @project.repo.tag_count
|
||||||
|
|
||||||
|
|
||||||
- if current_page?(project_commits_path(@project)) && current_user.private_token
|
- if current_page?(project_commits_path(@project)) && current_user.private_token
|
||||||
%li.right
|
%li.right
|
||||||
%span.rss-icon
|
%span.rss-icon
|
||||||
= link_to project_commits_path(@project, :atom, { private_token: current_user.private_token, ref: @ref }), title: "Feed" do
|
= link_to project_commits_path(@project, :atom, { private_token: current_user.private_token, ref: @ref }), title: "Feed" do
|
||||||
= image_tag "rss_ui.png", title: "feed"
|
= image_tag "rss_ui.png", title: "feed"
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function(){
|
|
||||||
$('.project-refs-select').chosen();
|
|
||||||
});
|
|
||||||
|
|
|
@ -13,14 +13,11 @@
|
||||||
%td.old_line
|
%td.old_line
|
||||||
= link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code
|
= link_to raw(type == "new" ? " " : line_old), "##{line_code}", id: line_code
|
||||||
- if @comments_allowed
|
- if @comments_allowed
|
||||||
= link_to "", "#", class: "line_note_link", "line_code" => line_code, title: "Add note for this line"
|
= render "notes/per_line_note_link", line_code: line_code
|
||||||
%td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code
|
%td.new_line= link_to raw(type == "old" ? " " : line_new) , "##{line_code}", id: line_code
|
||||||
%td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} "
|
%td.line_content{class: "noteable_line #{type} #{line_code}", "line_code" => line_code}= raw "#{line} "
|
||||||
|
|
||||||
- if @comments_allowed
|
- if @comments_allowed
|
||||||
- comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at).reverse
|
- comments = @line_notes.select { |n| n.line_code == line_code }.sort_by(&:created_at)
|
||||||
- unless comments.empty?
|
- unless comments.empty?
|
||||||
- comments.each_with_index do |note, i|
|
= render "notes/per_line_notes_with_reply", notes: comments
|
||||||
= render "notes/reply_button", line_code: line_code if i.zero?
|
|
||||||
= render "notes/per_line_show", note: note
|
|
||||||
- @line_notes.reject!{ |n| n == note }
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
= render "commits/commit_box"
|
= render "commits/commit_box"
|
||||||
= render "commits/diffs", diffs: @commit.diffs
|
= render "commits/diffs", diffs: @commit.diffs
|
||||||
= render "notes/notes", tid: @commit.id, tt: "commit"
|
= render "notes/notes_with_form", tid: @commit.id, tt: "commit"
|
||||||
= render "notes/per_line_form"
|
= render "notes/per_line_form"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,13 +31,19 @@
|
||||||
%span= project_last_activity(project)
|
%span= project_last_activity(project)
|
||||||
.bottom= paginate @projects, theme: "gitlab"
|
.bottom= paginate @projects, theme: "gitlab"
|
||||||
|
|
||||||
%hr
|
|
||||||
%div
|
%div
|
||||||
%span.rss-icon
|
%span.rss-icon
|
||||||
= link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
|
= link_to dashboard_path(:atom, { private_token: current_user.private_token }) do
|
||||||
= image_tag "rss_ui.png", title: "feed"
|
= image_tag "rss_ui.png", title: "feed"
|
||||||
%strong News Feed
|
%strong News Feed
|
||||||
|
|
||||||
|
%hr
|
||||||
|
.gitlab-promo
|
||||||
|
= link_to "Homepage", "http://gitlabhq.com"
|
||||||
|
= link_to "Blog", "http://blog.gitlabhq.com"
|
||||||
|
= link_to "@gitlabhq", "https://twitter.com/gitlabhq"
|
||||||
|
|
||||||
|
|
||||||
- else
|
- else
|
||||||
%h3.nothing_here_message There are no projects you have access to.
|
%h3.nothing_here_message There are no projects you have access to.
|
||||||
%br
|
%br
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
$(function() {
|
$(function() {
|
||||||
$('#new_user').toggle();
|
$('#new_user').toggle();
|
||||||
});
|
});
|
||||||
= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
|
= form_for(resource, :as => resource_name, :url => session_path(resource_name), :html => { :class => "login-box" }) do |f|
|
||||||
= f.text_field :email, :class => "text top", :placeholder => "Email"
|
= f.text_field :email, :class => "text top", :placeholder => "Email"
|
||||||
= f.password_field :password, :class => "text bottom", :placeholder => "Password"
|
= f.password_field :password, :class => "text bottom", :placeholder => "Password"
|
||||||
- if devise_mapping.rememberable?
|
- if devise_mapping.rememberable?
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
.right
|
.right
|
||||||
= render :partial => "devise/shared/links"
|
= render :partial => "devise/shared/links"
|
||||||
- if devise_mapping.omniauthable?
|
- if devise_mapping.omniauthable?
|
||||||
|
%hr/
|
||||||
- resource_class.omniauth_providers.each do |provider|
|
- resource_class.omniauth_providers.each do |provider|
|
||||||
%hr/
|
%span
|
||||||
= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider), :class => "btn primary"
|
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
|
||||||
%br/
|
|
||||||
|
|
|
@ -5,4 +5,4 @@
|
||||||
%strong.cdark= commit.author_name
|
%strong.cdark= commit.author_name
|
||||||
–
|
–
|
||||||
= image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
|
= image_tag gravatar_icon(commit.author_email), class: "avatar", width: 16
|
||||||
= gfm truncate(commit.title, length: 50) rescue "--broken encoding"
|
= gfm escape_once(truncate(commit.title, length: 50)) rescue "--broken encoding"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
%strong #{event.author_name}
|
%strong #{event.author_name}
|
||||||
%span.event_label{class: event.action_name}= event.action_name
|
%span.event_label{class: event.action_name}= event.action_name
|
||||||
project
|
project
|
||||||
%strong= link_to event.project.name, event.project
|
%strong= link_to event.project_name, event.project
|
||||||
%span.cgray
|
%span.cgray
|
||||||
= time_ago_in_words(event.created_at)
|
= time_ago_in_words(event.created_at)
|
||||||
ago.
|
ago.
|
||||||
|
|
|
@ -18,12 +18,12 @@
|
||||||
= f.label :assignee_id do
|
= f.label :assignee_id do
|
||||||
%i.icon-user
|
%i.icon-user
|
||||||
Assign to
|
Assign to
|
||||||
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" })
|
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select a user" }, {class: 'chosen'})
|
||||||
.issue_milestone
|
.issue_milestone
|
||||||
= f.label :milestone_id do
|
= f.label :milestone_id do
|
||||||
%i.icon-time
|
%i.icon-time
|
||||||
Milestone
|
Milestone
|
||||||
.input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" })
|
.input= f.select(:milestone_id, @project.milestones.active.all.collect {|p| [ p.title, p.id ] }, { include_blank: "Select milestone" }, {class: 'chosen'})
|
||||||
|
|
||||||
.issue_description
|
.issue_description
|
||||||
.clearfix
|
.clearfix
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
= check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
|
= check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, class: "selected_issue", disabled: !can?(current_user, :modify_issue, issue)
|
||||||
.right
|
.right
|
||||||
- issue.labels.each do |label|
|
- issue.labels.each do |label|
|
||||||
%span.label.label-issue.grouped
|
%span.label.label-tag.grouped
|
||||||
%i.icon-tag
|
%i.icon-tag
|
||||||
= label.name
|
= label.name
|
||||||
- if issue.notes.any?
|
- if issue.notes.any?
|
||||||
|
@ -34,5 +34,5 @@
|
||||||
- else
|
- else
|
||||||
|
|
||||||
|
|
||||||
- if issue.upvotes > 0
|
- if issue.votes_count > 0
|
||||||
%span.badge.badge-success= "+#{issue.upvotes}"
|
= render 'votes/votes_inline', votable: issue
|
||||||
|
|
|
@ -1,8 +1 @@
|
||||||
= render "form"
|
= render "form"
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function(){
|
|
||||||
$('select#issue_assignee_id').chosen();
|
|
||||||
$('select#issue_milestone_id').chosen();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
= form_tag search_project_issues_path(@project), method: :get, remote: true, id: "issue_search_form", class: :right do
|
= 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 :project_id, @project.id, { id: 'project_id' }
|
||||||
= hidden_field_tag :status, params[:f]
|
= hidden_field_tag :status, params[:f]
|
||||||
= search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib' }
|
= search_field_tag :issue_search, nil, { placeholder: 'Search', class: 'issue_search span3 right neib search-text-input' }
|
||||||
|
|
||||||
.clearfix
|
.clearfix
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1 @@
|
||||||
= render "form"
|
= render "form"
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function(){
|
|
||||||
$('select#issue_assignee_id').chosen();
|
|
||||||
$('select#issue_milestone_id').chosen();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
|
@ -8,22 +8,22 @@
|
||||||
%span.right
|
%span.right
|
||||||
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
|
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
|
||||||
- if @issue.closed
|
- if @issue.closed
|
||||||
= link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn small"
|
= link_to 'Reopen', project_issue_path(@project, @issue, issue: {closed: false }, status_only: true), method: :put, class: "btn grouped success"
|
||||||
- else
|
- else
|
||||||
= link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn small", title: "Close Issue"
|
= link_to 'Close', project_issue_path(@project, @issue, issue: {closed: true }, status_only: true), method: :put, class: "btn grouped danger", title: "Close Issue"
|
||||||
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
|
- if can?(current_user, :admin_project, @project) || @issue.author == current_user
|
||||||
= link_to edit_project_issue_path(@project, @issue), class: "btn small" do
|
= link_to edit_project_issue_path(@project, @issue), class: "btn grouped" do
|
||||||
%i.icon-edit
|
%i.icon-edit
|
||||||
Edit
|
Edit
|
||||||
|
|
||||||
%br
|
.right
|
||||||
- if @issue.upvotes > 0
|
.span3#votes= render 'votes/votes_block', votable: @issue
|
||||||
.upvotes#upvotes= "+#{pluralize @issue.upvotes, 'upvote'}"
|
|
||||||
|
|
||||||
.back_link
|
.back_link
|
||||||
= link_to project_issues_path(@project) do
|
= link_to project_issues_path(@project) do
|
||||||
← To issues list
|
← To issues list
|
||||||
|
|
||||||
|
|
||||||
.main_box
|
.main_box
|
||||||
.top_box_content
|
.top_box_content
|
||||||
%h4
|
%h4
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
.alert-message.error.status_info Closed
|
.alert-message.error.status_info Closed
|
||||||
- else
|
- else
|
||||||
.alert-message.success.status_info Open
|
.alert-message.success.status_info Open
|
||||||
= gfm @issue.title
|
= gfm escape_once(@issue.title)
|
||||||
|
|
||||||
.middle_box_content
|
.middle_box_content
|
||||||
%cite.cgray Created by
|
%cite.cgray Created by
|
||||||
|
@ -61,4 +61,4 @@
|
||||||
= markdown @issue.description
|
= markdown @issue.description
|
||||||
|
|
||||||
|
|
||||||
.issue_notes#notes= render "notes/notes", tid: @issue.id, tt: "issue"
|
.issue_notes.voting_notes#notes= render "notes/notes_with_form", tid: @issue.id, tt: "issue"
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
%li.wll
|
%li.wll
|
||||||
%strong= label.name
|
%strong
|
||||||
|
%i.icon-tag
|
||||||
|
= label.name
|
||||||
.right
|
.right
|
||||||
%span= pluralize label.count, 'issue'
|
= link_to project_issues_path(label_name: label.name) do
|
||||||
|
%strong
|
||||||
|
= pluralize(label.count, 'issue')
|
||||||
|
= "»"
|
||||||
|
|
|
@ -9,20 +9,20 @@
|
||||||
%li.home{class: tab_class(:profile)}
|
%li.home{class: tab_class(:profile)}
|
||||||
= link_to "Profile", profile_path
|
= link_to "Profile", profile_path
|
||||||
|
|
||||||
%li{class: tab_class(:password)}
|
%li{class: tab_class(:account)}
|
||||||
= link_to "Password", profile_password_path
|
= link_to "Account", profile_account_path
|
||||||
|
|
||||||
%li{class: tab_class(:ssh_keys)}
|
%li{class: tab_class(:ssh_keys)}
|
||||||
= link_to keys_path do
|
= link_to keys_path do
|
||||||
SSH Keys
|
SSH Keys
|
||||||
%span.count= current_user.keys.count
|
%span.count= current_user.keys.count
|
||||||
|
|
||||||
%li{class: tab_class(:token)}
|
|
||||||
= link_to "Token", profile_token_path
|
|
||||||
|
|
||||||
%li{class: tab_class(:design)}
|
%li{class: tab_class(:design)}
|
||||||
= link_to "Design", profile_design_path
|
= link_to "Design", profile_design_path
|
||||||
|
|
||||||
|
%li{class: tab_class(:history)}
|
||||||
|
= link_to "History", profile_history_path
|
||||||
|
|
||||||
|
|
||||||
.content
|
.content
|
||||||
= yield
|
= yield
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
.padded
|
.padded
|
||||||
= f.label :source_branch, "From", class: "control-label"
|
= f.label :source_branch, "From", class: "control-label"
|
||||||
.controls
|
.controls
|
||||||
= f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
|
= f.select(:source_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
|
||||||
.mr_source_commit
|
.mr_source_commit
|
||||||
|
|
||||||
.span2
|
.span2
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
.padded
|
.padded
|
||||||
= f.label :target_branch, "To", class: "control-label"
|
= f.label :target_branch, "To", class: "control-label"
|
||||||
.controls
|
.controls
|
||||||
= f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, style: "width:250px")
|
= f.select(:target_branch, @project.heads.map(&:name), { include_blank: "Select branch" }, {class: 'chosen span3'})
|
||||||
.mr_target_commit
|
.mr_target_commit
|
||||||
|
|
||||||
%h4.cdark 2. Fill info
|
%h4.cdark 2. Fill info
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
= f.label :assignee_id do
|
= f.label :assignee_id do
|
||||||
%i.icon-user
|
%i.icon-user
|
||||||
Assign to
|
Assign to
|
||||||
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, style: "width:250px")
|
.input= f.select(:assignee_id, @project.users.all.collect {|p| [ p.name, p.id ] }, { include_blank: "Select user" }, {class: 'chosen span3'})
|
||||||
|
|
||||||
.control-group
|
.control-group
|
||||||
|
|
||||||
|
@ -56,18 +56,12 @@
|
||||||
= link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
|
= link_to project_merge_request_path(@project, @merge_request), class: "btn cancel-btn" do
|
||||||
Cancel
|
Cancel
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
:javascript
|
:javascript
|
||||||
$(function(){
|
$(function(){
|
||||||
disableButtonIfEmptyField("#merge_request_title", ".save-btn");
|
disableButtonIfEmptyField("#merge_request_title", ".save-btn");
|
||||||
$('select#merge_request_assignee_id').chosen();
|
|
||||||
$('select#merge_request_source_branch').chosen();
|
|
||||||
$('select#merge_request_target_branch').chosen();
|
|
||||||
var source_branch = $("#merge_request_source_branch");
|
var source_branch = $("#merge_request_source_branch");
|
||||||
var target_branch = $("#merge_request_target_branch");
|
var target_branch = $("#merge_request_target_branch");
|
||||||
|
|
||||||
|
|
||||||
$.get("#{branch_from_project_merge_requests_path(@project)}", {ref: source_branch.val() });
|
$.get("#{branch_from_project_merge_requests_path(@project)}", {ref: source_branch.val() });
|
||||||
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: target_branch.val() });
|
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: target_branch.val() });
|
||||||
|
|
||||||
|
@ -79,4 +73,3 @@
|
||||||
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: $(this).val() });
|
$.get("#{branch_to_project_merge_requests_path(@project)}", {ref: $(this).val() });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -23,5 +23,6 @@
|
||||||
authored by #{merge_request.author_name}
|
authored by #{merge_request.author_name}
|
||||||
= time_ago_in_words(merge_request.created_at)
|
= time_ago_in_words(merge_request.created_at)
|
||||||
ago
|
ago
|
||||||
- if merge_request.upvotes > 0
|
|
||||||
%span.badge.badge-success= "+#{merge_request.upvotes}"
|
- if merge_request.votes_count > 0
|
||||||
|
= render 'votes/votes_inline', votable: merge_request
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
%i.icon-list-alt
|
%i.icon-list-alt
|
||||||
Diff
|
Diff
|
||||||
|
|
||||||
.merge_request_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
|
.merge_request_notes.voting_notes#notes{ class: (controller.action_name == 'show') ? "" : "hide" }
|
||||||
= render("notes/notes", tid: @merge_request.id, tt: "merge_request")
|
= render("notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")
|
||||||
.merge-request-diffs
|
.merge-request-diffs
|
||||||
= render "merge_requests/show/diffs" if @diffs
|
= render "merge_requests/show/diffs" if @diffs
|
||||||
.status
|
.status
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
= render "show"
|
= render "show"
|
||||||
|
|
||||||
|
:javascript
|
||||||
|
$(function(){
|
||||||
|
PerLineNotes.init();
|
||||||
|
});
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
:plain
|
:plain
|
||||||
$(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}");
|
$(".merge-request-diffs").html("#{escape_javascript(render(partial: "merge_requests/show/diffs"))}");
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
PerLineNotes.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
:plain
|
:plain
|
||||||
$(".merge-request-notes").html("#{escape_javascript(render("notes/notes", tid: @merge_request.id, tt: "merge_request"))}");
|
$(".merge-request-notes").html("#{escape_javascript(render notes/notes_with_form", tid: @merge_request.id, tt: "merge_request")}");
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
.alert-message.error.status_info Closed
|
.alert-message.error.status_info Closed
|
||||||
- else
|
- else
|
||||||
.alert-message.success.status_info Open
|
.alert-message.success.status_info Open
|
||||||
= gfm @merge_request.title
|
= gfm escape_once(@merge_request.title)
|
||||||
|
|
||||||
.middle_box_content
|
.middle_box_content
|
||||||
%div
|
%div
|
||||||
|
|
|
@ -23,10 +23,8 @@
|
||||||
%i.icon-edit
|
%i.icon-edit
|
||||||
Edit
|
Edit
|
||||||
|
|
||||||
%br
|
.right
|
||||||
- if @merge_request.upvotes > 0
|
.span3#votes= render 'votes/votes_block', votable: @merge_request
|
||||||
.upvotes#upvotes= "+#{pluralize @merge_request.upvotes, 'upvote'}"
|
|
||||||
|
|
||||||
|
|
||||||
.back_link
|
.back_link
|
||||||
= link_to project_merge_requests_path(@project) do
|
= link_to project_merge_requests_path(@project) do
|
||||||
|
|
|
@ -1,7 +1 @@
|
||||||
= render "form"
|
= render "form"
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function(){
|
|
||||||
$('select#issue_assignee_id').chosen();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
.alert-message.error.status_info Closed
|
.alert-message.error.status_info Closed
|
||||||
- else
|
- else
|
||||||
.alert-message.success.status_info Open
|
.alert-message.success.status_info Open
|
||||||
= gfm @milestone.title
|
= gfm escape_once(@milestone.title)
|
||||||
%small.right= @milestone.expires_at
|
%small.right= @milestone.expires_at
|
||||||
|
|
||||||
.middle_box_content
|
.middle_box_content
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
.right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
|
.right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
|
||||||
.clearfix
|
.clearfix
|
||||||
|
|
||||||
.row.note_advanced_opts.hide
|
.row.note_advanced_opts
|
||||||
.span3
|
.span3
|
||||||
= f.submit 'Add Comment', class: "btn success submit_note grouped", id: "submit_note"
|
= f.submit 'Add Comment', class: "btn success submit_note grouped", id: "submit_note"
|
||||||
= link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link'
|
= link_to 'Preview', preview_project_notes_path(@project), class: 'btn grouped', id: 'preview-link'
|
|
@ -5,8 +5,9 @@
|
||||||
$('.note-form-holder #preview-link').text('Preview');
|
$('.note-form-holder #preview-link').text('Preview');
|
||||||
$('.note-form-holder #preview-note').hide();
|
$('.note-form-holder #preview-note').hide();
|
||||||
$('.note-form-holder').show();
|
$('.note-form-holder').show();
|
||||||
NoteList.prepend(#{note.id}, "#{escape_javascript(render partial: "notes/show", locals: {note: note})}");
|
NoteList.appendNewNote(#{note.id}, "#{escape_javascript(render "notes/note", note: note)}");
|
||||||
|
|
||||||
- else
|
- else
|
||||||
:plain
|
:plain
|
||||||
$(".note-form-holder").replaceWith("#{escape_javascript(render('form'))}");
|
$(".note-form-holder").replaceWith("#{escape_javascript(render 'form')}");
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
- if note.valid?
|
|
||||||
:plain
|
|
||||||
$(".per_line_form").hide();
|
|
||||||
$('.line-note-form-holder 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})}");
|
|
19
app/views/notes/_create_per_line_note.js.haml
Normal file
19
app/views/notes/_create_per_line_note.js.haml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
- if note.valid?
|
||||||
|
:plain
|
||||||
|
// hide and reset the form
|
||||||
|
$(".per_line_form").hide();
|
||||||
|
$('.line-note-form-holder textarea').val("");
|
||||||
|
|
||||||
|
// find the reply button for this line
|
||||||
|
// (might not be there if this is the first note)
|
||||||
|
var trRpl = $("a.line_note_reply_link[data-line-code='#{note.line_code}']").closest("tr");
|
||||||
|
if (trRpl.size() == 0) {
|
||||||
|
// find the commented line ...
|
||||||
|
var trEl = $(".#{note.line_code}").parent();
|
||||||
|
// ... and insert the note and the reply button after it
|
||||||
|
trEl.after("#{escape_javascript(render "notes/per_line_reply_button", line_code: note.line_code)}");
|
||||||
|
trEl.after("#{escape_javascript(render "notes/per_line_note", note: note)}");
|
||||||
|
} else {
|
||||||
|
// instert new note before reply button
|
||||||
|
trRpl.before("#{escape_javascript(render "notes/per_line_note", note: note)}");
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
- unless @notes.blank?
|
|
||||||
- if params[:last_id]
|
|
||||||
:plain
|
|
||||||
NoteList.replace("#{escape_javascript(render(partial: 'notes/notes_list'))}");
|
|
||||||
|
|
||||||
- elsif params[:first_id]
|
|
||||||
:plain
|
|
||||||
NoteList.append(#{@notes.last.id}, "#{escape_javascript(render(partial: 'notes/notes_list'))}");
|
|
||||||
|
|
||||||
- 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]}, "");
|
|
|
@ -1,4 +1,4 @@
|
||||||
%li{id: dom_id(note), class: "note"}
|
%li{id: dom_id(note), class: "note #{note_vote_class(note)}"}
|
||||||
= image_tag gravatar_icon(note.author.email), class: "avatar s32"
|
= image_tag gravatar_icon(note.author.email), class: "avatar s32"
|
||||||
%div.note-author
|
%div.note-author
|
||||||
%strong= note.author_name
|
%strong= note.author_name
|
||||||
|
@ -6,6 +6,14 @@
|
||||||
%cite.cgray
|
%cite.cgray
|
||||||
= time_ago_in_words(note.updated_at)
|
= time_ago_in_words(note.updated_at)
|
||||||
ago
|
ago
|
||||||
|
- if note.upvote?
|
||||||
|
%span.label.label-success
|
||||||
|
%i.icon-thumbs-up
|
||||||
|
\+1
|
||||||
|
- if note.downvote?
|
||||||
|
%span.label.label-error
|
||||||
|
%i.icon-thumbs-down
|
||||||
|
\-1
|
||||||
- if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
|
- if(note.author_id == current_user.id) || can?(current_user, :admin_note, @project)
|
||||||
= link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do
|
= link_to [@project, note], confirm: 'Are you sure?', method: :delete, remote: true, class: "cred delete-note btn very_small" do
|
||||||
%i.icon-trash
|
%i.icon-trash
|
|
@ -1,13 +1,4 @@
|
||||||
- if can? current_user, :write_note, @project
|
- @notes.each do |note|
|
||||||
= render "notes/form"
|
- next unless note.author
|
||||||
.clear
|
= render "note", note: note
|
||||||
%hr
|
|
||||||
%ul#new_notes_list
|
|
||||||
%ul#notes-list
|
|
||||||
.status
|
|
||||||
|
|
||||||
|
|
||||||
:javascript
|
|
||||||
$(function(){
|
|
||||||
NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
- @notes.each do |note|
|
|
||||||
- next unless note.author
|
|
||||||
= render partial: "notes/show", locals: {note: note}
|
|
||||||
|
|
11
app/views/notes/_notes_with_form.html.haml
Normal file
11
app/views/notes/_notes_with_form.html.haml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
%ul#notes-list
|
||||||
|
%ul#new-notes-list
|
||||||
|
.notes-status
|
||||||
|
|
||||||
|
- if can? current_user, :write_note, @project
|
||||||
|
= render "notes/common_form"
|
||||||
|
|
||||||
|
:javascript
|
||||||
|
$(function(){
|
||||||
|
NoteList.init("#{tid}", "#{tt}", "#{project_notes_path(@project)}");
|
||||||
|
});
|
5
app/views/notes/_per_line_note.html.haml
Normal file
5
app/views/notes/_per_line_note.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
%tr.line_notes_row
|
||||||
|
%td{colspan: 3}
|
||||||
|
%ul
|
||||||
|
= render "notes/note", note: note
|
||||||
|
|
1
app/views/notes/_per_line_note_link.html.haml
Normal file
1
app/views/notes/_per_line_note_link.html.haml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
= link_to "", "#", class: "line_note_link", data: { line_code: line_code }, title: "Add note for this line"
|
3
app/views/notes/_per_line_notes_with_reply.html.haml
Normal file
3
app/views/notes/_per_line_notes_with_reply.html.haml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
- notes.each do |note|
|
||||||
|
= render "notes/per_line_note", note: note
|
||||||
|
= render "notes/per_line_reply_button", line_code: notes.first.line_code
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue