Merge branch '4-0-stable' into stable

This commit is contained in:
Dmitriy Zaporozhets 2012-12-23 14:02:47 +02:00
commit 02a29d1db4
399 changed files with 8207 additions and 4908 deletions

1
.gitignore vendored
View file

@ -23,3 +23,4 @@ db/data.yml
.idea
.DS_Store
.chef
vendor/bundle/*

View file

@ -19,8 +19,7 @@ services:
before_script:
- "cp config/database.yml.$DB config/database.yml"
- "cp config/gitlab.yml.example config/gitlab.yml"
- "bundle exec rake db:create RAILS_ENV=test"
- "bundle exec rake db:migrate RAILS_ENV=test"
- "bundle exec rake db:setup RAILS_ENV=test"
- "bundle exec rake db:seed_fu RAILS_ENV=test"
- "sh -e /etc/init.d/xvfb start"
script: "bundle exec rake travis --trace"

View file

@ -1,3 +1,35 @@
v 4.0.0
- Remove project code and path from API. Use id instead
- Return valid clonable url to repo for web hook
- Fixed backup issue
- Reorganized settings
- Fixed commits compare
- Refactored scss
- Improve status checks
- Validates presence of User#name
- Fixed postgres support
- Removed sqlite support
- Modified post-receive hook
- Milestones can be closed now
- Show comment events on dashboard
- Quick add team members via group#people page
- [API] expose created date for hooks and SSH keys
- [API] list, create issue notes
- [API] list, create snippet notes
- [API] list, create wall notes
- Remove project code - use path instead
- added username field to user
- rake task to fill usernames based on emails create namespaces for users
- STI Group < Namespace
- Project has namespace_id
- Projects with namespaces also namespaced in gitolite and stored in subdir
- Moving project to group will move it under group namespace
- Ability to move project from namespaces to another
- Fixes commit patches getting escaped (see #2036)
- Support diff and patch generation for commits and merge request
- MergeReqest doesn't generate a temporary file for the patch any more
- Update the UI to allow downloading Patch or Diff
v 3.1.0
- Updated gems
- Services: Gitlab CI integration
@ -34,7 +66,7 @@ v 3.0.0
- Fixed bug with gitolite keys
- UI improved
- Increased perfomance of application
- Show user avatar in last commit when browsing Files
- Show user avatar in last commit when browsing Files
- Refactored Gitlab::Merge
- Use Font Awsome for icons
- Separate observing of Note and MergeRequestsa

View file

@ -1,26 +1,26 @@
## Contribute to GitLab
# Contact & support
If you want to contribute to GitLab, follow this process:
If you want quick help, head over to our [Support Forum](https://groups.google.com/forum/#!forum/gitlabhq).
Otherwise you can follow our [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) for a more systematic and thorough guide to solving your issues.
1. Fork the project
2. Create a feature branch
3. Code
4. Create a pull request
We will only accept pull requests if:
* Your code has proper tests and all tests pass
* Your code can be merged w/o problems
* It won't break existing functionality
* It's quality code
* We like it :)
# Contribute to GitLab
For examples of feedback on pull requests please look at the [closed pull requests](https://github.com/gitlabhq/gitlabhq/pulls?direction=desc&page=1&sort=created&state=closed).
## Recipes
## Installation
We collect user submitted installation scripts and config file templates for platforms we don't support officially.
We believe there is merit in allowing a certain amount of diversity.
You can get and submit your solution to running/configuring GitLab with your favorite OS/distro, database, web server, cloud hoster, configuration management tool, etc.
Install the Gitlab development in a virtual machine with the [Gitlab Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm). Installing it in a virtual machine makes it much easier to set up all the dependencies for integration testing.
Help us improve the collection of [GitLab Recipes](https://github.com/gitlabhq/gitlab-recipes/)
## Running tests
For more information on running the tests please read the [development tips](https://github.com/gitlabhq/gitlabhq/blob/master/doc/development.md)
## Feature suggestions
Follow the [Issue Submission Guide](https://github.com/gitlabhq/gitlabhq/wiki/Issue-Submission-Guide) and support other peoples ideas or propose your own.
## Code
Follow our [Developer Guide](https://github.com/gitlabhq/gitlabhq/wiki/Developer-Guide) to set you up for hacking on GitLab.

15
Gemfile
View file

@ -11,7 +11,6 @@ end
gem "rails", "3.2.9"
# Supported DBs
gem "sqlite3", group: :sqlite
gem "mysql2", group: :mysql
gem "pg", group: :postgres
@ -27,13 +26,13 @@ gem "grit", git: "https://github.com/gitlabhq/grit.git", ref:
gem "omniauth-ldap", git: "https://github.com/gitlabhq/omniauth-ldap.git", ref: 'f038dd852d7bd473a557e385d5d7c2fd5dc1dc2e'
gem 'yaml_db', git: "https://github.com/gitlabhq/yaml_db.git", ref: '98e9a5dca43e3fedd3268c76a73af40d1bdf1dfd'
gem 'grack', git: "https://github.com/gitlabhq/grack.git", ref: 'ba46f3b0845c6a09d488ae6abdce6ede37e227e8'
gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '212fd40bea61f3c6a167223768e7295dc32bbc10'
gem 'grit_ext', git: "https://github.com/gitlabhq/grit_ext.git", ref: '8e6afc2da821354774aa4d1ee8a1aa2082f84a3e'
# Gitolite client (for work with gitolite-admin repo)
gem "gitolite", '1.1.0'
# Syntax highlighter
gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", ref: '4db80c599067e2d5f23c5c243bf85b8ca0368ad4'
gem "pygments.rb", git: "https://github.com/gitlabhq/pygments.rb.git", branch: "master"
# Language detection
gem "github-linguist", "~> 2.3.4" , require: "linguist"
@ -101,11 +100,11 @@ group :assets do
gem "therubyracer"
gem 'chosen-rails', "0.9.8"
gem 'jquery-atwho-rails', "0.1.6"
gem 'jquery-atwho-rails', "0.1.7"
gem "jquery-rails", "2.1.3"
gem "jquery-ui-rails", "2.0.2"
gem "modernizr", "2.6.2"
gem "raphael-rails", "2.1.0"
gem "raphael-rails", "1.5.2"
gem 'bootstrap-sass', "2.2.1.1"
gem "font-awesome-sass-rails", "~> 2.0.0"
gem "gemoji", "~> 1.2.1", require: 'emoji/railtie'
@ -125,7 +124,7 @@ group :development, :test do
gem "capybara"
gem "pry"
gem "awesome_print"
gem "database_cleaner"
gem "database_cleaner", ref: "f89c34300e114be99532f14c115b2799a3380ac6", git: "https://github.com/bmabey/database_cleaner.git"
gem "launchy"
gem 'factory_girl_rails'
@ -139,7 +138,7 @@ group :development, :test do
gem 'rb-inotify', require: linux_only('rb-inotify')
# PhantomJS driver for Capybara
gem 'poltergeist'
gem 'poltergeist', git: 'https://github.com/jonleighton/poltergeist.git', ref: '5c2e092001074a8cf09f332d3714e9ba150bc8ca'
end
group :test do
@ -152,5 +151,5 @@ group :test do
end
group :production do
gem "gitlab_meta", '3.1'
gem "gitlab_meta", '4.0'
end

View file

@ -1,3 +1,10 @@
GIT
remote: https://github.com/bmabey/database_cleaner.git
revision: f89c34300e114be99532f14c115b2799a3380ac6
ref: f89c34300e114be99532f14c115b2799a3380ac6
specs:
database_cleaner (0.9.1)
GIT
remote: https://github.com/ctran/annotate_models.git
revision: be4e26825b521f0b2d86b181e2dff89901aa9b1e
@ -26,10 +33,10 @@ GIT
GIT
remote: https://github.com/gitlabhq/grit_ext.git
revision: 212fd40bea61f3c6a167223768e7295dc32bbc10
ref: 212fd40bea61f3c6a167223768e7295dc32bbc10
revision: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e
ref: 8e6afc2da821354774aa4d1ee8a1aa2082f84a3e
specs:
grit_ext (0.6.0)
grit_ext (0.6.1)
charlock_holmes (~> 0.6.9)
GIT
@ -45,8 +52,8 @@ GIT
GIT
remote: https://github.com/gitlabhq/pygments.rb.git
revision: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
ref: 4db80c599067e2d5f23c5c243bf85b8ca0368ad4
revision: db1da0343adf86b49bdc3add04d02d2e80438d38
branch: master
specs:
pygments.rb (0.3.2)
posix-spawn (~> 0.3.6)
@ -59,6 +66,18 @@ GIT
specs:
yaml_db (0.2.2)
GIT
remote: https://github.com/jonleighton/poltergeist.git
revision: 5c2e092001074a8cf09f332d3714e9ba150bc8ca
ref: 5c2e092001074a8cf09f332d3714e9ba150bc8ca
specs:
poltergeist (1.0.2)
capybara (~> 1.1)
childprocess (~> 0.3)
faye-websocket (~> 0.4, >= 0.4.4)
http_parser.rb (~> 0.5.3)
multi_json (~> 1.0)
GEM
remote: http://rubygems.org/
specs:
@ -128,7 +147,6 @@ GEM
colorize (0.5.8)
crack (0.3.1)
daemons (1.1.9)
database_cleaner (0.9.1)
devise (2.1.2)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
@ -171,7 +189,7 @@ GEM
mime-types (~> 1.19)
pygments.rb (>= 0.2.13)
github-markup (0.7.4)
gitlab_meta (3.1)
gitlab_meta (4.0)
gitolite (1.1.0)
gratr19 (~> 0.4.4.1)
grit (~> 2.5.0)
@ -215,7 +233,7 @@ GEM
httpauth (0.2.0)
i18n (0.6.1)
journey (1.0.4)
jquery-atwho-rails (0.1.6)
jquery-atwho-rails (0.1.7)
jquery-rails (2.1.3)
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
@ -279,12 +297,6 @@ GEM
omniauth-oauth (~> 1.0)
orm_adapter (0.4.0)
pg (0.14.1)
poltergeist (1.0.2)
capybara (~> 1.1)
childprocess (~> 0.3)
faye-websocket (~> 0.4, >= 0.4.4)
http_parser.rb (~> 0.5.3)
multi_json (~> 1.0)
polyglot (0.3.3)
posix-spawn (0.3.6)
pry (0.9.10)
@ -329,7 +341,7 @@ GEM
thor (>= 0.14.6, < 2.0)
raindrops (0.10.0)
rake (10.0.1)
raphael-rails (2.1.0)
raphael-rails (1.5.2)
rb-fsevent (0.9.2)
rb-inotify (0.8.8)
ffi (>= 0.5.0)
@ -404,7 +416,6 @@ GEM
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.6)
stamp (0.3.0)
test_after_commit (0.0.1)
therubyracer (0.10.2)
@ -453,7 +464,7 @@ DEPENDENCIES
chosen-rails (= 0.9.8)
coffee-rails (~> 3.2.2)
colored
database_cleaner
database_cleaner!
devise (~> 2.1.0)
draper (~> 0.18.0)
email_spec
@ -465,7 +476,7 @@ DEPENDENCIES
git
github-linguist (~> 2.3.4)
github-markup (~> 0.7.4)
gitlab_meta (= 3.1)
gitlab_meta (= 4.0)
gitolite (= 1.1.0)
grack!
grape (~> 0.2.1)
@ -476,7 +487,7 @@ DEPENDENCIES
guard-spinach
haml-rails (~> 0.3.5)
httparty
jquery-atwho-rails (= 0.1.6)
jquery-atwho-rails (= 0.1.7)
jquery-rails (= 2.1.3)
jquery-ui-rails (= 2.0.2)
kaminari (~> 0.14.1)
@ -490,14 +501,14 @@ DEPENDENCIES
omniauth-ldap!
omniauth-twitter
pg
poltergeist
poltergeist!
pry
pygments.rb!
quiet_assets (~> 1.0.1)
rack-mini-profiler
rails (= 3.2.9)
rails-dev-tweaks
raphael-rails (= 2.1.0)
raphael-rails (= 1.5.2)
rb-fsevent
rb-inotify
redcarpet (~> 2.2.2)
@ -512,7 +523,6 @@ DEPENDENCIES
simplecov
six
spinach-rails
sqlite3
stamp
test_after_commit
therubyracer

View file

@ -1,4 +1,4 @@
# Welcome to GitLab [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://secure.travis-ci.org/gitlabhq/gitlabhq) [![build status](https://secure.travis-ci.org/gitlabhq/grit.png)](https://secure.travis-ci.org/gitlabhq/grit) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq)
# Welcome to GitLab [![build status](https://secure.travis-ci.org/gitlabhq/gitlabhq.png)](https://travis-ci.org/gitlabhq/gitlabhq) [![build status](https://secure.travis-ci.org/gitlabhq/grit.png)](https://travis-ci.org/gitlabhq/grit) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/gitlabhq/gitlabhq) [![Dependency Status](https://gemnasium.com/gitlabhq/gitlabhq.png)](https://gemnasium.com/gitlabhq/gitlabhq)
GitLab is a free project and repository management application

View file

@ -1 +1 @@
3.1.0
4.0.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -10,3 +10,8 @@ $ ->
$('.log-tabs a').click (e) ->
e.preventDefault()
$(this).tab('show')
$('.log-bottom').click (e) ->
e.preventDefault()
visible_log = $(".file_content:visible")
visible_log.animate({ scrollTop: visible_log.find('ol').height() }, "fast")

View file

@ -1,52 +1,38 @@
# Creates the variables for setting up GFM auto-completion
window.GitLab ?= {}
GitLab.GfmAutoComplete ?= {}
# Emoji
data = []
template = "<li data-value='${insert}'>${name} <img alt='${name}' height='20' src='${image}' width='20' /></li>"
GitLab.GfmAutoComplete.Emoji = {data, template}
# Team Members
data = []
url = '';
params = {private_token: '', page: 1}
GitLab.GfmAutoComplete.Members = {data, url, params}
# Add GFM auto-completion to all input fields, that accept GFM input.
GitLab.GfmAutoComplete.setup = ->
input = $('.js-gfm-input')
GitLab.GfmAutoComplete =
# Emoji
input.atWho ':',
data: GitLab.GfmAutoComplete.Emoji.data,
tpl: GitLab.GfmAutoComplete.Emoji.template
Emoji:
data: []
template: '<li data-value="${insert}">${name} <img alt="${name}" height="20" src="${image}" width="20" /></li>'
# Team Members
input.atWho '@', (query, callback) ->
(getMoreMembers = ->
$.getJSON(GitLab.GfmAutoComplete.Members.url, GitLab.GfmAutoComplete.Members.params)
.success (members) ->
# pick the data we need
newMembersData = $.map(members, (m) -> m.name )
Members:
data: []
url: ''
params:
private_token: ''
template: '<li data-value="${username}">${username} <small>${name}</small></li>'
# add the new page of data to the rest
$.merge(GitLab.GfmAutoComplete.Members.data, newMembersData)
# Add GFM auto-completion to all input fields, that accept GFM input.
setup: ->
input = $('.js-gfm-input')
# show the pop-up with a copy of the current data
callback(GitLab.GfmAutoComplete.Members.data[..])
# Emoji
input.atWho ':',
data: @Emoji.data
tpl: @Emoji.template
# are we past the last page?
if newMembersData.length is 0
# set static data and stop callbacks
input.atWho '@',
data: GitLab.GfmAutoComplete.Members.data
callback: null
else
# get next page
getMoreMembers()
# Team Members
input.atWho '@',
tpl: @Members.template
callback: (query, callback) =>
request_params = $.extend({}, @Members.params, query: query)
$.getJSON(@Members.url, request_params).done (members) =>
new_members_data = $.map(members, (m) ->
username: m.username,
name: m.name
)
callback(new_members_data)
# so the next request gets the next page
GitLab.GfmAutoComplete.Members.params.page += 1
).call()

View file

@ -1,43 +1,3 @@
function switchToNewIssue(){
$(".issues_content").hide("fade", { direction: "left" }, 150, function(){
$('select#issue_assignee_id').chosen();
$('select#issue_milestone_id').chosen();
$("#new_issue_dialog").show("fade", { direction: "right" }, 150);
$('.top-tabs .add_new').hide();
disableButtonIfEmptyField("#issue_title", ".save-btn");
GitLab.GfmAutoComplete.setup();
});
}
function switchToEditIssue(){
$(".issues_content").hide("fade", { direction: "left" }, 150, function(){
$('select#issue_assignee_id').chosen();
$('select#issue_milestone_id').chosen();
$("#edit_issue_dialog").show("fade", { direction: "right" }, 150);
$('.add_new').hide();
disableButtonIfEmptyField("#issue_title", ".save-btn");
GitLab.GfmAutoComplete.setup();
});
}
function switchFromNewIssue(){
backToIssues();
}
function switchFromEditIssue(){
backToIssues();
}
function backToIssues(){
$("#edit_issue_dialog, #new_issue_dialog").hide("fade", { direction: "right" }, 150, function(){
$(".issues_content").show("fade", { direction: "left" }, 150, function() {
$("#edit_issue_dialog").html("");
$("#new_issue_dialog").html("");
$('.add_new').show();
});
});
}
function initIssuesSearch() {
var href = $('#issue_search_form').attr('action');
var last_terms = '';
@ -76,23 +36,15 @@ function issuesPage(){
$(this).closest("form").submit();
});
$("#new_issue_link").click(function(){
updateNewIssueURL();
});
$('body').on('ajax:success', '.close_issue, .reopen_issue, #new_issue', function(){
$('body').on('ajax:success', '.close_issue, .reopen_issue', function(){
var t = $(this),
totalIssues,
reopen = t.hasClass('reopen_issue'),
newIssue = false;
if( this.id == 'new_issue' ){
newIssue = true;
}
$('.issue_counter, #new_issue').each(function(){
reopen = t.hasClass('reopen_issue');
$('.issue_counter').each(function(){
var issue = $(this);
totalIssues = parseInt( $(this).html(), 10 );
if( newIssue || ( reopen && issue.closest('.main_menu').length ) ){
if( reopen && issue.closest('.main_menu').length ){
$(this).html( totalIssues+1 );
}else {
$(this).html( totalIssues-1 );
@ -126,20 +78,3 @@ function issuesCheckChanged() {
$('.issues_filters').show();
}
}
function updateNewIssueURL(){
var new_issue_link = $("#new_issue_link");
var milestone_id = $("#milestone_id").val();
var assignee_id = $("#assignee_id").val();
var new_href = "";
if(milestone_id){
new_href = "issue[milestone_id]=" + milestone_id + "&";
}
if(assignee_id){
new_href = new_href + "issue[assignee_id]=" + assignee_id;
}
if(new_href.length){
new_href = new_issue_link.attr("href") + "?" + new_href;
new_issue_link.attr("href", new_href);
}
};

View file

@ -7,6 +7,18 @@ window.slugify = (text) ->
window.ajaxGet = (url) ->
$.ajax({type: "GET", url: url, dataType: "script"})
window.errorMessage = (message) ->
ehtml = $("<p>")
ehtml.addClass("error_message")
ehtml.html(message)
ehtml
window.split = (val) ->
return val.split( /,\s*/ )
window.extractLast = (term) ->
return split( term ).pop()
# Disable button if text field is empty
window.disableButtonIfEmptyField = (field_selector, button_selector) ->
field = $(field_selector)
@ -33,6 +45,11 @@ $ ->
# Bottom tooltip
$('.has_bottom_tooltip').tooltip(placement: 'bottom')
# Flash
if (flash = $("#flash-container")).length > 0
flash.click -> $(@).slideUp("slow")
flash.slideDown "slow"
setTimeout (-> flash.slideUp("slow")), 3000
# Disable form buttons while a form is submitting
$('body').on 'ajax:complete, ajax:beforeSend, submit', 'form', (e) ->

View file

@ -14,14 +14,6 @@ var MergeRequest = {
$(".mr_show_all_commits").bind("click", function() {
self.showAllCommits();
});
$(".line_note_link, .line_note_reply_link").live("click", function(e) {
var form = $(".per_line_form");
$(this).parent().parent().after(form);
form.find("#note_line_code").val($(this).attr("line_code"));
form.show();
return false;
});
},
initMergeWidget:
@ -34,6 +26,12 @@ var MergeRequest = {
self.showState(data.state);
}, "json");
}
if(self.opts.ci_enable){
$.get(self.opts.url_to_ci_check, function(data){
self.showCiState(data.status);
}, "json");
}
},
initTabs:
@ -87,6 +85,11 @@ var MergeRequest = {
$(".automerge_widget." + state).show();
},
showCiState:
function(state){
$(".ci_widget").hide();
$(".ci_widget.ci-" + state).show();
},
loadDiff:
function() {

View file

@ -8,3 +8,13 @@ $ ->
# Go up the hierarchy and show the corresponding submission feedback element
$(@).closest('fieldset').find('.update-feedback').show('highlight', {color: '#DFF0D8'}, 500)
$('.update-username form').on 'ajax:before', ->
$('.loading-gif').show()
$(this).find('.update-success').hide()
$(this).find('.update-failed').hide()
$('.update-username form').on 'ajax:complete', ->
$(this).find('.save-btn').removeAttr('disabled')
$(this).find('.save-btn').removeClass('disabled')
$(this).find('.loading-gif').hide()

View file

@ -1,8 +1,4 @@
window.Projects = ->
$('#project_name').on 'change', ->
slug = slugify $(@).val()
$('#project_code, #project_path').val slug
$('.new_project, .edit_project').on 'ajax:before', ->
$('.project_new_holder, .project_edit_holder').hide()
$('.save-project-loader').show()
@ -22,10 +18,3 @@ $ ->
# Ref switcher
$('.project-refs-select').on 'change', ->
$(@).parents('form').submit()
class @GraphNav
@init: ->
$('.graph svg').css 'position', 'relative'
$('body').bind 'keyup', (e) ->
$('.graph svg').animate(left: '+=400') if e.keyCode is 37 # left
$('.graph svg').animate(left: '-=400') if e.keyCode is 39 # right

View file

@ -28,7 +28,7 @@ $ ->
return false
$('#tree-slider .tree-item-file-name a, .breadcrumb li > a').live 'click', (e) ->
History.pushState(null, null, $(@).attr('href'))
History.pushState(null, null, decodeURIComponent($(@).attr('href')))
return false
History.Adapter.bind window, 'statechange', ->

View file

@ -1,11 +0,0 @@
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require jquery.ui.all
*= require jquery.ui.aristo
*= require jquery.atwho
*= require chosen
*= require_self
*= require main
*/

View file

@ -0,0 +1,47 @@
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require jquery.ui.gitlab
*= require jquery.atwho
*= require chosen
*= require_self
*/
/**
* GitLab bootstrap:
*/
@import "gitlab_bootstrap.scss";
@import "common.scss";
@import "ref_select.scss";
@import "sections/header.scss";
@import "sections/nav.scss";
@import "sections/commits.scss";
@import "sections/issues.scss";
@import "sections/projects.scss";
@import "sections/snippets.scss";
@import "sections/votes.scss";
@import "sections/merge_requests.scss";
@import "sections/graph.scss";
@import "sections/events.scss";
@import "sections/themes.scss";
@import "sections/tree.scss";
@import "sections/notes.scss";
@import "sections/profile.scss";
@import "sections/login.scss";
@import "sections/editor.scss";
@import "highlight/white.scss";
@import "highlight/dark.scss";
/**
* UI themes:
*/
@import "themes/ui_basic.scss";
@import "themes/ui_mars.scss";
@import "themes/ui_modern.scss";
@import "themes/ui_gray.scss";
@import "themes/ui_color.scss";

View file

@ -1,53 +1,45 @@
/** LAYOUT **/
body {
margin-bottom:20px;
margin-bottom: 20px;
}
.container {
padding-top:0;
z-index:5;
padding-top: 0;
z-index: 5;
}
.container .content {
margin:0 0;
margin: 0 0;
}
.container .sidebar {
width: 200px;
height:100%;
min-height:450px;
float:right;
}
.visible_link,
.author_link {
color: $link_color;
}
.help li { color:#111 }
.help li { color:$style_color; }
.back_link {
text-decoration:underline;
font-size:14px;
font-weight:bold;
padding:10px 0;
padding-bottom:0;
text-decoration: underline;
font-size: 14px;
font-weight: bold;
padding: 10px 0;
padding-bottom: 0;
}
.info_link {
margin-right:5px;
float:left;
margin-right: 5px;
float: left;
img {
width:20px;
width: 20px;
}
}
.download_repo_link {
background: url("images.png") no-repeat 0 -48px;
padding-left:20px;
padding-left: 20px;
}
table a code {
@ -61,32 +53,37 @@ table a code {
}
.loading {
margin:20px auto;
margin: 20px auto;
background: url(ajax_loader.gif) no-repeat center center;
width:40px;
height:40px;
width: 40px;
height: 40px;
&.loading-gray {
background: url(ajax_loader_gray.gif) no-repeat center center;
}
}
/** FLASH message **/
#flash_container {
height:50px;
position:fixed;
z-index:10001;
top:0px;
width:100%;
margin-bottom:15px;
overflow:hidden;
background:white;
cursor:pointer;
border-bottom:1px solid #ccc;
#flash-container {
height: 50px;
position: fixed;
z-index: 10001;
top: 0px;
width: 100%;
margin-bottom: 15px;
overflow: hidden;
background: white;
cursor: pointer;
border-bottom: 1px solid #ccc;
text-align: center;
display: none;
h4 {
color:#666;
font-size:18px;
line-height:38px;
padding-top:5px;
margin:2px;
font-weight:normal;
color: #666;
font-size: 18px;
line-height: 38px;
padding-top: 5px;
margin: 2px;
font-weight: normal;
}
}
@ -94,40 +91,29 @@ table a code {
margin-right:50px
}
.handle:hover {
cursor:move;
span.update-author {
display: block;
color: #999;
font-weight: normal;
font-style: italic;
strong {
font-weight: bold;
font-style: normal;
}
}
span.update-author {
display:block;
}
span.update-author {
color:#999;
font-weight:normal;
font-style:italic;
}
span.update-author strong {
font-weight:bold;
font-style: normal;
}
/** UPDATE ITEM **/
span.update-author {
display:block;
}
/** END UPDATE ITEM **/
.dashboard-loader {
float:left;
margin:10px;
display:none;
float: left;
margin: 10px;
display: none;
}
.user-mention {
color:#2FA0BB;
font-weight:bold;
color: #2FA0BB;
font-weight: bold;
}
.neib {
margin-right:10px;
margin-right: 10px;
}
.label {
@ -136,9 +122,9 @@ span.update-author {
&.label-tag {
background: none;
border: none;
padding:4px 6px;
color:#444;
text-shadow:0 0 1px #fff;
padding: 4px 6px;
color: #444;
text-shadow: 0 0 1px #fff;
&.grouped {
float: left;
@ -149,9 +135,9 @@ span.update-author {
&.label-issue {
background-color: #eee;
border: 1px solid #ccc;
padding:4px 6px;
color:#444;
text-shadow:0 0 1px #fff;
padding: 4px 6px;
color: #444;
text-shadow: 0 0 1px #fff;
&.grouped {
float: left;
@ -201,21 +187,21 @@ form {
.field_with_errors {
display:inline;
display: inline;
}
ul.breadcrumb {
background:white;
border:none;
background: white;
border: none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
color:#474D57;
font-weight:bold;
font-size:14px;
color: #474D57;
font-weight: bold;
font-size: 14px;
}
.arrow {
@ -225,31 +211,31 @@ ul.breadcrumb {
float: left;
position: relative;
left: -10px;
padding:0;
margin:0;
padding: 0;
margin: 0;
}
}
input[type=text] {
&.large_text {
padding:6px;
font-size:16px;
padding: 6px;
font-size: 16px;
}
}
input.git_clone_url {
width:325px;
width: 325px;
}
.merge-request-form-holder {
select {
width:300px;
width: 300px;
}
}
/** Issues **/
#issue_assignee_id {
width:300px;
width: 300px;
}
#new_issue_dialog textarea{
@ -257,26 +243,11 @@ input.git_clone_url {
}
.project_list_url {
width:250px;
width: 250px;
background:#fff !important;
}
/** bordered list **/
ul.bordered-list {
margin:5px 0px;
padding:0px;
li {
padding: 5px 0;
border-bottom: 1px solid #EEE;
overflow: hidden;
display: block;
margin:0px;
}
}
ul.bordered-list li:last-child { border:none }
.line_holder {
&:hover {
td {
@ -287,10 +258,10 @@ ul.bordered-list li:last-child { border:none }
li.commit {
.avatar {
width:24px;
width: 24px;
top:-5px;
margin-right:10px;
margin-left:10px;
margin-right: 10px;
margin-left: 10px;
}
code {
@ -310,102 +281,10 @@ p.time {
.styled_image {
border:2px solid #ddd;
border: 2px solid #ddd;
}
.ico {
background: url("images.png") no-repeat -85px -77px;
width: 19px;
height: 16px;
float: left;
position: relative;
margin-right: 10px;
top: 8px;
&.project {
background-position: -37px -77px;
}
&.activities {
background-position:-162px -22px;
}
&.projects {
background-position:-209px -21px;
}
}
.leftbar {
h5, .title {
padding:5px 10px;
}
h4 {
font-size:14px;
padding:2px 10px;
color:#666;
border-bottom:1px solid #f1f1f1;
}
a:last-child h4 { border:none; }
a:hover {
h4 {
color:#111;
background:$hover;
border-color:#CCC;
.ico.project {
background-position:-209px -21px;
}
}
}
.bottom {
padding:10px;
}
}
.votes {
font-size: 13px;
line-height: 15px;
.progress {
height: 4px;
margin: 0;
.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) */
.readme {
@ -418,63 +297,45 @@ p.time {
}
}
.highlight_word {
background:#EEDC94;
background: #EEDC94;
}
.status_info {
font-size:14px;
padding:5px 15px;
line-height:24px;
width:60px;
text-align:center;
float:left;
margin-right:20px;
font-size: 14px;
padding: 5px 15px;
line-height: 26px;
text-align: center;
float: right;
position: relative;
top: -5px;
@include border-radius(4px);
&.success {
background: #5BB75B;
color: white;
text-shadow: 0 1px #111;
border-color: #9A9;
}
&.error {
background: #DA4E49;
border-color: #BD362F;
color: white;
text-shadow: 0 1px #111;
color: #FFF;
}
}
.arrow{
background: #E3E5EA;
padding: 5px;
margin-top:5px;
border-radius: 5px;
margin-top: 5px;
@include border-radius(5px);
text-shadow: none;
color: #999;
line-height: 16px;
font-weight:bold;
font-weight: bold;
}
.thin_area{
height: 150px;
}
.gitlab_pagination {
span a { color:$link_color; }
.prev, .next, .current, .page a {
padding:10px;
}
.current {
border-bottom:2px solid $style_color;
}
}
// Fixes alignment on notes.
.new_note {
label {
text-align:left;
text-align: left;
}
}
@ -486,7 +347,7 @@ li.note {
border-bottom:none !important;
}
.file {
padding-left:20px;
padding-left: 20px;
background:url("icon-attachment.png") no-repeat left center;
}
}
@ -494,7 +355,7 @@ li.note {
.markdown {
img {
max-width:100%;
max-width: 100%;
}
}
@ -504,19 +365,19 @@ li.note {
.team_member_show {
td:first-child {
color:#aaa;
color: #aaa;
}
}
.remember_me {
text-align:left;
text-align: left;
input {
margin:0;
margin: 0;
}
span {
padding-left:5px;
padding-left: 5px;
}
}
@ -530,10 +391,10 @@ li.note {
.data {
a {
h1 {
line-height:48px;
font-size:48px;
padding:20px;
text-align:center;
line-height: 48px;
font-size: 48px;
padding: 20px;
text-align: center;
}
}
}
@ -541,12 +402,12 @@ li.note {
.rss-icon {
img {
width:24px;
vertical-align:top;
width: 24px;
vertical-align: top;
}
strong {
line-height:24px;
line-height: 24px;
}
}
@ -554,43 +415,43 @@ li.note {
/* CHZN reset few styles */
.chzn-container-single .chzn-single {
background:#FFF;
background: #FFF;
border: 1px solid #bbb;
box-shadow:none;
box-shadow: none;
}
.chzn-container-active .chzn-single {
background:#fff;
background: #fff;
}
.supp_diff_link,
.mr_show_all_commits {
cursor:pointer;
cursor: pointer;
}
.merge_request,
.issue {
&.today{
background: #EFE;
border-color:#CEC;
border-color: #CEC;
}
&.closed {
background: #F5f5f5;
border-color:#E5E5E5;
border-color: #E5E5E5;
}
&.merged {
background: #F5f5f5;
border-color:#E5E5E5;
border-color: #E5E5E5;
}
}
.git_error_tips {
@extend .span6;
text-align:left;
margin-top:40px;
text-align: left;
margin-top: 40px;
pre {
background:white;
border:none;
background: white;
border: none;
font-size: 12px;
}
}
@ -602,18 +463,22 @@ li.note {
margin-bottom: 10px;
background: #FEE;
padding-left: 20px;
&.centered {
text-align: center;
}
}
.oauth_select_holder {
padding:20px;
padding: 20px;
img {
padding:5px;
margin-right:10px;
padding: 5px;
margin-right: 10px;
}
.active {
img {
border:1px solid #ccc;
background:$hover;
border: 1px solid #ccc;
background: $hover;
@include border-radius(5px);
}
}
@ -627,29 +492,67 @@ li.note {
.gitlab-promo {
a {
color:#aaa;
color: #aaa;
margin-right: 30px;
}
}
pre {
&.clean {
background:none;
border:none;
margin:0;
padding:0;
background: none;
border: none;
margin: 0;
padding: 0;
}
}
.milestone .progress {
margin-bottom: 0;
margin-top:4px;
.milestone {
&.milestone-closed {
background: #eee;
}
.progress {
margin-bottom: 0;
margin-top: 4px;
}
}
.float-link {
float:left;
margin-right:15px;
float: left;
margin-right: 15px;
.s16 {
margin-right:5px;
margin-right: 5px;
}
}
.dashboard-search-filter {
padding:5px;
.search-text-input {
float:left;
@extend .span2;
}
.btn {
margin-left: 5px;
float:left;
}
}
h1.http_status_code {
font-size: 56px;
line-height: 100px;
font-weight: normal;
color: #456;
}
.control-group {
.controls {
span {
&.descr {
position: relative;
top: 2px;
left: 5px;
color: #666;
}
}
}
}

View file

@ -0,0 +1,26 @@
/** Override bootstrap variables **/
$baseFontSize: 13px !default;
$baseLineHeight: 18px !default;
// BOOTSTRAP
@import "bootstrap";
@import "bootstrap/responsive-utilities";
@import "bootstrap/responsive-1200px-min";
@import "font-awesome";
/**
* GitLab bootstrap.
* Overrides some styles of twitter bootstrap.
* Also give some common classes for GitLab app
*/
@import "gitlab_bootstrap/variables.scss";
@import "gitlab_bootstrap/fonts.scss";
@import "gitlab_bootstrap/mixins.scss";
@import "gitlab_bootstrap/common.scss";
@import "gitlab_bootstrap/typography.scss";
@import "gitlab_bootstrap/buttons.scss";
@import "gitlab_bootstrap/blocks.scss";
@import "gitlab_bootstrap/files.scss";
@import "gitlab_bootstrap/tables.scss";
@import "gitlab_bootstrap/lists.scss";

View file

@ -15,8 +15,8 @@
@extend .borders;
@extend .prepend-top-20;
@extend .append-bottom-20;
border-width:1px;
@include solid_shade;
border-width: 1px;
@include solid-shade;
img { max-width: 100%; }
@ -30,27 +30,37 @@
.top_box_content,
.middle_box_content,
.bottom_box_content {
padding:15px;
padding: 15px;
word-wrap: break-word;
pre {
background: none !important;
margin:0;
border:none;
padding:0;
margin: 0;
border: none;
padding: 0;
}
}
.top_box_content {
.box-title {
color: $style_color;
font-size: 18px;
font-weight: normal;
line-height: 28px;
}
}
.middle_box_content {
border-radius:0;
border:none;
font-size:12px;
background-color:#f5f5f5;
border:none;
border-top:1px solid #eee;
@include border-radius(0);
border: none;
font-size: 12px;
background-color: #f5f5f5;
border: none;
border-top: 1px solid #eee;
}
.bottom_box_content {
border-top:1px solid #eee;
border-top: 1px solid #eee;
}
}
@ -59,44 +69,52 @@
*
*/
.ui-box {
background:#F9F9F9;
background: #F9F9F9;
margin-bottom: 25px;
@include round-borders-all(4px);
border: 1px solid #eaeaea;
@include border-radius(4px);
border-color: #CCC;
@include solid_shade;
@include solid-shade;
&.white {
background:#fff;
background: #fff;
}
ul {
margin:0;
margin: 0;
}
h5, .title {
padding: 0 10px;
@include round-borders-top(4px);
@include border-radius(4px 4px 0 0);
@include bg-gray-gradient;
border-top: 1px solid #eaeaea;
border-bottom: 1px solid #bbb;
> a {
text-shadow: 0 1px 1px #fff;
}
&.small {
line-height: 28px;
font-size: 14px;
line-height:28px;
line-height: 28px;
text-shadow: 0 1px 1px white;
}
form {
padding:9px 0;
margin:0px;
padding: 9px 0;
margin: 0px;
}
.nav-pills {
li {
padding:3px 0;
&.active a { background-color:$style_color; }
padding: 3px 0;
&.active a { background-color: $style_color; }
a {
border-radius:7px;
@include border-radius(7px);
}
}
}
@ -104,8 +122,8 @@
.bottom {
@include bg-gray-gradient;
@include round-borders-bottom(4px);
border-bottom:none;
@include border-radius(0 0 4px 4px);
border-bottom: none;
border-top: 1px solid #bbb;
}
@ -116,38 +134,25 @@
padding: 5px 20px;
}
.middle_title {
background:#f5f5f5;
background: #f5f5f5;
margin:20px -20px;
padding: 0 20px;
border-top:1px solid #eee;
border-bottom:1px solid #eee;
font-size:14px;
color:#777;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
font-size: 14px;
color: #777;
}
}
.row_title {
font-weight:bold;
color:#444;
font-weight: bold;
color: #444;
&:hover {
color:#444;
text-decoration:underline;
}
}
li, .wll {
padding:10px;
&:first-child {
@include round-borders-top(4px);
border-top:none;
}
&:last-child {
@include round-borders-bottom(4px);
border:none;
color: #444;
text-decoration: underline;
}
}
.ui-box-body {
padding:10px;
padding: 10px;
}
}

View file

@ -1,42 +1,42 @@
.btn {
@include bg-gradient(#f7f7f7, #d5d5d5);
border-color:#aaa;
@include linear-gradient(#f7f7f7, #d5d5d5);
border-color: #aaa;
&:hover {
@include bg-gray-gradient;
border-color:#bbb;
color:#333;
border-color: #bbb;
color: #333;
}
&.primary {
background:#2a79A3;
@include bg-gradient(#47A7b7, #2585b5);
background: #2a79A3;
@include linear-gradient(#47A7b7, #2585b5);
border-color: #2A79A3;
color:#fff;
color: #fff;
text-shadow: 0 1px 1px #268;
&:hover {
background:$blue_link;
color:#fff;
background: $primary_color;
color: #fff;
}
&.disabled {
color:#fff;
background:#29B;
color: #fff;
background: #29B;
}
}
&.btn-info {
background:#5aB9C3;
border-color: $blue_link;
color:#fff;
background: #5aB9C3;
border-color: $primary_color;
color: #fff;
text-shadow: 0 1px 1px #268;
&:hover {
background:$blue_link;
color:#fff;
background: $primary_color;
color: #fff;
}
&.disabled {
color:#fff;
background:#29B;
color: #fff;
background: #29B;
}
}
@ -49,8 +49,8 @@
}
&.disabled {
color:#fff;
background:#2b2;
color: #fff;
background: #2b2;
}
}
@ -60,12 +60,12 @@
}
&.cancel-btn {
float:right;
float: right;
}
&.wide {
padding-left:30px;
padding-right:30px;
padding-left: 30px;
padding-right: 30px;
}
&.danger {
@ -73,7 +73,7 @@
border-color: #BD362F;
&:hover {
color:#fff;
color: #fff;
background: #EE4E49;
}
}
@ -87,24 +87,24 @@
}
&.active {
border-color:#aaa;
background-color:#ccc;
border-color: #aaa;
background-color: #ccc;
}
&.very_small {
font-size:11px;
padding:2px 6px;
font-size: 11px;
padding: 2px 6px;
line-height: 16px;
margin:2px;
margin: 2px;
}
&.grouped {
margin-right:7px;
float:left;
margin-right: 7px;
float: left;
}
&.padded {
margin-right:3px;
padding:4px 10px 4px;
margin-right: 3px;
padding: 4px 10px 4px;
}
}

View file

@ -10,11 +10,6 @@
/** COMMON CLASSES **/
.left { float:left }
.right { float:right!important }
.width-50p { width:50% }
.width-49p { width:49% }
.width-30p { width:30% }
.width-65p { width:65% }
.width-100p { width:100% }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-20 { margin-bottom:20px }
.prepend-top-10 { margin-top:10px }
@ -24,40 +19,42 @@
.lborder { border-left:1px solid #eee }
.no-padding { padding:0 !important; }
.underlined { border-bottom: 1px solid #CCC; }
.no-borders { border:none; }
.no-borders { border: none; }
.vlink { color: $link_color !important; }
.underlined_link { text-decoration: underline; }
.borders { border: 1px solid #ccc; @include shade; }
.hint { font-style: italic; color: #999; }
.light { color: #888 }
.tiny { font-weight: normal }
/** PILLS & TABS**/
.nav-pills a:hover { background-color:#888; }
.nav-pills a:hover { background-color: #888; }
.nav-pills .active a { background-color: $style_color; }
.nav-tabs > li > a, .nav-pills > li > a { color:$style_color; }
.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
.nav.nav-tabs {
li {
> a {
padding:8px 20px;
padding: 8px 20px;
margin-right: 7px;
line-height: 19px;
border-color: #EEE;
color:#888;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color:#888;
text-shadow:0 1px 1px #fff;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i[class^="icon-"] {
line-height:14px;
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color:#333;
color: #333;
}
}
}
@ -69,25 +66,50 @@
.alert-message.error { @extend .alert-error; }
/** AVATARS **/
img.avatar { float:left; margin-right:12px; width:40px; border:1px solid #ddd; padding:1px; }
img.avatar.s16 { width:16px; height:16px; margin-right:6px; }
img.avatar.s24 { width:24px; height:24px; margin-right:8px; }
img.avatar.s32 { width:32px; height:32px; margin-right:10px; }
img.lil_av { padding-left: 4px; padding-right:3px; }
img.avatar { float: left; margin-right: 12px; width: 40px; border: 1px solid #ddd; padding: 1px; }
img.avatar.s16 { width: 16px; height: 16px; margin-right: 6px; }
img.avatar.s24 { width: 24px; height: 24px; margin-right: 8px; }
img.avatar.s32 { width: 32px; height: 32px; margin-right: 10px; }
img.lil_av { padding-left: 4px; padding-right: 3px; }
img.small { width: 80px; }
/** HELPERS **/
.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; }
.nothing_here_message {
text-align: center;
padding: 20px;
color: #666;
font-weight: normal;
font-size: 16px;
line-height: 36px;
}
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;
padding-left: 25px;
@include border-radius(4px);
border:1px solid #ccc;
border: 1px solid #ccc;
}
input[type='text'].danger {
background: #F2DEDE!important;
border-color: #D66;
text-shadow: 0 1px 1px #fff
}
fieldset legend { font-size: 17px; }
/** PAGINATION **/
.gitlab_pagination {
span a { color: $link_color; }
.prev, .next, .current, .page a {
padding: 10px;
}
.current {
border-bottom: 2px solid $style_color;
}
}

View file

@ -3,9 +3,9 @@
*
*/
.file_holder {
border:1px solid #BBB;
margin-bottom:1em;
@include solid_shade;
border: 1px solid #BBB;
margin-bottom: 1em;
@include solid-shade;
.file_title {
border-bottom: 1px solid #bbb;
@ -16,47 +16,51 @@
text-align: left;
color: #666;
padding: 9px 10px;
height:18px;
height: 18px;
.options {
float:right;
float: right;
margin-top: -5px;
}
.file_name {
color:$style_color;
font-size:14px;
color: $style_color;
font-size: 14px;
text-shadow: 0 1px 1px #fff;
small {
color:#999;
font-size:13px;
color: #999;
font-size: 13px;
}
}
}
.file_content {
background:#fff;
background: #fff;
font-size: 11px;
&.wiki {
font-size: 13px;
code {
padding:0 4px;
padding: 0 4px;
}
padding:20px;
h1, h2 {
line-height: 46px;
}
h3, h4 {
line-height: 40px;
padding: 20px;
h1 { font-size: 26px; line-height: 46px; }
h2 { font-size: 22px; line-height: 42px; }
h3 { font-size: 20px; line-height: 40px; }
h4 { font-size: 18px; line-height: 32px; }
h5 { font-size: 16px; line-height: 26px; }
.white .highlight pre {
background: #f5f5f5;
}
}
&.image_file {
background:#eee;
text-align:center;
background: #eee;
text-align: center;
img {
padding:100px;
max-width:300px;
padding: 100px;
max-width: 300px;
}
}
@ -69,60 +73,60 @@
*/
&.blame {
table {
border:none;
box-shadow:none;
margin:0;
border: none;
box-shadow: none;
margin: 0;
}
tr {
border-bottom: 1px solid #eee;
}
td {
&:first-child {
border-left:none;
border-left: none;
}
&:last-child {
border-right:none;
border-right: none;
}
background:#fff;
padding:5px;
background: #fff;
padding: 5px;
}
.author,
.blame_commit {
background:#f5f5f5;
vertical-align:top;
background: #f5f5f5;
vertical-align: top;
}
.lines {
pre {
padding:0;
margin:0;
background:none;
border:none;
padding: 0;
margin: 0;
background: none;
border: none;
}
}
}
&.logs {
background:#eee;
background: #eee;
max-height: 700px;
overflow-y: auto;
ol {
margin-left:40px;
margin-left: 40px;
padding: 10px 0;
border-left: 1px solid #CCC;
margin-bottom:0;
margin-bottom: 0;
background: white;
li {
color:#888;
color: #888;
p {
margin:0;
color:#333;
line-height:24px;
margin: 0;
color: #333;
line-height: 24px;
padding-left: 10px;
}
&:hover {
background:$hover;
background: $hover;
}
}
}
@ -142,8 +146,8 @@
table-layout: fixed;
pre {
background: none;
border: none;
border-radius: 0;
font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
font-size: 12px !important;
line-height: 16px !important;

View file

@ -0,0 +1,7 @@
@font-face{
font-family: Korolev;
src: font-url('korolev-medium-compressed.otf');
}
/** Typo **/
$monospace: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;

View file

@ -1,41 +1,75 @@
/** LISTS **/
ul {
/**
* List li block element #1
*
*/
.wll {
/**
* Well styled list
*
*/
.well-list {
margin: 0;
list-style: none;
li {
background-color: #FFF;
padding: 10px 5px;
padding: 10px;
min-height: 20px;
border-bottom: 1px solid #eee;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
&.smoke { background-color:#f5f5f5; }
&:hover {
background:$hover;
border-bottom:1px solid #ADF;
&.disabled {
color: #888;
}
&:last-child { border:none }
&.smoke { background-color: #f5f5f5; }
&:hover {
background: $hover;
border-bottom: 1px solid #ADF;
}
&:first-child {
@include border-radius(4px 4px 0 0);
border-top: none;
}
&:last-child {
@include border-radius(0 0 4px 4px);
border: none;
}
.author { color: #999; }
p {
padding-top: 1px;
margin:0;
color:#222;
margin: 0;
color: #222;
img {
position:relative;
top:3px;
position: relative;
top: 3px;
}
}
.well-title {
font-size: 14px;
line-height: 18px;
}
}
}
ol, ul {
&.styled {
li {
padding:2px;
padding: 2px;
}
}
}
/** light list with border-bottom between li **/
ul.bordered-list {
margin: 5px 0px;
padding: 0px;
li {
padding: 5px 0;
border-bottom: 1px solid #EEE;
overflow: hidden;
display: block;
margin: 0px;
&:last-child { border:none }
}
}

View file

@ -0,0 +1,69 @@
/**
* Generic mixins
*/
@mixin box-shadow($shadow) {
-webkit-box-shadow: $shadow;
-moz-box-shadow: $shadow;
-ms-box-shadow: $shadow;
-o-box-shadow: $shadow;
box-shadow: $shadow;
}
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
-ms-border-radius: $radius;
-o-border-radius: $radius;
border-radius: $radius;
}
@mixin linear-gradient($from, $to) {
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
background-image: -webkit-linear-gradient($from, $to);
background-image: -moz-linear-gradient($from, $to);
background-image: -o-linear-gradient($from, $to);
}
/**
* Prefilled mixins
* Mixins with fixed values
*/
@mixin bg-light-gray-gradient {
background: #f1f1f1;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
}
@mixin bg-gray-gradient {
background: #eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
}
@mixin bg-dark-gray-gradient {
background: #eee;
background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
}
@mixin shade {
@include box-shadow(0 0 3px #ddd);
}
@mixin solid-shade {
@include box-shadow(0 0 0 3px #f1f1f1);
}
@mixin header-font {
color: $style_color;
text-shadow: 0 1px 1px #FFF;
font-family: 'Korolev', sans-serif;
font-size: 28px;
line-height: 48px;
font-weight: normal;
}

View file

@ -1,13 +1,13 @@
table {
@extend .table;
@extend .table-striped;
@include solid_shade;
border:1px solid #bbb;
width:100%;
@include solid-shade;
border: 1px solid #bbb;
width: 100%;
&.low {
td {
line-height:18px;
line-height: 18px;
}
}
@ -31,8 +31,8 @@ table {
}
td {
border-color:#f1f1f1;
line-height:28px;
border-color: #f1f1f1;
line-height: 28px;
.s16 {
margin-top: 5px;
@ -40,11 +40,11 @@ table {
}
&:first-child {
border-left:1px solid #bbb;
border-left: 1px solid #bbb;
}
&:last-child {
border-right:1px solid #bbb;
border-right: 1px solid #bbb;
}
}
@ -53,10 +53,10 @@ table {
}
&.lite {
border:none;
box-shadow:none;
border: none;
box-shadow: none;
tr, td {
border:none;
border: none;
background:none !important;
}
}

View file

@ -5,11 +5,11 @@
h1, h2, h3, h4, h5, h6 { margin: 0; }
h3, h4, h5, h6 { line-height: 36px; }
h5 { font-size:14px; }
h5 { font-size: 14px; }
h3.page_title {
color:#456;
font-size:20px;
color: #456;
font-size: 20px;
font-weight: normal;
line-height: 28px;
}
@ -25,7 +25,7 @@ pre {
&.dark {
background: #333;
color:#f5f5f5;
color: #f5f5f5;
}
}
@ -37,8 +37,8 @@ a {
outline: none;
color: $link_color;
&:hover {
text-decoration:none;
color: $blue_link;
text-decoration: none;
color: $primary_color;
}
&.btn {
@ -53,27 +53,31 @@ a {
}
&.lined {
text-decoration:underline;
&:hover { text-decoration:underline; }
text-decoration: underline;
&:hover { text-decoration: underline; }
}
&.gray {
color:gray;
color: gray;
}
&.supp_diff_link {
text-align:center;
padding:20px 0;
background:#f1f1f1;
width:100%;
float:left;
text-align: center;
padding: 20px 0;
background: #f1f1f1;
width: 100%;
float: left;
}
&.neib {
margin-right:15px;
margin-right: 15px;
}
}
a:focus {
outline: none;
}
.monospace {
font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
}

View file

@ -0,0 +1,5 @@
/** Colors **/
$primary_color: #2FA0BB;
$link_color: #3A89A3;
$style_color: #474D57;
$hover: #D9EDF7;

View file

@ -1,6 +1,9 @@
.black .lines .highlight {
background: #333;
pre { color: #eee; }
.black .highlight {
background-color: #333;
pre {
color: #eee;
background: inherit;
}
.hll { display: block; background-color: darken($hover, 65%) }
.c { color: #888888; font-style: italic } /* Comment */
@ -21,43 +24,43 @@
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #606060 } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
.kc{font-weight:bold;} /* Keyword.Constant */
.kd{font-weight:bold;} /* Keyword.Declaration */
.kn{font-weight:bold;} /* Keyword.Namespace */
.kp{font-weight:bold;} /* Keyword.Pseudo */
.kr{font-weight:bold;} /* Keyword.Reserved */
.kt{color:#458;font-weight:bold;} /* Keyword.Type */
.kc{font-weight: bold;} /* Keyword.Constant */
.kd{font-weight: bold;} /* Keyword.Declaration */
.kn{font-weight: bold;} /* Keyword.Namespace */
.kp{font-weight: bold;} /* Keyword.Pseudo */
.kr{font-weight: bold;} /* Keyword.Reserved */
.kt{color: #458;font-weight: bold;} /* Keyword.Type */
.m { color: #0000DD; font-weight: bold } /* Literal.Number */
.p { color: #eee; }
.s { color: #0AD; background-color: transparent } /* Literal.String */
.na{color:#008080;} /* Name.Attribute */
.nb{color:#0086B3;} /* Name.Builtin */
.nc{color:#ccc;font-weight:bold;} /* Name.Class */
.no{color:turquoise;} /* Name.Constant */
.ni{color:#800080;}
.ne{color:#900;font-weight:bold;} /* Name.Exception */
.nf{color:#ccc;font-weight:bold;} /* Name.Function */
.nn{color:#79C3E0;font-weight:bold;} /* Name.Namespace */
.nt{color:#fc5;} /* Name.Tag */
.nv{color:#FA4;} /* Name.Variable */
.na{color: #008080;} /* Name.Attribute */
.nb{color: #0086B3;} /* Name.Builtin */
.nc{color: #ccc;font-weight: bold;} /* Name.Class */
.no{color: turquoise;} /* Name.Constant */
.ni{color: #800080;}
.ne{color: #900;font-weight: bold;} /* Name.Exception */
.nf{color: #ccc;font-weight: bold;} /* Name.Function */
.nn{color: #79C3E0;font-weight: bold;} /* Name.Namespace */
.nt{color: #fc5;} /* Name.Tag */
.nv{color: #FA4;} /* Name.Variable */
.py { color: #336699; font-weight: bold } /* Name.Property */
.ow { color: #008800 } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #7AC; font-weight: bold } /* Literal.Number.Float */
.mh { color: #7AC; font-weight: bold } /* Literal.Number.Hex */
.mi {color:#099;} /* Literal.Number.Integer */
.mi {color: #099;} /* Literal.Number.Integer */
.mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.sb { color: #dd2200; background-color: transparent; } /* Literal.String.Backtick */
.sc{color:#d14;} /* Literal.String.Char */
.sc{color: #d14;} /* Literal.String.Char */
.sd { color: #dd2200; background-color: transparent; } /* Literal.String.Doc */
.s2{color:orange;} /* Literal.String.Double */
.se{color:orange;} /* Literal.String.Escape */
.sh{color:orange;} /* Literal.String.Heredoc */
.si{color:orange;} /* Literal.String.Interpol */
.sx{color:orange;} /* Literal.String.Other */
.sr{color:orange;} /* Literal.String.Regex */
.s1{color:orange;} /* Literal.String.Single */
.ss{color:orange;} /* Literal.String.Symbol */
.s2{color: orange;} /* Literal.String.Double */
.se{color: orange;} /* Literal.String.Escape */
.sh{color: orange;} /* Literal.String.Heredoc */
.si{color: orange;} /* Literal.String.Interpol */
.sx{color: orange;} /* Literal.String.Other */
.sr{color: orange;} /* Literal.String.Regex */
.s1{color: orange;} /* Literal.String.Single */
.ss{color: orange;} /* Literal.String.Symbol */
.bp { color: #D58 } /* Name.Builtin.Pseudo */
.vc { color: #336699 } /* Name.Variable.Class */
.vg { color: #dd7700 } /* Name.Variable.Global */

View file

@ -1,6 +1,8 @@
.white .lines .highlight {
background: white;
pre { color: #333; }
.white .highlight {
pre {
background-color: #fff;
color: #333;
}
.hll { display: block; background-color: $hover }
.c { color: #888888; font-style: italic } /* Comment */
@ -20,42 +22,42 @@
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #606060 } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
.kc{font-weight:bold;} /* Keyword.Constant */
.kd{font-weight:bold;} /* Keyword.Declaration */
.kn{font-weight:bold;} /* Keyword.Namespace */
.kp{font-weight:bold;} /* Keyword.Pseudo */
.kr{font-weight:bold;} /* Keyword.Reserved */
.kt{color:#458;font-weight:bold;} /* Keyword.Type */
.kc{font-weight: bold;} /* Keyword.Constant */
.kd{font-weight: bold;} /* Keyword.Declaration */
.kn{font-weight: bold;} /* Keyword.Namespace */
.kp{font-weight: bold;} /* Keyword.Pseudo */
.kr{font-weight: bold;} /* Keyword.Reserved */
.kt{color: #458;font-weight: bold;} /* Keyword.Type */
.m { color: #0000DD; font-weight: bold } /* Literal.Number */
.s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.na{color:#008080;} /* Name.Attribute */
.nb{color:#0086B3;} /* Name.Builtin */
.nc{color:#458;font-weight:bold;} /* Name.Class */
.no{color:#008080;} /* Name.Constant */
.ni{color:#800080;}
.ne{color:#900;font-weight:bold;} /* Name.Exception */
.nf{color:#900;font-weight:bold;} /* Name.Function */
.nn{color:#005;font-weight:bold;} /* Name.Namespace */
.nt{color:#000080;} /* Name.Tag */
.nv{color:#008080;} /* Name.Variable */
.na{color: #008080;} /* Name.Attribute */
.nb{color: #0086B3;} /* Name.Builtin */
.nc{color: #458;font-weight: bold;} /* Name.Class */
.no{color: #008080;} /* Name.Constant */
.ni{color: #800080;}
.ne{color: #900;font-weight: bold;} /* Name.Exception */
.nf{color: #900;font-weight: bold;} /* Name.Function */
.nn{color: #005;font-weight: bold;} /* Name.Namespace */
.nt{color: #000080;} /* Name.Tag */
.nv{color: #008080;} /* Name.Variable */
.py { color: #336699; font-weight: bold } /* Name.Property */
.ow { color: #008800 } /* Operator.Word */
.w { color: #bbbbbb } /* Text.Whitespace */
.mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.mi {color:#099;} /* Literal.Number.Integer */
.mi {color: #099;} /* Literal.Number.Integer */
.mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.sc{color:#d14;} /* Literal.String.Char */
.sc{color: #d14;} /* Literal.String.Char */
.sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.s2{color:#d14;} /* Literal.String.Double */
.se{color:#d14;} /* Literal.String.Escape */
.sh{color:#d14;} /* Literal.String.Heredoc */
.si{color:#d14;} /* Literal.String.Interpol */
.sx{color:#d14;} /* Literal.String.Other */
.sr{color:#d14;} /* Literal.String.Regex */
.s1{color:#d14;} /* Literal.String.Single */
.ss{color:#d14;} /* Literal.String.Symbol */
.s2{color: #d14;} /* Literal.String.Double */
.se{color: #d14;} /* Literal.String.Escape */
.sh{color: #d14;} /* Literal.String.Heredoc */
.si{color: #d14;} /* Literal.String.Interpol */
.sx{color: #d14;} /* Literal.String.Other */
.sr{color: #d14;} /* Literal.String.Regex */
.s1{color: #d14;} /* Literal.String.Single */
.ss{color: #d14;} /* Literal.String.Symbol */
.bp { color: #003388 } /* Name.Builtin.Pseudo */
.vc { color: #336699 } /* Name.Variable.Class */
.vg { color: #dd7700 } /* Name.Variable.Global */
@ -63,7 +65,5 @@
}
.shadow {
-webkit-box-shadow:0 5px 15px #000;
-moz-box-shadow:0 5px 15px #000;
box-shadow:0 5px 15px #000;
@include box-shadow(0 5px 15px #000);
}

View file

@ -0,0 +1,257 @@
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
* jQuery UI CSS Framework 1.8.7
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Arial,sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #CCC; background: #ffffff; color: #4F4F4F; }
.ui-widget-content a { color: #4F4F4F; }
.ui-widget-header { border: 1px solid #B6B6B6; color: #4F4F4F; font-weight: bold; }
.ui-widget-header {
background: #ededed url(bg_fallback.png) 0 0 repeat-x; /* Old browsers */
background: -moz-linear-gradient(top, #ededed 0%, #c4c4c4 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ededed), color-stop(100%,#c4c4c4)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* IE10+ */
background: linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* W3C */
}
.ui-widget-header a { color: #4F4F4F; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #B6B6B6; font-weight: normal; color: #4F4F4F; }
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {
background: #ededed url(bg_fallback.png) 0 0 repeat-x; /* Old browsers */
background: -moz-linear-gradient(top, #ededed 0%, #c4c4c4 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ededed), color-stop(100%,#c4c4c4)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* IE10+ */
background: linear-gradient(top, #ededed 0%,#c4c4c4 100%); /* W3C */
-webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
-moz-box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
}
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #4F4F4F; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #9D9D9D; font-weight: normal; color: #313131; }
.ui-state-hover a, .ui-state-hover a:hover { color: #313131; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active {
outline: none;
color: #1c4257; border: 1px solid #7096ab;
background: #ededed url(bg_fallback.png) 0 -50px repeat-x; /* Old browsers */
background: -moz-linear-gradient(top, #b9e0f5 0%, #92bdd6 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b9e0f5), color-stop(100%,#92bdd6)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* IE10+ */
background: linear-gradient(top, #b9e0f5 0%,#92bdd6 100%); /* W3C */
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #313131; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight { border: 1px solid #d2dbf4; background: #f4f8fd; color: #0d2054; -moz-border-radius: 0 !important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error { border: 1px solid #e2d0d0; background: #fcf0f0; color: #280b0b; -moz-border-radius: 0 !important; -webkit-border-radius: 0 !important; border-radius: 0 !important; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(ui-icons_454545_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(ui-icons_454545_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon { background: url(icon_sprite.png) -16px 0 no-repeat !important; }
.ui-state-highlight .ui-icon, .ui-state-error .ui-icon { margin-top: -1px; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { background: #262b33; opacity: .70;filter:Alpha(Opacity=70); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #000000; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
/*
* jQuery UI Selectable 1.8.7
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Selectable#theming
*/
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*
* jQuery UI Autocomplete 1.8.7
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Autocomplete#theming
*/
.ui-autocomplete {
position: absolute; cursor: default; z-index: 3;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
-moz-box-shadow: 0 1px 5px rgba(0,0,0,0.3);
-webkit-box-shadow: 0 1px 5px rgba(0,0,0,0.3);
box-shadow: 0 1px 5px rgba(0,0,0,0.3);
}
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/*
* jQuery UI Menu 1.8.7
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Menu#theming
*/
.ui-menu {
list-style:none;
padding: 1px;
margin: 0;
display:block;
float: left;
}
.ui-menu .ui-menu {
margin-top: -3px;
}
.ui-menu .ui-menu-item {
margin:0;
padding: 0;
zoom: 1;
float: left;
clear: left;
width: 100%;
}
.ui-menu .ui-menu-item a {
text-decoration:none;
display:block;
padding:.2em .4em;
line-height:1.5;
zoom:1;
color: #666;
font-size: 13px;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
font-weight: normal;
margin: -1px;
background: #D9EDF7;
color: #3A89A3;
text-shadow: 0px 1px 1px #fff;
border: none;
border: 1px solid #ADE;
cursor: pointer;
font-weight: bold;
}
/*
* jQuery UI Datepicker 1.8.7
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Datepicker#theming
*/
.ui-datepicker {
width: 17em;
padding: 0;
display: none;
border-color: #DDDDDD;
border: none;
box-shadow: none;
}
.ui-datepicker .ui-datepicker-header {
position:relative;
padding:.35em 0;
border: none;
border-bottom: 1px solid #B6B6B6;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
margin-bottom: 10px;
border: 1px solid #bbb;
-webkit-box-shadow: 0 0 0 3px #F1F1F1;
-moz-box-shadow: 0 0 0 3px #f1f1f1;
-ms-box-shadow: 0 0 0 3px #f1f1f1;
-o-box-shadow: 0 0 0 3px #f1f1f1;
box-shadow: 0 0 0 3px #F1F1F1;
}
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 6px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { border: 1px none; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev span { background-position: 0px -32px !important; }
.ui-datepicker .ui-datepicker-next span { background-position: -16px -32px !important; }
.ui-datepicker .ui-datepicker-prev-hover span { background-position: 0px -48px !important; }
.ui-datepicker .ui-datepicker-next-hover span { background-position: -16px -48px !important; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; background: url(icon_sprite.png) no-repeat; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; font-size: 12px; text-shadow: 0 1px 0 rgba(255,255,255,0.6); }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; line-height: 24px; background-color: #FFF!important; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
.ui-datepicker table .ui-state-highlight { border-color: #ADE; }
.ui-datepicker-calendar .ui-state-default { background: transparent; border-color: #FFF; }
.ui-datepicker-calendar .ui-state-active { background: #D9EDF7; border-color: #ADE; color: #3A89A3; font-weight: bold; text-shadow: 0 1px 1px #fff; }

View file

@ -1,204 +0,0 @@
/** Override bootstrap variables **/
$baseFontSize: 13px !default;
$baseLineHeight: 18px !default;
@import "bootstrap";
@import "bootstrap-responsive";
@import 'font-awesome';
/** GitLab colors **/
$link_color: #3A89A3;
$blue_link: #2FA0BB;
$style_color: #474D57;
$hover: #D9EDF7;
$hover_border: #ADF;
/** GitLab Fonts **/
@font-face { font-family: Korolev; src: font-url('korolev-medium-compressed.otf'); }
$monospace: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono', 'lucida console', monospace;
/** MIXINS **/
@mixin shade {
-moz-box-shadow: 0 0 3px #ddd;
-webkit-box-shadow: 0 0 3px #ddd;
box-shadow: 0 0 3px #ddd;
}
@mixin solid_shade {
-moz-box-shadow: 0 0 0 3px #f1f1f1;
-webkit-box-shadow: 0 0 0 3px #f1f1f1;
box-shadow: 0 0 0 3px #f1f1f1;
}
@mixin border-radius($radius) {
-moz-border-radius: $radius;
-webkit-border-radius: $radius;
border-radius: $radius;
}
@mixin round-borders-bottom($radius) {
border-top: 1px solid #eaeaea;
-moz-border-radius-bottomright: $radius;
-moz-border-radius-bottomleft: $radius;
border-bottom-right-radius: $radius;
border-bottom-left-radius: $radius;
-webkit-border-bottom-left-radius: $radius;
-webkit-border-bottom-right-radius: $radius;
}
@mixin round-borders-top($radius) {
border-top: 1px solid #eaeaea;
-moz-border-radius-topright: $radius;
-moz-border-radius-topleft: $radius;
border-top-right-radius: $radius;
border-top-left-radius: $radius;
-webkit-border-top-left-radius: $radius;
-webkit-border-top-right-radius: $radius;
}
@mixin round-borders-all($radius) {
border: 1px solid #eaeaea;
-moz-border-radius: $radius;
-webkit-border-radius: $radius;
border-radius: $radius;
}
@mixin bg-gradient($from, $to) {
background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
background-image: -webkit-linear-gradient($from, $to);
background-image: -moz-linear-gradient($from, $to);
background-image: -o-linear-gradient($from, $to);
}
@mixin bg-light-gray-gradient {
background:#f1f1f1;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #f5f5f5), to(#e1e1e1));
background-image: -webkit-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
background-image: -moz-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
background-image: -o-linear-gradient(#f5f5f5 6.6%, #e1e1e1);
}
@mixin bg-gray-gradient {
background:#eee;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -o-linear-gradient(#eee 6.6%, #dfdfdf);
}
@mixin bg-dark-gray-gradient {
background:#eee;
background-image: -webkit-linear-gradient(#e9e9e9, #d7d7d7);
background-image: -moz-linear-gradient(#e9e9e9, #d7d7d7);
background-image: -o-linear-gradient(#e9e9e9, #d7d7d7);
}
/**
* Header of application.
* Contain application logo, search panel, profile icon
*/
@import "sections/header.scss";
/**
* Navigation menu of application.
* Panel with links to pages depends on project, profile or admin area
*/
@import "sections/nav.scss";
/**
* This file represent some UI that can be changed
* during web app restyle or theme select.
*
* Next items should be placed there
* - link, button colors
* - header restyles
* - main menu restyles
*
*/
@import "themes/ui_basic.scss";
/**
* UI themes:
*/
@import "themes/ui_mars.scss";
@import "themes/ui_modern.scss";
@import "themes/ui_gray.scss";
@import "themes/ui_color.scss";
/**
* GitLab bootstrap.
* Overrides some styles of twitter bootstrap.
* Also give some common classes for GitLab app
*/
@import "gitlab_bootstrap/common.scss";
@import "gitlab_bootstrap/typography.scss";
@import "gitlab_bootstrap/buttons.scss";
@import "gitlab_bootstrap/blocks.scss";
@import "gitlab_bootstrap/files.scss";
@import "gitlab_bootstrap/tables.scss";
@import "gitlab_bootstrap/lists.scss";
/**
* Most of application styles placed here.
* This file represent common UI that should not be changed between themes
* or project restyling like form width or user avatar class or commit title
*
* TODO: clean it
*/
@import "common.scss";
/**
* Styles related to specific part of app
*/
@import "sections/commits.scss";
@import "sections/issues.scss";
@import "sections/projects.scss";
@import "sections/merge_requests.scss";
@import "sections/graph.scss";
@import "sections/events.scss";
@import "sections/themes.scss";
/**
* This scss file redefine chozen selectbox styles for
* project Branch/Tag select element
*/
@import "ref_select.scss";
/**
* Code (files list) styles. Browsing project files there
*/
@import "sections/tree.scss";
/**
* This file represent notes(comments) styles
*/
@import "sections/notes.scss";
/**
* This file represent profile styles
*/
@import "sections/profile.scss";
/**
* Devise styles
*/
@import "sections/login.scss";
/**
* CODE HIGHTLIGHT BASE
*
*/
@import "highlight/white.scss";
/**
* CODE HIGHTLIGHT DARK schema
*
*/
@import "highlight/dark.scss";
/**
* File Editor styles
*
*/
@import "sections/editor.scss";

View file

@ -1,6 +1,6 @@
/** Branch/tag selector **/
.project-refs-form {
margin:0;
margin: 0;
span {
background:none !important;
position:static !important;
@ -9,7 +9,7 @@
}
}
.project-refs-select {
width:120px;
width: 120px;
}
.project-refs-form .chzn-container {
@ -21,10 +21,10 @@
.chzn-drop {
min-width: 400px;
.chzn-results {
max-height:300px;
max-height: 300px;
}
.chzn-search input {
min-width:365px;
min-width: 365px;
}
}
}
@ -33,21 +33,19 @@
.chzn-container {
.chzn-search {
input:focus {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
@include box-shadow(none);
}
}
.chzn-drop {
margin:7px 0;
margin: 7px 0;
min-width: 200px;
border: 1px solid #bbb;
border-radius:0;
@include border-radius(0);
.chzn-results {
margin-top: 5px;
max-height:300px;
max-height: 300px;
.group-result {
color: $style_color;
@ -55,7 +53,7 @@
padding: 8px;
}
.active-result {
border-radius: 0;
@include border-radius(0);
&.highlighted {
background: $hover;
@ -71,7 +69,7 @@
.chzn-search {
@include bg-gray-gradient;
input {
min-width:165px;
min-width: 165px;
border-color: #CCC;
}
}
@ -81,8 +79,8 @@
@include bg-light-gray-gradient;
div {
background:transparent;
border-left:none;
background: transparent;
border-left: none;
}
span {

View file

@ -6,14 +6,14 @@
.commit-title {
line-height: 26px;
margin:0;
margin: 0;
}
.commit-description {
font-size: 14px;
border: none;
background-color: white;
padding-top:10px;
padding-top: 10px;
}
.browse-button {
@ -28,9 +28,9 @@
@extend .clearfix;
.sha-block {
text-align:right;
text-align: right;
&:first-child {
padding-bottom:6px;
padding-bottom: 6px;
}
a {
@ -49,10 +49,10 @@
.author a,
.committer a {
font-size:14px;
line-height:22px;
text-shadow:0 1px 1px #fff;
color:#777;
font-size: 14px;
line-height: 22px;
text-shadow: 0 1px 1px #fff;
color: #777;
&:hover {
color: #999;
}
@ -70,15 +70,16 @@
*
*/
.diff_file {
border:1px solid #CCC;
margin-bottom:1em;
border: 1px solid #CCC;
margin-bottom: 1em;
.diff_file_header {
@extend .clearfix;
padding: 5px 5px 5px 10px;
color: #555;
border-bottom:1px solid #CCC;
border-bottom: 1px solid #CCC;
background: #eee;
// TODO Replace with linear-gradient mixin
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
background-image: -webkit-linear-gradient(#eee 6.6%, #dfdfdf);
background-image: -moz-linear-gradient(#eee 6.6%, #dfdfdf);
@ -86,7 +87,7 @@
> span {
font-family: $monospace;
font-size:14px;
font-size: 14px;
line-height: 30px;
}
@ -104,36 +105,36 @@
}
}
.diff_file_content {
overflow:auto;
overflow-y:hidden;
background:#fff;
color:#333;
overflow: auto;
overflow-y: hidden;
background: #fff;
color: #333;
font-size: 12px;
font-family: $monospace;
.old{
span.idiff{
background-color:#FAA;
background-color: #FAA;
}
}
.new{
span.idiff{
background-color:#AFA;
background-color: #AFA;
}
}
table {
td {
line-height:18px;
line-height: 18px;
}
}
}
.diff_file_content_image {
background:#eee;
text-align:center;
background: #eee;
text-align: center;
.image {
display: inline-block;
margin:50px;
max-width:400px;
margin: 50px;
max-width: 400px;
img{
background: url('trans_bg.gif');
@ -158,7 +159,7 @@
&.img_compared {
.image {
max-width:300px;
max-width: 300px;
}
}
}
@ -166,46 +167,46 @@
.diff_file_content{
table {
border:none;
margin:0px;
padding:0px;
border: none;
margin: 0px;
padding: 0px;
tr {
td {
font-size:12px;
font-size: 12px;
}
}
}
.old_line, .new_line {
margin:0px;
padding:0px;
border:none;
background:#EEE;
color:#666;
margin: 0px;
padding: 0px;
border: none;
background: #EEE;
color: #666;
padding: 0px 5px;
border-right: 1px solid #ccc;
text-align:right;
min-width:35px;
max-width:35px;
width:35px;
text-align: right;
min-width: 35px;
max-width: 35px;
width: 35px;
moz-user-select: none;
-khtml-user-select: none;
user-select: none;
a {
float:left;
width:35px;
font-weight:normal;
color:#666;
float: left;
width: 35px;
font-weight: normal;
color: #666;
&:hover {
text-decoration:underline;
text-decoration: underline;
}
}
}
.line_content {
white-space:pre;
height:14px;
margin:0px;
padding:0px;
border:none;
white-space: pre;
height: 14px;
margin: 0px;
padding: 0px;
border: none;
&.new {
background: #CFD;
}
@ -213,8 +214,8 @@
background: #FDD;
}
&.matched {
color:#ccc;
background:#fafafa;
color: #ccc;
background: #fafafa;
}
}
}
@ -228,32 +229,30 @@
/** COMMIT ROW **/
.commit {
@extend .wll;
.browse_code_link_holder {
@extend .span2;
float:right;
float: right;
}
.committed_ago {
float:right;
float: right;
@extend .cgray;
}
.notes_count {
float:right;
float: right;
margin: -6px 8px 6px;
}
code {
background:#FCEEC1;
color:$style_color;
background: #FCEEC1;
color: $style_color;
}
.commit_short_id {
float:left;
float: left;
@extend .lined;
min-width:65px;
min-width: 65px;
font-family: $monospace;
}
@ -294,11 +293,24 @@
}
.label_commit {
@include round-borders-all(4px);
padding:2px 4px;
border:none;
font-size:13px;
@include border-radius(4px);
padding: 2px 4px;
font-size: 13px;
background: #474D57;
color:#fff;
color: #fff;
font-family: $monospace;
}
.commits-compare-switch{
background: url("switch_icon.png") no-repeat center center;
width: 16px;
height: 18px;
text-indent: -9999px;
float: left;
margin-right: 9px;
border: 1px solid #DDD;
@include border-radius(4px);
padding: 4px;
background-color: #EEE;
}

View file

@ -1,7 +1,7 @@
.file-editor {
#editor{
border: none;
border-radius: 0;
@include border-radius(0);
height: 500px;
margin: 0;
padding: 0;

View file

@ -4,25 +4,25 @@
*/
.event_label {
&.pushed {
padding:0 2px;
padding: 0 2px;
}
&.opened {
padding:0 2px;
padding: 0 2px;
}
&.closed {
padding:0 2px;
padding: 0 2px;
}
&.merged {
padding:0 2px;
padding: 0 2px;
}
&.left,
&.joined {
padding:0 2px;
float:none;
padding: 0 2px;
float: none;
}
}
@ -31,49 +31,51 @@
*
*/
.event-item {
min-height:40px;
border-bottom:1px solid #eee;
border-bottom: 1px solid #eee;
.event-title {
color:#333;
color: #333;
font-weight: bold;
.author_name {
color:#333;
color: #333;
}
}
.event-body {
p {
color:#555;
color: #555;
padding-top: 5px;
}
.event-info {
color:#666;
color: #666;
}
}
.avatar {
width:32px;
position: relative;
top: -3px;
}
.event_icon {
position: relative;
float: right;
border: 1px solid #EEE;
padding: 5px;
@include border-radius(5px);
background: #F9F9F9;
margin-left: 10px;
top: -6px;
img {
width:20px;
width: 20px;
}
}
ul {
margin-left:50px;
margin-bottom:5px;
margin-left: 50px;
margin-bottom: 5px;
.avatar {
width:18px;
margin-top:3px;
width: 18px;
margin-top: 3px;
}
}
padding: 15px 5px;
padding: 16px 5px;
&:last-child { border:none }
.wll:hover { background:none }
.event_commits {
margin-top: 5px;
@ -81,9 +83,9 @@
li {
&.commit {
background: transparent;
padding:3px;
border:none;
font-size:12px;
padding: 3px;
border: none;
font-size: 12px;
}
&.commits-stat {
display: block;
@ -98,15 +100,15 @@
*
*/
.event_lp {
color:#777;
padding:10px;
min-height:22px;
color: #777;
padding: 10px;
min-height: 22px;
border-left: 5px solid #5AB9C3;
margin-bottom:20px;
background:#f9f9f9;
margin-bottom: 20px;
background: #f9f9f9;
.avatar {
width:24px;
width: 24px;
}
.btn-new-mr {
@ -133,7 +135,7 @@
background: #f9f9f9;
margin-bottom: 10px;
img {
width:20px;
width: 20px;
}
&.inactive {

View file

@ -1,10 +1,10 @@
.graph_holder {
border: 1px solid #aaa;
padding:1px;
padding: 1px;
h4 {
padding:0 10px;
padding: 0 10px;
border-bottom: 1px solid #bbb;
@include bg-gray-gradient;
}

View file

@ -5,7 +5,7 @@
header {
&.navbar-gitlab {
.navbar-inner {
height:45px;
height: 45px;
padding: 5px;
background: #F1F1F1;
@ -24,8 +24,8 @@ header {
}
}
z-index:10;
/*height:60px;*/
z-index: 10;
/*height: 60px;*/
/**
*
@ -33,25 +33,20 @@ header {
*
*/
.app_logo {
width:170px;
float:left;
width: 170px;
float: left;
a {
float:left;
float: left;
padding: 0px;
h1 {
width:90px;
width: 90px;
background: url('logo_dark.png') no-repeat 0px 2px;
float:left;
margin-left:2px;
font-size:30px;
line-height:48px;
font-weight:normal;
color:$style_color;
text-shadow: 0 1px 1px #FFF;
padding-left:45px;
height:40px;
font-family: 'Korolev', sans-serif;
float: left;
margin-left: 2px;
padding-left: 45px;
height: 40px;
@include header-font;
}
}
}
@ -62,16 +57,11 @@ header {
*
*/
.project_name {
position:relative;
float:left;
margin:0;
margin-right:30px;
font-size:30px;
line-height:48px;
font-weight:normal;
color:$style_color;
text-shadow: 0 1px 1px #FFF;
font-family: 'Korolev', sans-serif;
position: relative;
float: left;
margin: 0;
margin-right: 30px;
@include header-font;
}
/**
@ -81,7 +71,7 @@ header {
*/
.search {
margin-right: 45px;
margin-left:10px;
margin-left: 10px;
margin-top: 2px;
.search-input {
@ -89,11 +79,11 @@ header {
background-image: url("icon-search.png");
background-repeat: no-repeat;
background-position: 10px;
padding-left:25px;
padding-left: 25px;
font-size: 13px;
@include border-radius(3px);
border:1px solid #c6c6c6;
box-shadow:none;
border: 1px solid #c6c6c6;
box-shadow: none;
&:focus {
@extend .span3;
}
@ -122,7 +112,7 @@ header {
width: 28px;
height: 28px;
display: block;
top:1px;
top: 1px;
&:after {
content: " ";
display: block;
@ -132,12 +122,15 @@ header {
left: 0;
bottom: 0;
float: right;
border-radius: 5px;
@include border-radius(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-bottom: 0;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, 0.15)), to(rgba(0, 0, 0, 0.25))), -webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(255, 255, 255, 0)), color-stop(0.5, rgba(255, 255, 255, 0.1)), color-stop(0.501, rgba(255, 255, 255, 0)), color-stop(1, rgba(255, 255, 255, 0)));
background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)), -moz-linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
background: linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)), linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255, 255, 255, 0.15)), to(rgba(0, 0, 0, 0.25))),
-webkit-gradient(linear, left top, right bottom, color-stop(0, rgba(255, 255, 255, 0)), color-stop(0.5, rgba(255, 255, 255, 0.1)), color-stop(0.501, rgba(255, 255, 255, 0)), color-stop(1, rgba(255, 255, 255, 0)));
background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)),
-moz-linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
background: linear-gradient(top, rgba(255, 255, 255, 0.15), rgba(0, 0, 0, 0.25)),
linear-gradient(left top, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 50%, rgba(255, 255, 255, 0) 50%, rgba(255, 255, 255, 0));
-webkit-background-origin: border-box;
-moz-background-origin: border;
background-origin: border-box; } } }
@ -149,7 +142,7 @@ header {
display: block; } }
.account-links {
border-radius: 5px;
@include border-radius(5px);
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
position: relative;
&:before {
@ -169,7 +162,7 @@ header {
display: none;
z-index: 100000;
@include border-radius(4px);
width: 100px;
width: 130px;
position: absolute;
right: 5px;
top: 38px;
@ -178,13 +171,13 @@ header {
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
a {
color: #fff;
padding: 7px 10px;
padding: 12px 15px;
display: block;
text-shadow: none;
border-bottom: 1px solid #666;
font-size: 12px;
&:hover {
color:#fff;
color: #fff;
background: #333;
}
}
@ -197,20 +190,13 @@ header {
.account-links a {
&:first-child {
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
border-top-left-radius: 5px;
border-top-right-radius: 5px; }
@include border-radius(5px 5px 0 0);
}
&:last-child {
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-moz-border-radius-bottomleft: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
border-bottom: 0; } }
@include border-radius(0 0 5px 5px);
border-bottom: 0;
}
}
@ -248,13 +234,13 @@ header {
a {
h1 {
background: url('logo_white.png') no-repeat 0px 2px;
color:#fff;
color: #fff;
text-shadow: 0 1px 1px #111;
}
}
}
.project_name {
color:#fff;
color: #fff;
text-shadow: 0 1px 1px #111;
}
}

View file

@ -3,7 +3,7 @@
.issue_title {
@extend .top_box_content;
.clearfix {
margin-bottom:0px;
margin-bottom: 0px;
input {
@extend .span8;
}
@ -11,14 +11,14 @@
}
.issue_middle_block {
@extend .middle_box_content;
height:30px;
height: 30px;
.issue_assignee {
@extend .span6;
float:left;
float: left;
}
.issue_milestone {
@extend .span4;
float:left;
float: left;
}
}
.issue_description {
@ -28,31 +28,31 @@
.issues_table {
.issue {
padding:7px 10px;
padding: 7px 10px;
.issue_check {
float:left;
float: left;
padding: 8px 0;
padding-right: 8px;
min-width: 15px;
}
p {
padding-top:0;
padding-bottom:2px;
padding-top: 0;
padding-bottom: 2px;
}
img.avatar {
width:32px;
margin-top:1px;
width: 32px;
margin-top: 1px;
}
}
}
input.check_all_issues {
float:left;
float: left;
padding: 0;
margin:0;
margin: 0;
margin-right: 10px;
position: relative;
top: 8px;
@ -82,16 +82,16 @@ input.check_all_issues {
}
}
@media (min-width: 800px) { .issues_filters select { width:160px; } }
@media (min-width: 1000px) { .issues_filters select { width:200px; } }
@media (min-width: 1200px) { .issues_filters select { width:220px; } }
@media (min-width: 800px) { .issues_filters select { width: 160px; } }
@media (min-width: 1000px) { .issues_filters select { width: 200px; } }
@media (min-width: 1200px) { .issues_filters select { width: 220px; } }
#issues-table-holder {
.issues_filters {
form {
padding:0;
margin:0;
padding: 0;
margin: 0;
margin-top:7px
}
}
@ -99,48 +99,25 @@ input.check_all_issues {
.issues_bulk_update {
margin: 0;
form {
padding:0;
margin:0;
padding: 0;
margin: 0;
margin-top:7px
}
.update_selected_issues {
position:relative;
position: relative;
top:-2px;
margin-left:4px;
float:left;
margin-left: 4px;
float: left;
}
.update_issues_text {
padding:3px;
padding: 3px;
line-height: 18px;
float:left;
float: left;
}
}
}
#update_status {
width:100px;
}
/**
* Milestones list
*
*/
.milestone {
@extend .wll;
}
/**
* Fix milestone calendar
*/
.ui-datepicker {
border:none;
box-shadow:none;
.ui-datepicker-header {
@include solid_shade;
margin-bottom:10px;
border:1px solid #bbb;
}
width: 100px;
}

View file

@ -1,13 +1,13 @@
/* Login Page */
body.login-page{
padding-top: 10%;
background:#f1f1f1;
background: #f1f1f1;
}
.login-box{
width: 304px;
position: relative;
border-radius: 5px;
@include border-radius(5px);
margin: auto;
padding: 20px;
background: white;
@ -18,25 +18,15 @@ body.login-page{
display: block;
}
.login-box input.text{background-color: #f1f1f1; font-size: 16px; border-radius: 0; padding: 14px 10px; width: 280px}
.login-box input.text{background-color: #f1f1f1; font-size: 16px; @include border-radius(0); padding: 14px 10px; width: 280px}
.login-box input.text.top{
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
margin-bottom:0px;
@include border-radius(5px 5px 0 0);
margin-bottom: 0px;
}
.login-box input.text.bottom{
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-moz-border-radius-bottomleft: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
@include border-radius(0 0 5px 5px);
border-top: 0;
margin-bottom: 20px;
}

View file

@ -5,10 +5,10 @@
.mr_branch_box {
@extend .ui-box;
margin-bottom:20px;
margin-bottom: 20px;
.body {
background:#f1f1f1;
background: #f1f1f1;
}
}
@ -23,31 +23,30 @@
}
form {
margin-bottom:0;
margin-bottom: 0;
.clearfix {
margin-bottom:0;
margin-bottom: 0;
}
}
.accept_group {
float:left;
float: left;
border: 1px solid #ADA;
padding: 2px;
@include border-radius(5px);
border-radius: 5px;
background: #CEB;
.accept_merge_request {
font-size:13px;
float:left;
font-size: 13px;
float: left;
}
.remove_branch_holder {
margin-left:20px;
margin-right:10px;
float:left;
margin-left: 20px;
margin-right: 10px;
float: left;
}
label {
color:#444;
color: #444;
}
}
@ -60,15 +59,15 @@
.mr_nav_tabs {
li {
a {
font-weight:bold;
padding:8px 20px;
text-align:center;
font-weight: bold;
padding: 8px 20px;
text-align: center;
}
}
}
li.merge_request {
padding:7px 10px;
padding: 7px 10px;
img.avatar {
width: 32px;
margin-top: 1px;
@ -85,35 +84,35 @@ li.merge_request {
}
.label_branch {
@include round-borders-all(4px);
padding:2px 4px;
border:none;
font-size:14px;
@include border-radius(4px);
padding: 2px 4px;
border: none;
font-size: 14px;
background: #474D57;
color:#fff;
color: #fff;
font-family: 'Menlo', 'Liberation Mono', 'Consolas', 'Courier New', 'andale mono','lucida console',monospace;
}
.mr_source_commit,
.mr_target_commit {
.commit {
margin:0;
padding:0;
margin: 0;
padding: 0;
padding: 5px;
margin-bottom: 5px;
.avatar { position:relative }
.row_title {
color:#444;
color: #444;
}
.commit-author-name,
.dash,
.committed_ago,
.browse_code_link_holder {
display:none;
display: none;
}
list-style:none;
list-style: none;
&:hover {
background:none;
background: none;
}
}
}
@ -126,20 +125,14 @@ li.merge_request {
@extend .main_box;
.merge_requests_middle_box {
@extend .middle_box_content;
height:30px;
height: 30px;
.merge_requests_assignee {
@extend .span6;
float:left;
float: left;
}
.merge_requests_milestone {
@extend .span4;
float:left;
float: left;
}
}
}
.status-badge {
height: 32px;
width: 100%;
@include border-radius(5px);
}

View file

@ -3,64 +3,40 @@
*
*/
ul.main_menu {
border-radius: 4px;
margin: auto;
margin:30px 0;
border:1px solid #BBB;
height:37px;
@include bg-gray-gradient;
position:relative;
overflow:hidden;
@include shade;
margin: 30px 0;
margin-top: 10px;
border-bottom: 1px solid #DDD;
height: 37px;
position: relative;
overflow: hidden;
.count {
position: relative;
top: -1px;
display: inline-block;
height: 15px;
margin: 0 0 0 5px;
padding: 0 8px 1px 8px;
height: auto;
font-size: 0.82em;
line-height: 14px;
text-align: center;
color: #777;
background: #f2f2f2;
border-top: 1px solid #CCC;
border-radius: 8px;
-moz-border-radius: 8px;
top: -1px;
display: inline-block;
height: 15px;
margin: 0 0 0 5px;
padding: 0 8px 1px 8px;
height: auto;
font-size: 0.82em;
line-height: 14px;
text-align: center;
color: #777;
}
.label {
background:$hover;
text-shadow:none;
color:$style_color;
background: $hover;
text-shadow: none;
color: $style_color;
}
li {
list-style-type: none;
margin: 0;
display: table-cell;
width: 1%;
border-right: 1px solid #DDD;
border-left: 1px solid #EEE;
border-bottom:2px solid #CFCFCF;
&:first-child{
-webkit-border-top-left-radius: 4px;
-webkit-border-bottom-left-radius: 4px;
-moz-border-radius-topleft: 4px;
-moz-border-radius-bottomleft: 4px;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
border-left: 0;
}
&.active {
background-color:#D5D5D5;
border-right: 1px solid #BBB;
border-left: 1px solid #BBB;
border-radius: 0 0 1px 1px;
&:first-child{
border-bottom:none;
border-left:none;
border-bottom: 2px solid #474D57;
a {
color: $style_color;
}
}
@ -68,10 +44,10 @@ ul.main_menu {
a {
background: url(home_icon.PNG) no-repeat center center;
text-indent:-9999px;
min-width:20px;
min-width: 20px;
img {
position:relative;
top:4px;
position: relative;
top: 4px;
}
}
}
@ -79,12 +55,12 @@ ul.main_menu {
a {
display: block;
text-align: center;
font-weight:bold;
height:35px;
line-height:36px;
color: $style_color;
text-shadow:0 1px 1px white;
padding:0 10px;
font-weight: normal;
height: 35px;
line-height: 36px;
color: #777;
text-shadow: 0 1px 1px white;
padding: 0 10px;
}
}
/*

View file

@ -4,30 +4,30 @@
*/
#notes-list,
#new-notes-list {
display:block;
list-style:none;
margin:0px;
padding:0px;
display: block;
list-style: none;
margin: 0px;
padding: 0px;
}
.issue_notes,
.wiki_notes {
.note_content {
float:left;
width:400px;
float: left;
width: 400px;
}
}
/* Note textare */
#note_note {
height:80px;
width:99%;
font-size:14px;
height: 80px;
width: 99%;
font-size: 14px;
}
#new_note {
.attach_holder {
display:none;
display: none;
}
}
@ -36,34 +36,34 @@
border: 1px solid #ddd;
padding: 10px;
min-height: 60px;
background:#f5f5f5;
background: #f5f5f5;
}
.note {
padding: 8px 0;
overflow: hidden;
display: block;
position:relative;
position: relative;
img {float: left; margin-right: 10px;}
img.emoji {float:none;margin:0;}
img.emoji {float: none;margin: 0;}
.note-author cite{font-style: italic;}
p { color:$style_color; }
p { color: $style_color; }
.note-author { color: $style_color;}
.note-title { margin-left:45px; padding-top: 5px;}
.note-title { margin-left: 45px; padding-top: 5px;}
.avatar {
margin-top:3px;
margin-top: 3px;
}
.delete-note {
display:none;
position:absolute;
right:0;
top:0;
display: none;
position: absolute;
right: 0;
top: 0;
}
&:hover {
.delete-note { display:block; }
.delete-note { display: block; }
}
}
#notes-list:not(.reversed) .note,
@ -94,30 +94,31 @@ p.notify_controls span{
}
tr.line_notes_row {
border-bottom:1px solid #DDD;
border-bottom: 1px solid #DDD;
border-left: 7px solid #2A79A3;
&.reply {
background:#eee;
background: #eee;
border-left: 7px solid #2A79A3;
border-top:1px solid #ddd;
border-top: 1px solid #ddd;
td {
padding:7px 10px;
padding: 7px 10px;
}
a.line_note_reply_link {
@include round-borders-all(4px);
border: 1px solid #eaeaea;
@include border-radius(4px);
padding: 3px 10px;
margin-left:5px;
margin-left: 5px;
color: white;
background: #2A79A3;
border-color: #2A79A3;
}
}
ul {
margin:0;
margin: 0;
li {
padding:0;
border:none;
padding: 0;
border: none;
}
}
}
@ -125,28 +126,28 @@ tr.line_notes_row {
.line_notes_row, .per_line_form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; }
.per_line_form {
background:#f5f5f5;
border-top:1px solid #eee;
background: #f5f5f5;
border-top: 1px solid #eee;
form { margin: 0; }
td {
border-bottom:1px solid #ddd;
border-bottom: 1px solid #ddd;
}
.note_actions {
margin:0;
margin: 0;
padding-top: 10px;
.buttons {
float:left;
width:300px;
float: left;
width: 300px;
}
.options {
.labels {
float:left;
padding-left:10px;
float: left;
padding-left: 10px;
label {
padding: 6px 0;
margin: 0;
width:120px;
width: 120px;
}
}
}
@ -154,13 +155,13 @@ tr.line_notes_row {
}
td .line_note_link {
position:absolute;
position: absolute;
margin-left:-70px;
margin-top:-10px;
z-index:10;
z-index: 10;
background: url("comment_add.png") no-repeat left 0;
width:32px;
height:32px;
width: 32px;
height: 32px;
opacity: 0.0;
filter: alpha(opacity=0);
@ -180,13 +181,13 @@ td .line_note_link {
.new_note {
.input-file {
font: 500px monospace;
opacity:0;
opacity: 0;
filter: alpha(opacity=0);
position: absolute;
z-index: 1;
top:0;
right:0;
padding:0;
top: 0;
right: 0;
padding: 0;
margin: 0;
}
@ -198,24 +199,24 @@ td .line_note_link {
}
.attachments {
position:relative;
position: relative;
width: 350px;
height: 50px;
overflow:hidden;
overflow: hidden;
margin:0 0 5px !important;
.input_file {
.file_upload {
position: absolute;
right:14px;
top:7px;
right: 14px;
top: 7px;
}
.file_name {
line-height:30px;
width:240px;
height:28px;
overflow:hidden;
line-height: 30px;
width: 240px;
height: 28px;
overflow: hidden;
}
.input-file {
width: 260px;
@ -228,5 +229,5 @@ td .line_note_link {
.note-text {
border: 1px solid #aaa;
box-shadow:none;
box-shadow: none;
}

View file

@ -1,21 +1,21 @@
.profile_history {
.event_feed {
min-height:20px;
min-height: 20px;
.avatar {
width:20px;
width: 20px;
}
}
}
.profile_avatar_holder {
float:left;
width:60px;
height:60px;
margin-right:20px;
float: left;
width: 60px;
height: 60px;
margin-right: 20px;
img {
width:60px;
height:60px;
background:#fff;
width: 60px;
height: 60px;
background: #fff;
padding: 1px;
border: 1px solid #ddd;
}

View file

@ -4,50 +4,34 @@
}
.side {
@extend .span4;
@extend .right;
.groups_box,
.projects_box {
h5 {
color:$style_color;
font-size:16px;
> h5 {
color: $style_color;
font-size: 16px;
text-shadow: 0 1px 1px #fff;
padding: 2px 10px;
line-height:32px;
font-size:14px;
line-height: 32px;
font-size: 14px;
}
ul {
li {
padding:0;
a {
display:block;
.group_name {
font-size:14px;
line-height:18px;
}
.project_name {
color:#4fa2bd;
font-size:14px;
line-height:18px;
}
.arrow {
float:right;
padding:10px;
margin:0;
}
.last_activity {
padding-top:5px;
display:block;
span, strong {
font-size:12px;
color:#666;
}
}
.nav-projects-tabs li { padding: 0; }
.well-list {
.arrow {
float: right;
padding: 10px;
margin: 0;
}
.last_activity {
padding-top: 5px;
display: block;
span, strong {
font-size: 12px;
color: #666;
}
}
}
@extend .leftbar;
@extend .ui-box;
}
}
@ -58,21 +42,27 @@
.project_name_holder {
input,
label {
font-size:16px;
line-height:20px;
padding:8px;
font-size: 16px;
line-height: 20px;
padding: 8px;
}
label {
color:#888;
color: #888;
}
.btn {
padding:6px 10px;
margin-left:10px;
margin-bottom:8px;
padding: 6px 10px;
margin-left: 10px;
margin-bottom: 8px;
}
}
.adv_settings {
h6 { margin-left:40px; }
h6 { margin-left: 40px; }
}
fieldset.features {
.control-label {
font-weight: bold;
}
}
}
@ -81,19 +71,20 @@
@include bg-gray-gradient;
padding: 4px 7px;
border: 1px solid #CCC;
margin-bottom:20px;
margin-bottom: 20px;
}
.project_clone_holder {
input[type="text"],
.btn {
font-size:12px;
font-size: 12px;
line-height: 18px;
margin: 0;
padding: 3px 10px;
}
input[type="text"] {
@extend .monospace;
border: 1px solid #BBB;
box-shadow: none;
margin-left: -1px;
@ -102,11 +93,33 @@
.save-project-loader {
img {
margin-top:50px;
margin-bottom:50px;
margin-top: 50px;
margin-bottom: 50px;
}
h3 {
@extend .page_title;
}
}
ul.nav.nav-projects-tabs {
@extend .nav-tabs;
padding-left: 8px;
li {
a {
padding: 4px 20px;
margin-top: 2px;
border-color: #DDD;
background-color: #EEE;
text-shadow: 0 1px 1px white;
color: #555;
}
&.active {
a {
font-weight: bold;
}
}
}
}

View file

@ -0,0 +1,9 @@
.snippet.file_holder {
.file_title {
.snippet-file-name {
position: relative;
top: -4px;
left: -4px;
}
}
}

View file

@ -6,17 +6,17 @@
}
.themes_opts {
padding-left:20px;
padding-left: 20px;
label {
width:175px;
margin-right:40px;
width: 175px;
margin-right: 40px;
.prev {
@extend .thumbnail;
height:30px;
width:175px;
margin-bottom:10px;
height: 30px;
width: 175px;
margin-bottom: 10px;
&.classic {
background: #31363e;
@ -42,17 +42,17 @@
}
.code_highlight_opts {
padding-left:20px;
padding-left: 20px;
label {
width:220px;
margin-right:40px;
width: 220px;
margin-right: 40px;
.prev {
@extend .thumbnail;
height:151px;
width:220px;
margin-bottom:10px;
height: 151px;
width: 220px;
margin-bottom: 10px;
}
}
}

View file

@ -1,14 +1,14 @@
.tree-holder {
.tree-content-holder {
float:left;
width:100%;
float: left;
width: 100%;
}
.tree_progress {
display:none;
margin:20px;
display: none;
margin: 20px;
&.loading {
display:block;
display: block;
}
}
@ -18,20 +18,20 @@
&:hover {
td {
background: $hover;
border-top:1px solid #ADF;
border-bottom:1px solid #ADF;
border-top: 1px solid #ADF;
border-bottom: 1px solid #ADF;
}
cursor:pointer;
cursor: pointer;
}
}
}
.tree-item {
.tree-item-file-name {
vertical-align:middle;
vertical-align: middle;
a {
&:hover {
color:$blue_link;
color: $primary_color;
}
}
@ -48,8 +48,8 @@
padding: 2px 10px;
}
td {
line-height:20px;
background:#fafafa;
line-height: 20px;
background: #fafafa;
}
}
@ -86,7 +86,7 @@
.tree-btn-group {
.btn {
margin-right:-3px;
padding:2px 10px;
padding: 2px 10px;
}
}

View file

@ -0,0 +1,43 @@
.votes {
font-size: 13px;
line-height: 15px;
.progress {
height: 4px;
margin: 0;
.bar {
float: left;
height: 100%;
}
.bar-success {
@include linear-gradient(#62C462, #51A351);
background-color: #468847;
}
.bar-danger {
@include linear-gradient(#EE5F5B, #BD362F);
background-color: #B94A48;
}
}
.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;
}
}

View file

@ -4,18 +4,6 @@
*
*/
.ui_basic {
/*
* Common styles
*
*/
a {
color: $link_color;
&:hover {
text-decoration:none;
color: $blue_link;
}
}
.app_logo {
.separator {
margin-left: 0;

View file

@ -47,17 +47,17 @@
a {
h1 {
background: url('logo_white.png') no-repeat 0px 2px;
color:#eee;
color: #eee;
text-shadow: 0 1px 1px #111;
}
}
.separator {
display:none;
display: none;
}
}
.project_name {
color:#eee;
color: #eee;
text-shadow: 0 1px 1px #111;
}
}

View file

@ -19,8 +19,6 @@ module Notes
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"
project.wiki_notes.limit(20)
end
@notes = if after_id

View file

@ -0,0 +1,23 @@
class ProjectUpdateContext < BaseContext
def execute(role = :default)
namespace_id = params[:project].delete(:namespace_id)
allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin
if allowed_transfer && namespace_id.present?
if namespace_id == Namespace.global_id
if project.namespace.present?
# Transfer to global namespace from anyone
project.transfer(nil)
end
elsif namespace_id.to_i != project.namespace_id
# Transfer to someone namespace
namespace = Namespace.find(namespace_id)
project.transfer(namespace)
end
end
project.update_attributes(params[:project], as: role)
end
end

View file

@ -2,7 +2,7 @@ class Admin::GroupsController < AdminController
before_filter :group, only: [:edit, :show, :update, :destroy, :project_update]
def index
@groups = Group.scoped
@groups = Group.order('name ASC')
@groups = @groups.search(params[:name]) if params[:name].present?
@groups = @groups.page(params[:page]).per(20)
end
@ -11,6 +11,7 @@ class Admin::GroupsController < AdminController
@projects = Project.scoped
@projects = @projects.not_in_group(@group) if @group.projects.present?
@projects = @projects.all
@projects.reject!(&:empty_repo?)
end
def new
@ -22,6 +23,7 @@ class Admin::GroupsController < AdminController
def create
@group = Group.new(params[:group])
@group.path = @group.name.dup.parameterize if @group.name
@group.owner = current_user
if @group.save
@ -48,15 +50,17 @@ class Admin::GroupsController < AdminController
def project_update
project_ids = params[:project_ids]
Project.where(id: project_ids).update_all(group_id: @group.id)
Project.where(id: project_ids).each do |project|
project.transfer(@group)
end
redirect_to :back, notice: 'Group was successfully updated.'
end
def remove_project
@project = Project.find(params[:project_id])
@project.group_id = nil
@project.save
@project.transfer(nil)
redirect_to :back, notice: 'Group was successfully updated.'
end
@ -70,6 +74,6 @@ class Admin::GroupsController < AdminController
private
def group
@group = Group.find_by_code(params[:id])
@group = Group.find_by_path(params[:id])
end
end

View file

@ -1,65 +1,51 @@
class Admin::ProjectsController < AdminController
before_filter :admin_project, only: [:edit, :show, :update, :destroy, :team_update]
before_filter :project, only: [:edit, :show, :update, :destroy, :team_update]
def index
@admin_projects = Project.scoped
@admin_projects = @admin_projects.search(params[:name]) if params[:name].present?
@admin_projects = @admin_projects.order("name ASC").page(params[:page]).per(20)
@projects = Project.scoped
@projects = @projects.where(namespace_id: params[:namespace_id]) if params[:namespace_id].present?
@projects = @projects.where(namespace_id: nil) if params[:namespace_id] == Namespace.global_id
@projects = @projects.search(params[:name]) if params[:name].present?
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20)
end
def show
@users = User.scoped
@users = @users.not_in_project(@admin_project) if @admin_project.users.present?
@users = User.active
@users = @users.not_in_project(@project) if @project.users.present?
@users = @users.all
end
def new
@admin_project = Project.new
end
def edit
end
def team_update
@admin_project.add_users_ids_to_team(params[:user_ids], params[:project_access])
@project.add_users_ids_to_team(params[:user_ids], params[:project_access])
redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.'
end
def create
@admin_project = Project.new(params[:project])
@admin_project.owner = current_user
if @admin_project.save
redirect_to [:admin, @admin_project], notice: 'Project was successfully created.'
else
render action: "new"
end
redirect_to [:admin, @project], notice: 'Project was successfully updated.'
end
def update
owner_id = params[:project].delete(:owner_id)
status = ProjectUpdateContext.new(project, current_user, params).execute(:admin)
if owner_id
@admin_project.owner = User.find(owner_id)
end
if @admin_project.update_attributes(params[:project])
redirect_to [:admin, @admin_project], notice: 'Project was successfully updated.'
if status
redirect_to [:admin, @project], notice: 'Project was successfully updated.'
else
render action: "edit"
end
end
def destroy
@admin_project.destroy
@project.destroy
redirect_to admin_projects_url, notice: 'Project was successfully deleted.'
redirect_to admin_projects_path, notice: 'Project was successfully deleted.'
end
private
protected
def admin_project
@admin_project = Project.find_by_code(params[:id])
def project
id = params[:project_id] || params[:id]
@project = Project.find_with_namespace(id)
@project || render_404
end
end

View file

@ -3,7 +3,7 @@ class Admin::UsersController < AdminController
@admin_users = User.scoped
@admin_users = @admin_users.filter(params[:filter])
@admin_users = @admin_users.search(params[:name]) if params[:name].present?
@admin_users = @admin_users.order("updated_at DESC").page(params[:page])
@admin_users = @admin_users.order("name ASC").page(params[:page])
end
def show
@ -30,7 +30,7 @@ class Admin::UsersController < AdminController
def new
@admin_user = User.new({ projects_limit: Gitlab.config.default_projects_limit }, as: :admin)
@admin_user = User.new({ projects_limit: Gitlab.config.gitlab.default_projects_limit }, as: :admin)
end
def edit

View file

@ -2,6 +2,7 @@ class ApplicationController < ActionController::Base
before_filter :authenticate_user!
before_filter :reject_blocked!
before_filter :set_current_user_for_observers
before_filter :add_abilities
before_filter :dev_tools if Rails.env == 'development'
protect_from_forgery
@ -34,7 +35,7 @@ class ApplicationController < ActionController::Base
def reject_blocked!
if current_user && current_user.blocked
sign_out current_user
flash[:alert] = "Your account was blocked"
flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
redirect_to new_user_session_path
end
end
@ -42,7 +43,7 @@ class ApplicationController < ActionController::Base
def after_sign_in_path_for resource
if resource.is_a?(User) && resource.respond_to?(:blocked) && resource.blocked
sign_out resource
flash[:alert] = "Your account was blocked"
flash[:alert] = "Your account is blocked. Retry when an admin unblock it."
new_user_session_path
else
super
@ -63,11 +64,19 @@ class ApplicationController < ActionController::Base
end
def project
@project ||= current_user.projects.find_by_code(params[:project_id] || params[:id])
@project || render_404
id = params[:project_id] || params[:id]
@project = Project.find_with_namespace(id)
if @project and can?(current_user, :read_project, @project)
@project
else
@project = nil
render_404
end
end
def add_project_abilities
def add_abilities
abilities << Ability
end
@ -103,6 +112,10 @@ class ApplicationController < ActionController::Base
render file: Rails.root.join("public", "404"), layout: false, status: "404"
end
def render_403
render file: Rails.root.join("public", "403"), layout: false, status: "403"
end
def require_non_empty_project
redirect_to @project if @project.empty_repo?
end

View file

@ -26,7 +26,8 @@ class CommitController < ProjectResourceController
end
end
format.patch
format.diff { render text: @commit.to_diff }
format.patch { render text: @commit.to_patch }
end
end
end

View file

@ -1,11 +1,23 @@
class DashboardController < ApplicationController
respond_to :html
before_filter :projects
before_filter :event_filter, only: :index
def index
@groups = Group.where(id: current_user.projects.pluck(:group_id))
@projects = current_user.projects_sorted_by_activity
@groups = current_user.authorized_groups
@has_authorized_projects = @projects.count > 0
@projects = case params[:scope]
when 'personal' then
@projects.personal(current_user)
when 'joined' then
@projects.joined(current_user)
else
@projects
end
@projects = @projects.page(params[:page]).per(30)
@events = Event.in_projects(current_user.project_ids)
@ -23,15 +35,16 @@ class DashboardController < ApplicationController
# Get authored or assigned open merge requests
def merge_requests
@projects = current_user.projects.all
@merge_requests = current_user.cared_merge_requests.recent.page(params[:page]).per(20)
@merge_requests = current_user.cared_merge_requests
@merge_requests = dashboard_filter(@merge_requests)
@merge_requests = @merge_requests.recent.page(params[:page]).per(20)
end
# Get only assigned issues
def issues
@projects = current_user.projects.all
@user = current_user
@issues = current_user.assigned_issues.opened.recent.page(params[:page]).per(20)
@issues = current_user.assigned_issues
@issues = dashboard_filter(@issues)
@issues = @issues.recent.page(params[:page]).per(20)
@issues = @issues.includes(:author, :project)
respond_to do |format|
@ -40,7 +53,32 @@ class DashboardController < ApplicationController
end
end
protected
def projects
@projects = current_user.authorized_projects.sorted_by_activity
end
def event_filter
@event_filter ||= EventFilter.new(params[:event_filter])
end
def dashboard_filter items
if params[:project_id]
items = items.where(project_id: params[:project_id])
end
if params[:search].present?
items = items.search(params[:search])
end
case params[:status]
when 'closed'
items.closed
when 'all'
items
else
items.opened
end
end
end

View file

@ -5,6 +5,9 @@ class GroupsController < ApplicationController
before_filter :group
before_filter :projects
# Authorize
before_filter :authorize_read_group!
def show
@events = Event.in_projects(project_ids).limit(20).offset(params[:offset] || 0)
@last_push = current_user.recent_push
@ -18,7 +21,7 @@ class GroupsController < ApplicationController
# Get authored or assigned open merge requests
def merge_requests
@merge_requests = current_user.cared_merge_requests
@merge_requests = current_user.cared_merge_requests.opened
@merge_requests = @merge_requests.of_group(@group).recent.page(params[:page]).per(20)
end
@ -44,20 +47,33 @@ class GroupsController < ApplicationController
end
def people
@users = group.users.all
@project = group.projects.find(params[:project_id]) if params[:project_id]
@users = @project ? @project.users : group.users
@users.sort_by!(&:name)
if @project
@team_member = @project.users_projects.new
end
end
protected
def group
@group ||= Group.find_by_code(params[:id])
@group ||= Group.find_by_path(params[:id])
end
def projects
@projects ||= current_user.projects_sorted_by_activity.where(group_id: @group.id)
@projects ||= group.projects.authorized_for(current_user).sorted_by_activity
end
def project_ids
projects.map(&:id)
end
# Dont allow unauthorized access to group
def authorize_read_group!
unless projects.present? or can?(current_user, :manage_group, @group)
return render_404
end
end
end

View file

@ -1,6 +1,6 @@
class IssuesController < ProjectResourceController
before_filter :module_enabled
before_filter :issue, only: [:edit, :update, :destroy, :show]
before_filter :issue, only: [:edit, :update, :show]
# Allow read any issue
before_filter :authorize_read_issue!
@ -11,9 +11,6 @@ class IssuesController < ProjectResourceController
# Allow modify issue
before_filter :authorize_modify_issue!, only: [:edit, :update]
# Allow destroy issue
before_filter :authorize_admin_issue!, only: [:destroy]
respond_to :js, :html
def index
@ -77,15 +74,6 @@ class IssuesController < ProjectResourceController
end
end
def destroy
@issue.destroy
respond_to do |format|
format.html { redirect_to project_issues_path }
format.js { render nothing: true }
end
end
def sort
return render_404 unless can?(current_user, :admin_issue, @project)

View file

@ -1,7 +1,7 @@
class MergeRequestsController < ProjectResourceController
before_filter :module_enabled
before_filter :merge_request, only: [:edit, :update, :destroy, :show, :commits, :diffs, :automerge, :automerge_check, :raw]
before_filter :validates_merge_request, only: [:show, :diffs, :raw]
before_filter :merge_request, only: [:edit, :update, :show, :commits, :diffs, :automerge, :automerge_check, :ci_status]
before_filter :validates_merge_request, only: [:show, :diffs]
before_filter :define_show_vars, only: [:show, :diffs]
# Allow read any merge_request
@ -13,10 +13,6 @@ class MergeRequestsController < ProjectResourceController
# Allow modify merge_request
before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
# Allow destroy merge_request
before_filter :authorize_admin_merge_request!, only: [:destroy]
def index
@merge_requests = MergeRequestsLoadContext.new(project, current_user, params).execute
end
@ -25,11 +21,10 @@ class MergeRequestsController < ProjectResourceController
respond_to do |format|
format.html
format.js
end
end
def raw
send_file @merge_request.to_raw
format.diff { render text: @merge_request.to_diff }
format.patch { render text: @merge_request.to_patch }
end
end
def diffs
@ -87,14 +82,6 @@ class MergeRequestsController < ProjectResourceController
end
end
def destroy
@merge_request.destroy
respond_to do |format|
format.html { redirect_to project_merge_requests_url(@project) }
end
end
def branch_from
@commit = project.commit(params[:ref])
@commit = CommitDecorator.decorate(@commit)
@ -105,6 +92,13 @@ class MergeRequestsController < ProjectResourceController
@commit = CommitDecorator.decorate(@commit)
end
def ci_status
status = project.gitlab_ci_service.commit_status(merge_request.last_commit.sha)
response = { status: status }
render json: response
end
protected
def merge_request

View file

@ -12,11 +12,12 @@ class MilestonesController < ProjectResourceController
def index
@milestones = case params[:f]
when 'all'; @project.milestones
else @project.milestones.active
when 'all'; @project.milestones.order("closed, due_date DESC")
when 'closed'; @project.milestones.closed.order("due_date DESC")
else @project.milestones.active.order("due_date ASC")
end
@milestones = @milestones.includes(:project).order("due_date")
@milestones = @milestones.includes(:project)
@milestones = @milestones.page(params[:page]).per(20)
end
@ -42,6 +43,7 @@ class MilestonesController < ProjectResourceController
def create
@milestone = @project.milestones.new(params[:milestone])
@milestone.author_id_of_changes = current_user.id
if @milestone.save
redirect_to project_milestone_path(@project, @milestone)
@ -51,7 +53,7 @@ class MilestonesController < ProjectResourceController
end
def update
@milestone.update_attributes(params[:milestone])
@milestone.update_attributes(params[:milestone].merge(author_id_of_changes: current_user.id))
respond_to do |format|
format.js

View file

@ -1,5 +1,5 @@
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
Gitlab.config.omniauth_providers.each do |provider|
Gitlab.config.omniauth.providers.each do |provider|
define_method provider['name'] do
handle_omniauth
end

View file

@ -1,5 +1,6 @@
class ProfileController < ApplicationController
class ProfilesController < ApplicationController
before_filter :user
layout 'profile'
def show
end
@ -7,8 +8,15 @@ class ProfileController < ApplicationController
def design
end
def account
end
def update
@user.update_attributes(params[:user])
if @user.update_attributes(params[:user])
flash[:notice] = "Profile was successfully updated"
else
flash[:alert] = "Failed to update profile"
end
respond_to do |format|
format.html { redirect_to :back }
@ -19,7 +27,7 @@ class ProfileController < ApplicationController
def token
end
def password_update
def update_password
params[:user].reject!{ |k, v| k != "password" && k != "password_confirmation"}
if @user.update_attributes(params[:user])
@ -31,14 +39,25 @@ class ProfileController < ApplicationController
end
def reset_private_token
current_user.reset_authentication_token!
redirect_to profile_account_path
if current_user.reset_authentication_token!
flash[:notice] = "Token was successfully updated"
end
redirect_to account_profile_path
end
def history
@events = current_user.recent_events.page(params[:page]).per(20)
end
def update_username
@user.update_attributes(username: params[:user][:username])
respond_to do |format|
format.js
end
end
private
def user

View file

@ -1,5 +1,3 @@
class ProjectResourceController < ApplicationController
before_filter :project
# Authorize
before_filter :add_project_abilities
end

View file

@ -34,8 +34,11 @@ class ProjectsController < ProjectResourceController
end
def update
status = ProjectUpdateContext.new(project, current_user, params).execute
respond_to do |format|
if project.update_attributes(params[:project])
if status
flash[:notice] = 'Project was successfully updated.'
format.html { redirect_to edit_project_path(project), notice: 'Project was successfully updated.' }
format.js
else
@ -43,6 +46,10 @@ class ProjectsController < ProjectResourceController
format.js
end
end
rescue Project::TransferError => ex
@error = ex
render :update_failed
end
def show
@ -51,12 +58,12 @@ class ProjectsController < ProjectResourceController
respond_to do |format|
format.html do
unless @project.empty_repo?
@last_push = current_user.recent_push(@project.id)
render :show
else
render "projects/empty"
end
unless @project.empty_repo?
@last_push = current_user.recent_push(@project.id)
render :show
else
render "projects/empty"
end
end
format.js
end
@ -80,12 +87,18 @@ class ProjectsController < ProjectResourceController
end
def graph
graph = Gitlab::Graph::JsonBuilder.new(project)
@days_json, @commits_json = graph.days_json, graph.commits_json
respond_to do |format|
format.html
format.json do
graph = Gitlab::Graph::JsonBuilder.new(project)
render :json => graph.to_json
end
end
end
def destroy
return access_denied! unless can?(current_user, :remove_project, project)
# Disable the UsersProject update_repository call, otherwise it will be
# called once for every person removed from the project
UsersProject.skip_callback(:destroy, :after, :update_repository)

View file

@ -16,7 +16,7 @@ class SnippetsController < ProjectResourceController
respond_to :html
def index
@snippets = @project.snippets
@snippets = @project.snippets.fresh
end
def new
@ -60,7 +60,7 @@ class SnippetsController < ProjectResourceController
redirect_to project_snippets_path(@project)
end
def raw
def raw
send_data(
@snippet.content,
type: "text/plain",

View file

@ -21,7 +21,11 @@ class TeamMembersController < ProjectResourceController
params[:project_access]
)
redirect_to project_team_index_path(@project)
if params[:redirect_to]
redirect_to params[:redirect_to]
else
redirect_to project_team_index_path(@project)
end
end
def update

View file

@ -76,7 +76,7 @@ class CommitDecorator < ApplicationDecorator
source_name = send "#{options[:source]}_name".to_sym
source_email = send "#{options[:source]}_email".to_sym
text = if options[:avatar]
avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size]
avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: ""
%Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
else
source_name

View file

@ -1,4 +1,5 @@
require 'digest/md5'
require 'uri'
module ApplicationHelper
@ -30,13 +31,15 @@ module ApplicationHelper
args.any? { |v| v.to_s.downcase == action_name }
end
def gravatar_icon(user_email = '', size = 40)
if Gitlab.config.disable_gravatar? || user_email.blank?
def gravatar_icon(user_email = '', size = nil)
size = 40 if size.nil? || size <= 0
if !Gitlab.config.gravatar.enabled || user_email.blank?
'no_avatar.png'
else
gravatar_prefix = request.ssl? ? "https://secure" : "http://www"
gravatar_url = request.ssl? ? Gitlab.config.gravatar.ssl_url : Gitlab.config.gravatar.plain_url
user_email.strip!
"#{gravatar_prefix}.gravatar.com/avatar/#{Digest::MD5.hexdigest(user_email.downcase)}?s=#{size}&d=mm"
sprintf(gravatar_url, {:hash => Digest::MD5.hexdigest(user_email.downcase), :email => URI.escape(user_email), :size => size})
end
end
@ -45,7 +48,7 @@ module ApplicationHelper
end
def web_app_url
"#{request_protocol}://#{Gitlab.config.web_host}/"
"#{request_protocol}://#{Gitlab.config.gitlab.host}/"
end
def last_commit(project)
@ -75,7 +78,7 @@ module ApplicationHelper
end
def search_autocomplete_source
projects = current_user.projects.map{ |p| { label: p.name, url: project_path(p) } }
projects = current_user.projects.map{ |p| { label: p.name_with_namespace, url: project_path(p) } }
default_nav = [
{ label: "My Profile", url: profile_path },
@ -92,6 +95,7 @@ module ApplicationHelper
{ label: "API Help", url: help_api_path },
{ label: "Markdown Help", url: help_markdown_path },
{ label: "SSH Keys Help", url: help_ssh_path },
{ label: "Gitlab Rake Tasks Help", url: help_raketasks_path },
]
project_nav = []
@ -126,6 +130,10 @@ module ApplicationHelper
Gitlab::Theme.css_class_by_id(current_user.try(:theme_id))
end
def user_color_scheme_class
current_user.dark_scheme ? :black : :white
end
def show_last_push_widget?(event)
event &&
event.last_push_to_non_root? &&

View file

@ -0,0 +1,32 @@
module DashboardHelper
def dashboard_filter_path(entity, options={})
exist_opts = {
status: params[:status],
project_id: params[:project_id],
}
options = exist_opts.merge(options)
case entity
when 'issue' then
dashboard_issues_path(options)
when 'merge_request'
dashboard_merge_requests_path(options)
end
end
def entities_per_project project, entity
items = project.items_for(entity)
items = case params[:status]
when 'closed'
items.closed
when 'all'
items
else
items.opened
end
items.where(assignee_id: current_user.id).count
end
end

View file

@ -4,28 +4,6 @@ module IssuesHelper
project_issues_path project, params
end
def link_to_issue_assignee(issue)
project = issue.project
tm = project.team_member_by_id(issue.assignee_id)
if tm
link_to issue.assignee_name, project_team_member_path(project, tm), class: "author_link"
else
issue.assignee_name
end
end
def link_to_issue_author(issue)
project = issue.project
tm = project.team_member_by_id(issue.author_id)
if tm
link_to issue.author_name, project_team_member_path(project, tm), class: "author_link"
else
issue.author_name
end
end
def issue_css_classes issue
classes = "issue"
classes << " closed" if issue.closed
@ -52,4 +30,14 @@ module IssuesHelper
open: "open"
}
end
def labels_autocomplete_source
labels = @project.issues_labels.order('count DESC')
labels = labels.map{ |l| { label: l.name, value: l.name } }
labels.to_json
end
def issues_active_milestones
@project.milestones.active.order("id desc").all
end
end

View file

@ -1,26 +1,4 @@
module MergeRequestsHelper
def link_to_merge_request_assignee(merge_request)
project = merge_request.project
tm = project.team_member_by_id(merge_request.assignee_id)
if tm
link_to merge_request.assignee_name, project_team_member_path(project, tm), class: "author_link"
else
merge_request.assignee_name
end
end
def link_to_merge_request_author(merge_request)
project = merge_request.project
tm = project.team_member_by_id(merge_request.author_id)
if tm
link_to merge_request.author_name, project_team_member_path(project, tm), class: "author_link"
else
merge_request.author_name
end
end
def new_mr_path_from_push_event(event)
new_project_merge_request_path(
event.project,
@ -39,7 +17,7 @@ module MergeRequestsHelper
classes
end
def ci_status_path
@project.gitlab_ci_service.commit_badge_path(@merge_request.last_commit.sha)
def ci_build_details_path merge_request
merge_request.project.gitlab_ci_service.build_page(merge_request.last_commit.sha)
end
end

View file

@ -0,0 +1,26 @@
module NamespacesHelper
def namespaces_options(selected = :current_user, scope = :default)
groups = current_user.namespaces.select {|n| n.type == 'Group'}
users = if scope == :all
Namespace.root
else
current_user.namespaces.reject {|n| n.type == 'Group'}
end
global_opts = ["Global", [['/', Namespace.global_id]] ]
group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ]
users_opts = [ "Users", users.map {|u| [u.human_name, u.id]} ]
options = []
options << global_opts if current_user.admin
options << group_opts
options << users_opts
if selected == :current_user && current_user.namespace
selected = current_user.namespace.id
end
grouped_options_for_select(options, selected)
end
end

View file

@ -8,11 +8,49 @@ module ProjectsHelper
end
def link_to_project project
link_to project.name, project
link_to project do
title = content_tag(:strong, project.name)
if project.namespace
namespace = content_tag(:span, "#{project.namespace.human_name} / ", class: 'tiny')
title = namespace + title
end
title
end
end
def link_to_member(project, author)
return "(deleted)" unless author
# Build avatar image tag
avatar = image_tag(gravatar_icon(author.try(:email)), width: 16, class: "lil_av")
# Build name strong tag
name = content_tag :strong, author.name, class: 'author'
author_html = avatar + name
tm = project.team_member_by_id(author)
content_tag :span, class: 'member-link' do
if tm
link_to author_html, project_team_member_path(project, tm), class: "author_link"
else
author_html
end
end
end
def tm_path team_member
project_team_member_path(@project, team_member)
end
end
def project_title project
if project.group
project.name_with_namespace
else
project.name
end
end
end

View file

@ -72,7 +72,7 @@ module TabHelper
return "active" if current_page?(controller: "projects", action: action, id: @project)
end
if ['snippets', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name
if ['snippets', 'services', 'hooks', 'deploy_keys', 'team_members'].include? controller.controller_name
"active"
end
end
@ -84,4 +84,17 @@ module TabHelper
'active'
end
end
# Use nav_tab for save controller/action but different params
def nav_tab key, value, &block
o = {}
o[:class] = ""
o[:class] << " active" if params[key] == value
if block_given?
content_tag(:li, capture(&block), o)
else
content_tag(:li, nil, o)
end
end
end

View file

@ -3,11 +3,11 @@ class Notify < ActionMailer::Base
add_template_helper ApplicationHelper
add_template_helper GitlabMarkdownHelper
default_url_options[:host] = Gitlab.config.web_host
default_url_options[:protocol] = Gitlab.config.web_protocol
default_url_options[:port] = Gitlab.config.web_port if Gitlab.config.web_custom_port?
default_url_options[:host] = Gitlab.config.gitlab.host
default_url_options[:protocol] = Gitlab.config.gitlab.protocol
default_url_options[:port] = Gitlab.config.gitlab.port if Gitlab.config.gitlab_on_non_standard_port?
default from: Gitlab.config.email_from
default from: Gitlab.config.gitlab.email_from
@ -31,6 +31,7 @@ class Notify < ActionMailer::Base
def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id)
@issue = Issue.find issue_id
@issue_status = status
@project = @issue.project
@updated_by = User.find updated_by_user_id
mail(to: recipient(recipient_id),
subject: subject("changed issue ##{@issue.id}", @issue.title))
@ -89,14 +90,6 @@ class Notify < ActionMailer::Base
mail(to: recipient(recipient_id), subject: subject)
end
def note_wiki_email(recipient_id, note_id)
@note = Note.find(note_id)
@wiki = @note.noteable
@project = @note.project
mail(to: recipient(recipient_id), subject: subject("note for wiki"))
end
#
# Project
@ -105,11 +98,17 @@ class Notify < ActionMailer::Base
def project_access_granted_email(user_project_id)
@users_project = UsersProject.find user_project_id
@project = @users_project.project
mail(to: @users_project.user.email,
mail(to: @users_project.user.email,
subject: subject("access to project was granted"))
end
def project_was_moved_email(user_project_id)
@users_project = UsersProject.find user_project_id
@project = @users_project.project
mail(to: @users_project.user.email,
subject: subject("project was moved"))
end
#
# User

View file

@ -7,6 +7,7 @@ class Ability
when "Note" then note_abilities(object, subject)
when "Snippet" then snippet_abilities(object, subject)
when "MergeRequest" then merge_request_abilities(object, subject)
when "Group" then group_abilities(object, subject)
else []
end
end
@ -14,7 +15,40 @@ class Ability
def project_abilities(user, project)
rules = []
rules << [
# Rules based on role in project
if project.master_access_for?(user)
rules << project_master_rules
elsif project.dev_access_for?(user)
rules << project_dev_rules
elsif project.report_access_for?(user)
rules << project_report_rules
elsif project.guest_access_for?(user)
rules << project_guest_rules
end
if project.namespace
# If user own project namespace
# (Ex. group owner or account owner)
if project.namespace.owner == user
rules << project_admin_rules
end
else
# For compatibility with global projects
# use projects.owner_id
if project.owner == user
rules << project_admin_rules
end
end
rules.flatten
end
def project_guest_rules
[
:read_project,
:read_wiki,
:read_issue,
@ -26,28 +60,30 @@ class Ability
:write_project,
:write_issue,
:write_note
] if project.guest_access_for?(user)
]
end
rules << [
def project_report_rules
project_guest_rules + [
:download_code,
:write_merge_request,
:write_snippet
] if project.report_access_for?(user)
]
end
rules << [
def project_dev_rules
project_report_rules + [
:write_wiki,
:push_code
] if project.dev_access_for?(user)
]
end
rules << [
:push_code_to_protected_branches
] if project.master_access_for?(user)
rules << [
def project_master_rules
project_dev_rules + [
:push_code_to_protected_branches,
:modify_issue,
:modify_snippet,
:modify_merge_request,
:admin_project,
:admin_issue,
:admin_milestone,
:admin_snippet,
@ -55,8 +91,25 @@ class Ability
:admin_merge_request,
:admin_note,
:accept_mr,
:admin_wiki
] if project.master_access_for?(user) || project.owner == user
:admin_wiki,
:admin_project
]
end
def project_admin_rules
project_master_rules + [
:change_namespace,
:rename_project,
:remove_project
]
end
def group_abilities user, group
rules = []
rules << [
:manage_group
] if group.owner == user
rules.flatten
end

View file

@ -87,14 +87,10 @@ class Commit
last = project.commit(from.try(:strip))
if first && last
commits = [first, last].sort_by(&:created_at)
younger = commits.first
older = commits.last
result[:same] = (younger.id == older.id)
result[:commits] = project.repo.commits_between(younger.id, older.id).map {|c| Commit.new(c)}
result[:diffs] = project.repo.diff(younger.id, older.id) rescue []
result[:commit] = Commit.new(older)
result[:same] = (first.id == last.id)
result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)}
result[:diffs] = project.repo.diff(last.id, first.id) rescue []
result[:commit] = Commit.new(first)
end
result
@ -150,4 +146,21 @@ class Commit
def parents_count
parents && parents.count || 0
end
# Shows the diff between the commit's parent and the commit.
#
# Cuts out the header and stats from #to_patch and returns only the diff.
def to_diff
# see Grit::Commit#show
patch = to_patch
# discard lines before the diff
lines = patch.split("\n")
while !lines.first.start_with?("diff --git") do
lines.shift
end
lines.pop if lines.last =~ /^[\d.]+$/ # Git version
lines.pop if lines.last == "-- " # end of diff
lines.join("\n")
end
end

View file

@ -15,6 +15,7 @@
#
class Event < ActiveRecord::Base
include NoteEvent
include PushEvent
attr_accessible :project, :action, :data, :author_id, :project_id,
@ -58,12 +59,14 @@ class Event < ActiveRecord::Base
end
end
# Next events currently enabled for system
# - push
# - new issue
# - merge request
def allowed?
push? || issue? || merge_request? || membership_changed?
def proper?
if push?
true
elsif membership_changed?
true
else
(issue? || merge_request? || note? || milestone?) && target
end
end
def project_name
@ -94,6 +97,14 @@ class Event < ActiveRecord::Base
action == self.class::Reopened
end
def milestone?
target_type == "Milestone"
end
def note?
target_type == "Note"
end
def issue?
target_type == "Issue"
end

View file

@ -36,4 +36,22 @@ class GitlabCiService < Service
def commit_badge_path sha
project_url + "/status?sha=#{sha}"
end
def commit_status_path sha
project_url + "/builds/#{sha}/status.json?token=#{token}"
end
def commit_status sha
response = HTTParty.get(commit_status_path(sha))
if response.code == 200 and response["status"]
response["status"]
else
:error
end
end
def build_page sha
project_url + "/builds/#{sha}"
end
end

View file

@ -1,36 +1,24 @@
# == Schema Information
#
# Table name: groups
# Table name: namespaces
#
# id :integer not null, primary key
# name :string(255) not null
# code :string(255) not null
# path :string(255) not null
# owner_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# type :string(255)
#
class Group < ActiveRecord::Base
attr_accessible :code, :name, :owner_id
has_many :projects
belongs_to :owner, class_name: "User"
validates :name, presence: true, uniqueness: true
validates :code, presence: true, uniqueness: true
validates :owner, presence: true
delegate :name, to: :owner, allow_nil: true, prefix: true
def self.search query
where("name LIKE :query OR code LIKE :query", query: "%#{query}%")
end
def to_param
code
end
class Group < Namespace
def users
User.joins(:users_projects).where(users_projects: {project_id: project_ids}).uniq
users = User.joins(:users_projects).where(users_projects: {project_id: project_ids})
users = users << owner
users.uniq
end
def human_name
name
end
end

View file

@ -202,20 +202,26 @@ class MergeRequest < ActiveRecord::Base
false
end
def to_raw
FileUtils.mkdir_p(Rails.root.join("tmp", "patches"))
patch_path = Rails.root.join("tmp", "patches", "merge_request_#{self.id}.patch")
from = commits.last.id
to = source_branch
project.repo.git.run('', "format-patch" , " > #{patch_path.to_s}", {}, ["#{from}..#{to}", "--stdout"])
patch_path
end
def mr_and_commit_notes
commit_ids = commits.map(&:id)
Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND noteable_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
Note.where("(noteable_type = 'MergeRequest' AND noteable_id = :mr_id) OR (noteable_type = 'Commit' AND commit_id IN (:commit_ids))", mr_id: id, commit_ids: commit_ids)
end
# Returns the raw diff for this merge request
#
# see "git diff"
def to_diff
project.repo.git.native(:diff, {timeout: 30, raise: true}, "#{target_branch}...#{source_branch}")
end
# Returns the commit as a series of email patches.
#
# see "git format-patch"
def to_patch
project.repo.git.format_patch({timeout: 30, raise: true, stdout: true}, "#{target_branch}..#{source_branch}")
end
def last_commit_short_sha
@last_commit_short_sha ||= last_commit.sha[0..10]
end
end

View file

@ -13,18 +13,26 @@
#
class Milestone < ActiveRecord::Base
attr_accessible :title, :description, :due_date, :closed
attr_accessible :title, :description, :due_date, :closed, :author_id_of_changes
attr_accessor :author_id_of_changes
belongs_to :project
has_many :issues
has_many :merge_requests
scope :active, where(closed: false)
scope :closed, where(closed: true)
validates :title, presence: true
validates :project, presence: true
validates :closed, inclusion: { in: [true, false] }
def self.active
where("due_date > ? OR due_date IS NULL", Date.today)
def expired?
if due_date
due_date < Date.today
else
false
end
end
def participants
@ -52,4 +60,20 @@ class Milestone < ActiveRecord::Base
def expires_at
"expires at #{due_date.stamp("Aug 21, 2011")}" if due_date
end
def can_be_closed?
open? && issues.opened.count.zero?
end
def is_empty?
total_items_count.zero?
end
def open?
!closed
end
def author_id
author_id_of_changes
end
end

77
app/models/namespace.rb Normal file
View file

@ -0,0 +1,77 @@
# == Schema Information
#
# Table name: namespaces
#
# id :integer not null, primary key
# name :string(255) not null
# path :string(255) not null
# owner_id :integer not null
# created_at :datetime not null
# updated_at :datetime not null
# type :string(255)
#
class Namespace < ActiveRecord::Base
attr_accessible :name, :path
has_many :projects, dependent: :destroy
belongs_to :owner, class_name: "User"
validates :name, presence: true, uniqueness: true
validates :path, uniqueness: true, presence: true, length: { within: 1..255 },
format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :owner, presence: true
delegate :name, to: :owner, allow_nil: true, prefix: true
after_create :ensure_dir_exist
after_update :move_dir
after_destroy :rm_dir
scope :root, where('type IS NULL')
def self.search query
where("name LIKE :query OR path LIKE :query", query: "%#{query}%")
end
def self.global_id
'GLN'
end
def to_param
path
end
def human_name
owner_name
end
def ensure_dir_exist
namespace_dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
system("mkdir -m 770 #{namespace_dir_path}") unless File.exists?(namespace_dir_path)
end
def move_dir
if path_changed?
old_path = File.join(Gitlab.config.gitolite.repos_path, path_was)
new_path = File.join(Gitlab.config.gitolite.repos_path, path)
if File.exists?(new_path)
raise "Already exists"
end
if system("mv #{old_path} #{new_path}")
send_update_instructions
end
end
end
def rm_dir
dir_path = File.join(Gitlab.config.gitolite.repos_path, path)
system("rm -rf #{dir_path}")
end
def send_update_instructions
projects.each(&:send_move_instructions)
end
end

View file

@ -20,7 +20,7 @@ require 'file_size_validator'
class Note < ActiveRecord::Base
attr_accessible :note, :noteable, :noteable_id, :noteable_type, :project_id,
:attachment, :line_code
:attachment, :line_code, :commit_id
attr_accessor :notify
attr_accessor :notify_author
@ -32,14 +32,17 @@ class Note < ActiveRecord::Base
delegate :name, to: :project, prefix: true
delegate :name, :email, to: :author, prefix: true
validates :project, presence: true
validates :note, presence: true, length: { within: 0..5000 }
validates :note, :project, presence: true
validates :attachment, file_size: { maximum: 10.megabytes.to_i }
mount_uploader :attachment, AttachmentUploader
validates :noteable_id, presence: true, if: ->(n) { n.noteable_type.present? && n.noteable_type != 'Commit' }
validates :commit_id, presence: true, if: ->(n) { n.noteable_type == 'Commit' }
mount_uploader :attachment, AttachmentUploader
# Scopes
scope :common, ->{ where(noteable_id: nil) }
scope :for_commits, ->{ where(noteable_type: "Commit") }
scope :common, ->{ where(noteable_id: nil, commit_id: nil) }
scope :today, ->{ where("created_at >= :date", date: Date.today) }
scope :last_week, ->{ where("created_at >= :date", date: (Date.today - 7.days)) }
scope :since, ->(day) { where("created_at >= :date", date: (day)) }
@ -67,7 +70,7 @@ class Note < ActiveRecord::Base
# override to return commits, which are not active record
def noteable
if for_commit?
project.commit(noteable_id)
project.commit(commit_id)
else
super
end
@ -122,4 +125,12 @@ class Note < ActiveRecord::Base
def downvote?
note.start_with?('-1') || note.start_with?(':-1:')
end
def noteable_type_name
if noteable_type.present?
noteable_type.downcase
else
"wall"
end
end
end

View file

@ -9,14 +9,13 @@
# created_at :datetime not null
# updated_at :datetime not null
# private_flag :boolean default(TRUE), not null
# code :string(255)
# owner_id :integer
# default_branch :string(255)
# issues_enabled :boolean default(TRUE), not null
# wall_enabled :boolean default(TRUE), not null
# merge_requests_enabled :boolean default(TRUE), not null
# wiki_enabled :boolean default(TRUE), not null
# group_id :integer
# namespace_id :integer
#
require "grit"
@ -26,13 +25,24 @@ class Project < ActiveRecord::Base
include PushObserver
include Authority
include Team
include NamespacedProject
class TransferError < StandardError; end
attr_accessible :name, :path, :description, :default_branch, :issues_enabled,
:wall_enabled, :merge_requests_enabled, :wiki_enabled, as: [:default, :admin]
attr_accessible :namespace_id, :owner_id, as: :admin
attr_accessible :name, :path, :description, :code, :default_branch, :issues_enabled,
:wall_enabled, :merge_requests_enabled, :wiki_enabled
attr_accessor :error_code
# Relations
belongs_to :group
belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
belongs_to :namespace
# TODO: replace owner with creator.
# With namespaces a project owner will be a namespace owner
# so this field makes sense only for global projects
belongs_to :owner, class_name: "User"
has_many :users, through: :users_projects
has_many :events, dependent: :destroy
@ -54,36 +64,79 @@ class Project < ActiveRecord::Base
# Validations
validates :owner, presence: true
validates :description, length: { within: 0..2000 }
validates :name, uniqueness: true, presence: true, length: { within: 0..255 }
validates :path, uniqueness: true, presence: true, length: { within: 0..255 },
format: { with: /\A[a-zA-Z][a-zA-Z0-9_\-\.]*\z/,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :code, presence: true, uniqueness: true, length: { within: 1..255 },
format: { with: /\A[a-zA-Z][a-zA-Z0-9_\-\.]*\z/,
validates :name, presence: true, length: { within: 0..255 }
validates :path, presence: true, length: { within: 0..255 },
format: { with: Gitlab::Regex.path_regex,
message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" }
validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
:wiki_enabled, inclusion: { in: [true, false] }
validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id
validate :check_limit, :repo_name
# Scopes
scope :public_only, where(private_flag: false)
scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.projects.map(&:id) ) }
scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) }
scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
scope :joined, ->(user) { where("namespace_id != ?", user.namespace_id) }
class << self
def authorized_for user
projects = includes(:users_projects, :namespace)
projects = projects.where("users_projects.user_id = :user_id or projects.owner_id = :user_id or namespaces.owner_id = :user_id", user_id: user.id)
end
def active
joins(:issues, :notes, :merge_requests).order("issues.created_at, notes.created_at, merge_requests.created_at DESC")
end
def search query
where("name LIKE :query OR code LIKE :query OR path LIKE :query", query: "%#{query}%")
where("projects.name LIKE :query OR projects.path LIKE :query", query: "%#{query}%")
end
def find_with_namespace(id)
if id.include?("/")
id = id.split("/")
namespace_id = Namespace.find_by_path(id.first).id
where(namespace_id: namespace_id).find_by_path(id.last)
else
where(path: id, namespace_id: nil).last
end
end
def create_by_user(params, user)
namespace_id = params.delete(:namespace_id)
project = Project.new params
Project.transaction do
# Parametrize path for project
#
# Ex.
# 'GitLab HQ'.parameterize => "gitlab-hq"
#
project.path = project.name.dup.parameterize
project.owner = user
# Apply namespace if user has access to it
# else fallback to user namespace
if namespace_id != Namespace.global_id
project.namespace_id = user.namespace_id
if namespace_id
group = Group.find_by_id(namespace_id)
if user.can? :manage_group, group
project.namespace_id = namespace_id
end
end
end
project.save!
# Add user as project master
@ -126,7 +179,7 @@ class Project < ActiveRecord::Base
end
def repo_name
denied_paths = %w(gitolite-admin groups projects dashboard)
denied_paths = %w(gitolite-admin admin dashboard groups help profile projects search)
if denied_paths.include?(path)
errors.add(:path, "like #{path} is not allowed")
@ -134,11 +187,15 @@ class Project < ActiveRecord::Base
end
def to_param
code
if namespace
namespace.path + "/" + path
else
path
end
end
def web_url
[Gitlab.config.url, code].join("/")
[Gitlab.config.gitlab.url, path_with_namespace].join("/")
end
def common_notes
@ -146,15 +203,15 @@ class Project < ActiveRecord::Base
end
def build_commit_note(commit)
notes.new(noteable_id: commit.id, noteable_type: "Commit")
notes.new(commit_id: commit.id, noteable_type: "Commit")
end
def commit_notes(commit)
notes.where(noteable_id: commit.id, noteable_type: "Commit", line_code: nil)
notes.where(commit_id: commit.id, noteable_type: "Commit", line_code: nil)
end
def commit_line_notes(commit)
notes.where(noteable_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
notes.where(commit_id: commit.id, noteable_type: "Commit").where("line_code IS NOT NULL")
end
def public?
@ -173,10 +230,6 @@ class Project < ActiveRecord::Base
last_event.try(:created_at) || updated_at
end
def wiki_notes
Note.where(noteable_id: wikis.pluck(:id), noteable_type: 'Wiki', project_id: self.id)
end
def project_id
self.id
end
@ -192,4 +245,24 @@ class Project < ActiveRecord::Base
def gitlab_ci?
gitlab_ci_service && gitlab_ci_service.active
end
# For compatibility with old code
def code
path
end
def items_for entity
case entity
when 'issue' then
issues
when 'merge_request' then
merge_requests
end
end
def send_move_instructions
self.users_projects.each do |member|
Notify.project_was_moved_email(member.id).deliver
end
end
end

Some files were not shown because too many files have changed in this diff Show more