Commit 2bae8121 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch '6_5_ce' into 'master'

CE 6.5.0.rc1 into EE
parents 4dd2c896 2df9a760
v 6.5.0
- Dropdown menus on issue#show page for assignee and milestone (Jason Blanchard)
- Add color custimization and previewing to broadcast messages
- Fixed notes anchors
- Load new comments in issues dynamically
- Added sort options to Public page
- New filters (assigned/authored/all) for Dashboard#issues/merge_requests (sponsored by Say Media)
- Add project visibility icons to dashboard
- Enable secure cookies if https used
- Protect users/confirmation with rack_attack
- Default HTTP headers to protect against MIME-sniffing, force https if enabled
- Bootstrap 3 with responsive UI
- New repository download formats: tar.bz2, zip, tar (Jason Hollingsworth)
- Restyled accept widgets for MR
- SCSS refactored
- Use jquery timeago plugin
- Fix 500 error for rdoc files
- Ability to customize merge commit message (sponsored by Say Media)
- Search autocomplete via ajax
- Add website url to user profile
- Files API supports base64 encoded content (sponsored by O'Reilly Media)
- Added support for Go's repository retrieval (Bruno Albuquerque)
v6.4.3
- Don't use unicorn worker killer if PhusionPassenger is defined
v6.4.2 v6.4.2
- Fixed wrong behaviour of script/upgrade.rb - Fixed wrong behaviour of script/upgrade.rb
......
This diff is collapsed.
...@@ -30,7 +30,7 @@ gem 'omniauth-github' ...@@ -30,7 +30,7 @@ gem 'omniauth-github'
# Extracting information from a git repository # Extracting information from a git repository
# Provide access to Gitlab::Git library # Provide access to Gitlab::Git library
gem "gitlab_git", "~> 4.0.0.pre" gem "gitlab_git", "~> 4.0.0"
# Ruby/Rack Git Smart-HTTP Server Handler # Ruby/Rack Git Smart-HTTP Server Handler
gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack' gem 'gitlab-grack', '~> 2.0.0.pre', require: 'grack'
...@@ -53,6 +53,9 @@ gem "grape", "~> 0.6.1" ...@@ -53,6 +53,9 @@ gem "grape", "~> 0.6.1"
gem "grape-entity", "~> 0.3.0" gem "grape-entity", "~> 0.3.0"
gem 'rack-cors', require: 'rack/cors' gem 'rack-cors', require: 'rack/cors'
# Email validation
gem "email_validator", "~> 1.4.0", :require => 'email_validator/strict'
# Format dates and times # Format dates and times
# based on human-friendly examples # based on human-friendly examples
gem "stamp" gem "stamp"
...@@ -61,7 +64,7 @@ gem "stamp" ...@@ -61,7 +64,7 @@ gem "stamp"
gem 'enumerize' gem 'enumerize'
# Pagination # Pagination
gem "kaminari", "~> 0.14.1" gem "kaminari", "~> 0.15.1"
# HAML # HAML
gem "haml-rails" gem "haml-rails"
...@@ -80,7 +83,7 @@ gem "seed-fu" ...@@ -80,7 +83,7 @@ gem "seed-fu"
# Markdown to HTML # Markdown to HTML
gem "redcarpet", "~> 2.2.2" gem "redcarpet", "~> 2.2.2"
gem "github-markup", "~> 0.7.4", require: 'github/markup' gem "github-markup", "~> 0.7.4", require: 'github/markup', git: 'https://github.com/gitlabhq/markup.git', ref: '61ade389c1e1c159359338f570d18464a44ddbc4'
# Asciidoc to HTML # Asciidoc to HTML
gem "asciidoctor" gem "asciidoctor"
...@@ -121,7 +124,7 @@ gem "redis-rails" ...@@ -121,7 +124,7 @@ gem "redis-rails"
gem 'tinder', '~> 1.9.2' gem 'tinder', '~> 1.9.2'
# HipChat integration # HipChat integration
gem "hipchat", "~> 0.9.0" gem "hipchat", "~> 0.14.0"
# Flowdock integration # Flowdock integration
gem "gitlab-flowdock-git-hook", "~> 0.4.2" gem "gitlab-flowdock-git-hook", "~> 0.4.2"
...@@ -145,17 +148,16 @@ gem "therubyracer" ...@@ -145,17 +148,16 @@ gem "therubyracer"
gem 'turbolinks' gem 'turbolinks'
gem 'jquery-turbolinks' gem 'jquery-turbolinks'
gem 'chosen-rails', "1.0.1"
gem 'select2-rails' gem 'select2-rails'
gem 'jquery-atwho-rails', "~> 0.3.3" gem 'jquery-atwho-rails', "~> 0.3.3"
gem "jquery-rails", "2.1.3" gem "jquery-rails", "2.1.3"
gem "jquery-ui-rails", "2.0.2" gem "jquery-ui-rails", "2.0.2"
gem "modernizr", "2.6.2" gem "modernizr", "2.6.2"
gem "raphael-rails", "~> 2.1.2" gem "raphael-rails", "~> 2.1.2"
gem 'bootstrap-sass', '~> 2.3' gem 'bootstrap-sass', '~> 3.0'
gem "font-awesome-rails", '~> 3.2' gem "font-awesome-rails", '~> 3.2'
gem "gemoji", "~> 1.3.0" gem "gemoji", "~> 1.3.0"
gem "gon", git: "https://github.com/gitlabhq/gon.git", ref: '58ca8e17273051cb370182cabd3602d1da6783ab' gem "gon", '~> 5.0.0'
group :development do group :development do
gem "annotate", "~> 2.6.0.beta2" gem "annotate", "~> 2.6.0.beta2"
......
GIT GIT
remote: https://github.com/gitlabhq/gon.git remote: https://github.com/gitlabhq/markup.git
revision: 58ca8e17273051cb370182cabd3602d1da6783ab revision: 61ade389c1e1c159359338f570d18464a44ddbc4
ref: 58ca8e17273051cb370182cabd3602d1da6783ab ref: 61ade389c1e1c159359338f570d18464a44ddbc4
specs: specs:
gon (4.1.1) github-markup (0.7.6)
actionpack (>= 2.3.0)
json
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
...@@ -57,7 +55,7 @@ GEM ...@@ -57,7 +55,7 @@ GEM
erubis (>= 2.6.6) erubis (>= 2.6.6)
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
bootstrap-sass (2.3.2.2) bootstrap-sass (3.0.3.0)
sass (~> 3.2) sass (~> 3.2)
builder (3.1.4) builder (3.1.4)
capybara (2.1.0) capybara (2.1.0)
...@@ -73,12 +71,6 @@ GEM ...@@ -73,12 +71,6 @@ GEM
celluloid (0.15.2) celluloid (0.15.2)
timers (~> 1.1.0) timers (~> 1.1.0)
charlock_holmes (0.6.9.4) charlock_holmes (0.6.9.4)
chosen-rails (1.0.1)
coffee-rails (>= 3.2)
compass-rails (>= 1.0)
railties (>= 3.0)
sass-rails (>= 3.2)
chunky_png (1.2.9)
cliver (0.2.2) cliver (0.2.2)
code_analyzer (0.4.3) code_analyzer (0.4.3)
sexp_processor sexp_processor
...@@ -94,12 +86,6 @@ GEM ...@@ -94,12 +86,6 @@ GEM
coffee-script-source (1.6.3) coffee-script-source (1.6.3)
colored (1.2) colored (1.2)
colorize (0.5.8) colorize (0.5.8)
compass (0.12.2)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.1)
compass-rails (1.1.1)
compass (>= 0.12.2)
connection_pool (1.2.0) connection_pool (1.2.0)
coveralls (0.7.0) coveralls (0.7.0)
multi_json (~> 1.3) multi_json (~> 1.3)
...@@ -128,6 +114,8 @@ GEM ...@@ -128,6 +114,8 @@ GEM
email_spec (1.5.0) email_spec (1.5.0)
launchy (~> 2.1) launchy (~> 2.1)
mail (~> 2.2) mail (~> 2.2)
email_validator (1.4.0)
activemodel
enumerize (0.7.0) enumerize (0.7.0)
activesupport (>= 3.2) activesupport (>= 3.2)
equalizer (0.0.8) equalizer (0.0.8)
...@@ -163,12 +151,10 @@ GEM ...@@ -163,12 +151,10 @@ GEM
dotenv (>= 0.7) dotenv (>= 0.7)
thor (>= 0.13.6) thor (>= 0.13.6)
formatador (0.2.4) formatador (0.2.4)
fssm (0.2.10)
gemoji (1.3.1) gemoji (1.3.1)
gherkin-ruby (0.3.1) gherkin-ruby (0.3.1)
racc racc
github-markdown (0.5.5) github-markdown (0.5.5)
github-markup (0.7.5)
gitlab-flowdock-git-hook (0.4.2.2) gitlab-flowdock-git-hook (0.4.2.2)
gitlab-grit (>= 2.4.1) gitlab-grit (>= 2.4.1)
multi_json multi_json
...@@ -195,7 +181,7 @@ GEM ...@@ -195,7 +181,7 @@ GEM
gitlab-pygments.rb (0.5.4) gitlab-pygments.rb (0.5.4)
posix-spawn (~> 0.3.6) posix-spawn (~> 0.3.6)
yajl-ruby (~> 1.1.0) yajl-ruby (~> 1.1.0)
gitlab_git (4.0.0.pre) gitlab_git (4.0.0)
activesupport (~> 4.0.0) activesupport (~> 4.0.0)
gitlab-grit (~> 2.6.1) gitlab-grit (~> 2.6.1)
gitlab-linguist (~> 2.9.5) gitlab-linguist (~> 2.9.5)
...@@ -206,6 +192,9 @@ GEM ...@@ -206,6 +192,9 @@ GEM
omniauth (~> 1.0) omniauth (~> 1.0)
pyu-ruby-sasl (~> 0.0.3.1) pyu-ruby-sasl (~> 0.0.3.1)
rubyntlm (~> 0.1.1) rubyntlm (~> 0.1.1)
gon (5.0.1)
actionpack (>= 2.3.0)
json
grape (0.6.1) grape (0.6.1)
activesupport activesupport
builder builder
...@@ -241,7 +230,7 @@ GEM ...@@ -241,7 +230,7 @@ GEM
railties (~> 4.0.0) railties (~> 4.0.0)
hashie (2.0.5) hashie (2.0.5)
hike (1.2.3) hike (1.2.3)
hipchat (0.9.0) hipchat (0.14.0)
httparty httparty
httparty httparty
http_parser.rb (0.5.3) http_parser.rb (0.5.3)
...@@ -270,7 +259,7 @@ GEM ...@@ -270,7 +259,7 @@ GEM
json (1.8.1) json (1.8.1)
jwt (0.1.8) jwt (0.1.8)
multi_json (>= 1.5) multi_json (>= 1.5)
kaminari (0.14.1) kaminari (0.15.1)
actionpack (>= 3.0.0) actionpack (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
kgio (2.8.1) kgio (2.8.1)
...@@ -292,7 +281,7 @@ GEM ...@@ -292,7 +281,7 @@ GEM
minitest (4.7.5) minitest (4.7.5)
modernizr (2.6.2) modernizr (2.6.2)
sprockets (~> 2.0) sprockets (~> 2.0)
multi_json (1.8.2) multi_json (1.8.4)
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (1.2.0) multipart-post (1.2.0)
mysql2 (0.3.11) mysql2 (0.3.11)
...@@ -569,10 +558,9 @@ DEPENDENCIES ...@@ -569,10 +558,9 @@ DEPENDENCIES
awesome_print awesome_print
better_errors better_errors
binding_of_caller binding_of_caller
bootstrap-sass (~> 2.3) bootstrap-sass (~> 3.0)
capybara capybara
carrierwave carrierwave
chosen-rails (= 1.0.1)
coffee-rails coffee-rails
colored colored
coveralls coveralls
...@@ -581,6 +569,7 @@ DEPENDENCIES ...@@ -581,6 +569,7 @@ DEPENDENCIES
devise (= 3.0.4) devise (= 3.0.4)
devise-async (= 0.8.0) devise-async (= 0.8.0)
email_spec email_spec
email_validator (~> 1.4.0)
enumerize enumerize
factory_girl_rails factory_girl_rails
ffaker ffaker
...@@ -588,30 +577,30 @@ DEPENDENCIES ...@@ -588,30 +577,30 @@ DEPENDENCIES
font-awesome-rails (~> 3.2) font-awesome-rails (~> 3.2)
foreman foreman
gemoji (~> 1.3.0) gemoji (~> 1.3.0)
github-markup (~> 0.7.4) github-markup (~> 0.7.4)!
gitlab-flowdock-git-hook (~> 0.4.2) gitlab-flowdock-git-hook (~> 0.4.2)
gitlab-gollum-lib (~> 1.0.2) gitlab-gollum-lib (~> 1.0.2)
gitlab-grack (~> 2.0.0.pre) gitlab-grack (~> 2.0.0.pre)
gitlab-linguist (~> 2.9.6) gitlab-linguist (~> 2.9.6)
gitlab-pygments.rb (~> 0.5.4) gitlab-pygments.rb (~> 0.5.4)
gitlab_git (~> 4.0.0.pre) gitlab_git (~> 4.0.0)
gitlab_meta (= 6.0) gitlab_meta (= 6.0)
gitlab_omniauth-ldap (= 1.0.3) gitlab_omniauth-ldap (= 1.0.3)
gon! gon (~> 5.0.0)
grape (~> 0.6.1) grape (~> 0.6.1)
grape-entity (~> 0.3.0) grape-entity (~> 0.3.0)
growl growl
guard-rspec guard-rspec
guard-spinach guard-spinach
haml-rails haml-rails
hipchat (~> 0.9.0) hipchat (~> 0.14.0)
httparty httparty
jasmine (= 2.0.0.rc5) jasmine (= 2.0.0.rc5)
jquery-atwho-rails (~> 0.3.3) jquery-atwho-rails (~> 0.3.3)
jquery-rails (= 2.1.3) jquery-rails (= 2.1.3)
jquery-turbolinks jquery-turbolinks
jquery-ui-rails (= 2.0.2) jquery-ui-rails (= 2.0.2)
kaminari (~> 0.14.1) kaminari (~> 0.15.1)
launchy launchy
letter_opener letter_opener
minitest (~> 4.7.0) minitest (~> 4.7.0)
......
This diff is collapsed.
## GitLab: self hosted Git management software ## GitLab: self hosted Git management software
![logo](https://raw.github.com/gitlabhq/gitlabhq/master/public/gitlab_logo.png) ![logo](https://gitlab.com/gitlab-org/gitlab-ce/raw/master/public/gitlab_logo.png)
![animated-screenshots](https://gist.github.com/fnkr/2f9badd56bfe0ed04ee7/raw/4f48806fbae97f556c2f78d8c2d299c04500cb0d/compiled.gif) ![animated-screenshots](https://gist.github.com/fnkr/2f9badd56bfe0ed04ee7/raw/4f48806fbae97f556c2f78d8c2d299c04500cb0d/compiled.gif)
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* [GitLab Enterprise Edition](https://www.gitlab.com/features/) offers additional features that are useful for larger organizations (100+ users). * [GitLab Enterprise Edition](https://www.gitlab.com/features/) offers additional features that are useful for larger organizations (100+ users).
* [GitLab CI](https://github.com/gitlabhq/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab. * [GitLab CI](https://gitlab.com/gitlab-org/gitlab-ci/blob/master/README.md) is a continuous integration (CI) server that is easy to integrate with GitLab.
### Requirements ### Requirements
...@@ -62,7 +62,7 @@ ...@@ -62,7 +62,7 @@
#### Unofficial installation methods #### Unofficial installation methods
* [GitLab recipes](https://github.com/gitlabhq/gitlab-recipes) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version. * [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/) repository with unofficial guides for using GitLab with different software (operating systems, webservers, etc.) than the official version.
* [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems. * [Installation guides](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Unofficial-Installation-Guides) public wiki with unofficial guides to install GitLab on different operating systems.
...@@ -145,13 +145,13 @@ or start each component separately ...@@ -145,13 +145,13 @@ or start each component separately
* [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab. * [Feedback and suggestions forum](http://feedback.gitlab.com) is the place to propose and discuss new features for GitLab.
* [Contributing guide](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) describes how to submit pull requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed. * [Contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md) describes how to submit merge requests and issues. Pull requests and issues not in line with the guidelines in this document will be closed.
* [Support subscription](http://www.gitlab.com/subscription/) connects you to the knowledge of GitLab experts that will resolve your issues and answer your questions. * [Support subscription](http://www.gitlab.com/subscription/) connects you to the knowledge of GitLab experts that will resolve your issues and answer your questions.
* [Consultancy](http://www.gitlab.com/consultancy/) from the GitLab experts for installations, upgrades and customizations. * [Consultancy](http://www.gitlab.com/consultancy/) from the GitLab experts for installations, upgrades and customizations.
* [#gitlab IRC channel](http://www.freenode.net/) on Freenode to get in touch with other GitLab users and get help, it's managed by James Newton, Drew Blessing and Sam Gleske * [#gitlab IRC channel](http://www.freenode.net/) on Freenode to get in touch with other GitLab users and get help, it's managed by James Newton (newton), Drew Blessing (dblessing), and Sam Gleske (sag47).
* [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview. * [Book](http://www.packtpub.com/gitlab-repository-management/book) written by GitLab enthusiast Jonathan M. Hethey is unofficial but it offers a good overview.
......
...@@ -8,6 +8,23 @@ class Admin ...@@ -8,6 +8,23 @@ class Admin
else else
elems.removeAttr 'disabled' elems.removeAttr 'disabled'
$('body').on 'click', '.js-toggle-colors-link', (e) ->
e.preventDefault()
$('.js-toggle-colors-link').hide()
$('.js-toggle-colors-container').show()
$('input#broadcast_message_color').on 'input', ->
previewColor = $('input#broadcast_message_color').val()
$('div.broadcast-message-preview').css('background-color', previewColor)
$('input#broadcast_message_font').on 'input', ->
previewColor = $('input#broadcast_message_font').val()
$('div.broadcast-message-preview').css('color', previewColor)
$('textarea#broadcast_message_message').on 'input', ->
previewMessage = $('textarea#broadcast_message_message').val()
$('div.broadcast-message-preview span').text(previewMessage)
$('.log-tabs a').click (e) -> $('.log-tabs a').click (e) ->
e.preventDefault() e.preventDefault()
$(this).tab('show') $(this).tab('show')
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
//= require jquery.turbolinks //= require jquery.turbolinks
//= require bootstrap //= require bootstrap
//= require modernizr //= require modernizr
//= require chosen-jquery
//= require select2 //= require select2
//= require raphael //= require raphael
//= require g.raphael-min //= require g.raphael-min
......
...@@ -3,7 +3,7 @@ $ -> ...@@ -3,7 +3,7 @@ $ ->
container = $(@).closest(".js-toggler-container") container = $(@).closest(".js-toggler-container")
container.toggleClass("on") container.toggleClass("on")
$("body").on "click", ".js-toggle-visibility-link", (e) -> $("body").on "click", ".js-toggle-visibility-link", (e) ->
$(@).find('i'). $(@).find('i').
toggleClass('icon-chevron-down'). toggleClass('icon-chevron-down').
...@@ -11,7 +11,7 @@ $ -> ...@@ -11,7 +11,7 @@ $ ->
container = $(".js-toggle-visibility-container") container = $(".js-toggle-visibility-container")
container.toggleClass("hide") container.toggleClass("hide")
e.preventDefault() e.preventDefault()
$("body").on "click", ".js-toggle-button", (e) -> $("body").on "click", ".js-toggle-button", (e) ->
$(@).closest(".js-toggle-container").find(".js-toggle-content").toggle() $(@).closest(".js-toggle-container").find(".js-toggle-content").toggle()
e.preventDefault() e.preventDefault()
...@@ -194,11 +194,14 @@ class BranchGraph ...@@ -194,11 +194,14 @@ class BranchGraph
fill: @colors[commit.space] fill: @colors[commit.space]
stroke: "none" stroke: "none"
) )
r.rect(@offsetX + @unitSpace * @mspace + 10, y - 10, 20, 20).attr(
fill: "url(#{commit.author.icon})" avatar_box_x = @offsetX + @unitSpace * @mspace + 10
avatar_box_y = y - 10
r.rect(avatar_box_x, avatar_box_y, 20, 20).attr(
stroke: @colors[commit.space] stroke: @colors[commit.space]
"stroke-width": 2 "stroke-width": 2
) )
r.image(commit.author.icon, avatar_box_x, avatar_box_y, 20, 20)
r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr( r.text(@offsetX + @unitSpace * @mspace + 35, y, commit.message.split("\n")[0]).attr(
"text-anchor": "start" "text-anchor": "start"
font: "14px Monaco, monospace" font: "14px Monaco, monospace"
......
...@@ -47,5 +47,9 @@ class Dispatcher ...@@ -47,5 +47,9 @@ class Dispatcher
initSearch: -> initSearch: ->
autocomplete_json = $('.search-autocomplete-json').data('autocomplete-opts') opts = $('.search-autocomplete-opts')
new SearchAutocomplete(autocomplete_json) path = opts.data('autocomplete-path')
project_id = opts.data('autocomplete-project-id')
project_ref = opts.data('autocomplete-project-ref')
new SearchAutocomplete(path, project_id, project_ref)
...@@ -29,12 +29,10 @@ ...@@ -29,12 +29,10 @@
$('#filter_issue_search').val($('#issue_search').val()) $('#filter_issue_search').val($('#issue_search').val())
initSelects: -> initSelects: ->
$("#update_status").chosen() $("select#update_status").select2(width: 'resolve', dropdownAutoWidth: true)
$("#update_assignee_id").chosen() $("select#update_assignee_id").select2(width: 'resolve', dropdownAutoWidth: true)
$("#update_milestone_id").chosen() $("select#update_milestone_id").select2(width: 'resolve', dropdownAutoWidth: true)
$("#label_name").chosen() $("select#label_name").select2(width: 'resolve', dropdownAutoWidth: true)
$("#assignee_id").chosen()
$("#milestone_id").chosen()
$("#milestone_id, #assignee_id, #label_name").on "change", -> $("#milestone_id, #assignee_id, #label_name").on "change", ->
$(this).closest("form").submit() $(this).closest("form").submit()
...@@ -79,3 +77,9 @@ ...@@ -79,3 +77,9 @@
$("#update_issues_ids").val [] $("#update_issues_ids").val []
$(".issues_bulk_update").hide() $(".issues_bulk_update").hide()
$(".issues-filters").show() $(".issues-filters").show()
$ ->
$('.edit-issue.inline-update input[type="submit"]').hide();
$("body").on "change", ".edit-issue.inline-update select", ->
$(this).submit()
...@@ -67,8 +67,8 @@ $ -> ...@@ -67,8 +67,8 @@ $ ->
$('.appear-data').fadeIn() $('.appear-data').fadeIn()
e.preventDefault() e.preventDefault()
# Initialize chosen selects # Initialize select2 selects
$('select.chosen').chosen() $('select.select2').select2(width: 'resolve', dropdownAutoWidth: true)
# Initialize tooltips # Initialize tooltips
$('.has_tooltip').tooltip() $('.has_tooltip').tooltip()
...@@ -81,6 +81,7 @@ $ -> ...@@ -81,6 +81,7 @@ $ ->
$(@).parents('form').submit() $(@).parents('form').submit()
$("abbr.timeago").timeago() $("abbr.timeago").timeago()
$('.js-timeago').timeago()
# Flash # Flash
if (flash = $(".flash-container")).length > 0 if (flash = $(".flash-container")).length > 0
...@@ -125,12 +126,6 @@ $ -> ...@@ -125,12 +126,6 @@ $ ->
$(@).remove() $(@).remove()
(($) -> (($) ->
_chosen = $.fn.chosen
$.fn.extend chosen: (options) ->
default_options = search_contains: "true"
$.extend default_options, options
_chosen.apply @, [default_options]
# Disable an element and add the 'disabled' Bootstrap class # Disable an element and add the 'disabled' Bootstrap class
$.fn.extend disable: -> $.fn.extend disable: ->
$(@).attr('disabled', 'disabled').addClass('disabled') $(@).attr('disabled', 'disabled').addClass('disabled')
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
# * Filter merge requests # * Filter merge requests
# #
@merge_requestsPage = -> @merge_requestsPage = ->
$('#assignee_id').chosen() $('#assignee_id').select2()
$('#milestone_id').chosen() $('#milestone_id').select2()
$('#milestone_id, #assignee_id').on 'change', -> $('#milestone_id, #assignee_id').on 'change', ->
$(this).closest('form').submit() $(this).closest('form').submit()
...@@ -24,6 +24,8 @@ class MergeRequest ...@@ -24,6 +24,8 @@ class MergeRequest
modal = $('#modal_merge_info').modal(show: false) modal = $('#modal_merge_info').modal(show: false)
disableButtonIfEmptyField '#merge_commit_message', '.accept_merge_request'
# Local jQuery finder # Local jQuery finder
$: (selector) -> $: (selector) ->
this.$el.find(selector) this.$el.find(selector)
......
This diff is collapsed.
This diff is collapsed.
class NotesVotes
updateVotes: ->
votes = $("#votes .votes")
notes = $("#notes-list .note .vote")
# only update if there is a vote display
if votes.size()
upvotes = notes.filter(".upvote").size()
downvotes = notes.filter(".downvote").size()
votesCount = upvotes + downvotes
upvotesPercent = (if votesCount then (100.0 / votesCount * upvotes) else 0)
downvotesPercent = (if votesCount then (100.0 - upvotesPercent) else 0)
# change vote bar lengths
votes.find(".bar-success").css "width", upvotesPercent + "%"
votes.find(".bar-danger").css "width", downvotesPercent + "%"
# replace vote numbers
votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes)
votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes)
@NotesVotes = NotesVotes
...@@ -35,7 +35,7 @@ $ -> ...@@ -35,7 +35,7 @@ $ ->
$('a, button', scope).removeClass 'active' $('a, button', scope).removeClass 'active'
$(@).addClass 'active' $(@).addClass 'active'
$('#project_clone', scope).val $(@).data 'clone' $('#project_clone', scope).val $(@).data 'clone'
$(".clone").text("").append 'git remote add origin ' + $(@).data 'clone' $(".clone").text("").append $(@).data 'clone'
# Ref switcher # Ref switcher
$('.project-refs-select').on 'change', -> $('.project-refs-select').on 'change', ->
......
class SearchAutocomplete class SearchAutocomplete
constructor: (json) -> constructor: (search_autocomplete_path, project_id, project_ref) ->
project_id = '' unless project_id
project_ref = '' unless project_ref
query = "?project_id=" + project_id + "&project_ref=" + project_ref
$("#search").autocomplete $("#search").autocomplete
source: json source: search_autocomplete_path + query
minLength: 1
select: (event, ui) -> select: (event, ui) ->
location.href = ui.item.url location.href = ui.item.url
......
...@@ -46,11 +46,7 @@ class window.ContributorsGraph ...@@ -46,11 +46,7 @@ class window.ContributorsGraph
class window.ContributorsMasterGraph extends ContributorsGraph class window.ContributorsMasterGraph extends ContributorsGraph
constructor: (@data) -> constructor: (@data) ->
if $(window).width() > 1214 @width = $('.container').width() - 70
@width = 1100
else
@width = 870
@height = 200 @height = 200
@x = null @x = null
@y = null @y = null
...@@ -88,7 +84,6 @@ class window.ContributorsMasterGraph extends ContributorsGraph ...@@ -88,7 +84,6 @@ class window.ContributorsMasterGraph extends ContributorsGraph
x(d.date) x(d.date)
).y0(@height).y1((d) -> ).y0(@height).y1((d) ->
xa = d.commits = d.commits ? d.additions ? d.deletions xa = d.commits = d.commits ? d.additions ? d.deletions
console.log(xa)
y(xa) y(xa)
).interpolate("basis") ).interpolate("basis")
create_brush: -> create_brush: ->
...@@ -124,11 +119,7 @@ class window.ContributorsMasterGraph extends ContributorsGraph ...@@ -124,11 +119,7 @@ class window.ContributorsMasterGraph extends ContributorsGraph
class window.ContributorsAuthorGraph extends ContributorsGraph class window.ContributorsAuthorGraph extends ContributorsGraph
constructor: (@data) -> constructor: (@data) ->
if $(window).width() > 1214 @width = $('.container').width()/2 - 100
@width = 490
else
@width = 380
@height = 200 @height = 200
@x = null @x = null
@y = null @y = null
......
...@@ -6,12 +6,12 @@ $ -> ...@@ -6,12 +6,12 @@ $ ->
avatar = gon.gravatar_url avatar = gon.gravatar_url
avatar = avatar.replace('%{hash}', md5(user.email)) avatar = avatar.replace('%{hash}', md5(user.email))
avatar = avatar.replace('%{size}', '24') avatar = avatar.replace('%{size}', '24')
markup = "<div class='user-result'>"
markup += "<div class='user-image'><img class='avatar s24' src='" + avatar + "'></div>" "<div class='user-result'>
markup += "<div class='user-name'>" + user.name + "</div>" <div class='user-image'><img class='avatar s24' src='#{avatar}'></div>
markup += "<div class='user-username'>" + user.username + "</div>" <div class='user-name'>#{user.name}</div>
markup += "</div>" <div class='user-username'>#{user.username}</div>
markup </div>"
userFormatSelection = (user) -> userFormatSelection = (user) ->
user.name user.name
......
...@@ -4,19 +4,44 @@ ...@@ -4,19 +4,44 @@
* the top of the compiled file, but it's generally better to create a new file per style scope. * 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.ui.gitlab
*= require jquery.atwho *= require jquery.atwho
*= require chosen
*= require select2 *= require select2
*= require_self *= require_self
*/ */
@import "main/variables.scss";
@import "main/mixins.scss";
@import "main/fonts.scss";
@import "main/layout.scss";
/**
* Customized Twitter bootstrap
*/
@import 'gl_bootstrap';
/** /**
* GitLab bootstrap: * Font icons
*
*/ */
@import "gitlab_bootstrap.scss"; @import "font-awesome";
@import "common.scss"; /**
@import "selects.scss"; * Generic css (forms, nav etc):
*/
@import "generic/avatar.scss";
@import "generic/common.scss";
@import "generic/typography.scss";
@import "generic/buttons.scss";
@import "generic/blocks.scss";
@import "generic/ui_box.scss";
@import "generic/issue_box.scss";
@import "generic/files.scss";
@import "generic/lists.scss";
@import "generic/forms.scss";
@import "generic/selects.scss";
/**
* Page specific styles (issues, projects etc):
*/
@import "sections/header.scss"; @import "sections/header.scss";
@import "sections/nav.scss"; @import "sections/nav.scss";
@import "sections/commits.scss"; @import "sections/commits.scss";
...@@ -39,6 +64,9 @@ ...@@ -39,6 +64,9 @@
@import "sections/dashboard.scss"; @import "sections/dashboard.scss";
@import "sections/stat_graph.scss"; @import "sections/stat_graph.scss";
/**
* Code ighlight
*/
@import "highlight/white.scss"; @import "highlight/white.scss";
@import "highlight/dark.scss"; @import "highlight/dark.scss";
@import "highlight/solarized_dark.scss"; @import "highlight/solarized_dark.scss";
...@@ -57,4 +85,3 @@ ...@@ -57,4 +85,3 @@
* Styles for JS behaviors. * Styles for JS behaviors.
*/ */
@import "behaviors.scss"; @import "behaviors.scss";
.light-well {
background: #f9f9f9;
padding: 15px;
}
...@@ -143,16 +143,27 @@ ...@@ -143,16 +143,27 @@
line-height: 16px; line-height: 16px;
margin: 2px; margin: 2px;
} }
}
.btn-block {
width: 100%;
margin: 0;
margin-bottom: 15px;
&.btn {
padding: 6px 0;
}
}
.btn,
.btn-group {
&.grouped { &.grouped {
margin-right: 7px; margin-right: 7px;
float: left; float: left;
} &:last-child {
margin-right: 0px;
&.btn-block { }
width: 100%;
margin: 0;
padding: 6px 0;
margin-bottom: 15px;
} }
} }
.btn-group-small > .btn { @extend .btn.btn-small; }
.btn-group-tiny > .btn { @extend .btn.btn-tiny; }
html { /** COLORS **/
overflow-y: scroll; .cgray { color: gray }
.clgray { color: #BBB }
.cred { color: #D12F19 }
.cgreen { color: #4a2 }
.cblue { color: #29A }
.cblack { color: #111 }
.cdark { color: #444 }
.camber { color: #ffc000 }
.cwhite { color: #fff!important }
.bgred { background: #F2DEDE!important }
/** COMMON CLASSES **/
.left { float:left }
.prepend-top-10 { margin-top:10px }
.prepend-top-20 { margin-top:20px }
.prepend-left-10 { margin-left:10px }
.prepend-left-20 { margin-left:20px }
.append-right-10 { margin-right:10px }
.append-right-20 { margin-right:20px }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-15 { margin-bottom:15px }
.append-bottom-20 { margin-bottom:20px }
.inline { display: inline-block }
.padded { padding:20px }
.ipadded { padding:20px!important }
.lborder { border-left:1px solid #eee }
.underlined_link { text-decoration: underline; }
.hint { font-style: italic; color: #999; }
.light { color: #888 }
.tiny { font-weight: normal }
.vtop { vertical-align: top !important; }
/** ALERT MESSAGES **/
.alert.alert-disabled {
background: #EEE;
color: #777;
border-color: #DDD;
}
/** HELPERS **/
.nothing_here_message {
text-align: center;
padding: 20px;
color: #666;
font-weight: normal;
font-size: 16px;
line-height: 36px;
} }
/** LAYOUT **/ .slead {
color: #666;
body { font-size: 14px;
-webkit-font-smoothing: antialiased; margin-bottom: 12px;
margin-bottom: 20px; font-weight: normal;
line-height: 24px;
} }
.container {
padding-top: 0; .tab-content {
z-index: 5; overflow: visible;
} }
.container .content { @media (max-width: 1200px) {
margin: 0 0; .only-wide {
display: none;
}
} }
.author_link { pre.well-pre {
color: $link_color; border: 1px solid #EEE;
background: #f9f9f9;
border-radius: 0;
color: #555;
} }
.help li { color:$style_color; } .input-append .btn.active, .input-prepend .btn.active {
background: #CCC;
border-color: #BBB;
text-shadow: 0 1px 1px #fff;
font-weight: bold;
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
}
.back-link { /** Big Labels **/
.state-label {
font-size: 14px; font-size: 14px;
padding: 6px 25px;
text-align: center;
@include border-radius(4px);
text-shadow: none;
margin-left: 10px;
&.state-label-green {
background: #4A4;
color: #FFF;
}
&.state-label-red {
background: #DA4E49;
color: #FFF;
}
} }
table a code { .dropdown-menu > li > a {
position: relative; text-shadow: none;
top: -2px;
margin-right: 3px;
} }
.loading { .dropdown-menu > li > a:hover,
margin: 20px auto; .dropdown-menu > li > a:focus {
background: url(ajax_loader.gif) no-repeat center center; background: #29b;
width: 40px; }
height: 40px;
&.loading-gray { .breadcrumb > li + li:before {
background: url(ajax_loader_gray.gif) no-repeat center center; content: "/";
} padding: 0;
color: #666;
}
.str-truncated {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
white-space: nowrap;
max-width: 82%;
} }
/** FLASH message **/ /** FLASH message **/
...@@ -70,6 +155,31 @@ table a code { ...@@ -70,6 +155,31 @@ table a code {
padding: 10px; padding: 10px;
} }
} }
.author_link {
color: $link_color;
}
.help li { color:$style_color; }
.back-link {
font-size: 14px;
}
table a code {
position: relative;
top: -2px;
margin-right: 3px;
}
.loading {
margin: 20px auto;
background: url(ajax_loader.gif) no-repeat center center;
width: 40px;
height: 40px;
&.loading-gray {
background: url(ajax_loader_gray.gif) no-repeat center center;
}
}
span.update-author { span.update-author {
display: block; display: block;
...@@ -91,19 +201,6 @@ span.update-author { ...@@ -91,19 +201,6 @@ span.update-author {
display: inline; display: inline;
} }
ul.breadcrumb {
background: white;
border: none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
font-size: 16px;
}
}
.line_holder { .line_holder {
&:hover { &:hover {
td { td {
...@@ -118,18 +215,6 @@ p.time { ...@@ -118,18 +215,6 @@ p.time {
margin: 30px 3px 3px 2px; margin: 30px 3px 3px 2px;
} }
.search-holder {
label, input {
height: 30px;
padding: 0;
font-size: 14px;
}
label {
line-height: 30px;
color: #666;
}
}
.highlight { .highlight {
text-shadow: none; text-shadow: none;
} }
...@@ -208,7 +293,7 @@ li.note { ...@@ -208,7 +293,7 @@ li.note {
} }
.git_error_tips { .git_error_tips {
@extend .span6; @extend .col-md-6;
text-align: left; text-align: left;
margin-top: 40px; margin-top: 40px;
pre { pre {
...@@ -235,6 +320,7 @@ li.note { ...@@ -235,6 +320,7 @@ li.note {
background: #C67; background: #C67;
margin: 0; margin: 0;
color: #FFF; color: #FFF;
margin-top: -1px;
text-align: center; text-align: center;
a { a {
...@@ -352,12 +438,6 @@ table { ...@@ -352,12 +438,6 @@ table {
min-height: 100px; min-height: 100px;
} }
.navbar-gitlab .navbar-inner .nav > li .btn-sign-in {
@extend .btn-new;
padding: 5px 15px;
text-shadow: none;
}
.broadcast-message { .broadcast-message {
padding: 10px; padding: 10px;
text-align: center; text-align: center;
...@@ -365,6 +445,11 @@ table { ...@@ -365,6 +445,11 @@ table {
color: #BBB; color: #BBB;
} }
.broadcast-message-preview {
@extend .broadcast-message;
margin-bottom: 20px;
}
.ajax-users-select { .ajax-users-select {
width: 400px; width: 400px;
...@@ -398,3 +483,14 @@ table { ...@@ -398,3 +483,14 @@ table {
font-weight: bolder; font-weight: bolder;
} }
} }
.btn-sign-in {
margin-top: 7px;
text-shadow: none;
}
.side-filters {
fieldset {
margin-bottom: 15px;
}
}
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
text-align: left; text-align: left;
color: $style_color; color: $style_color;
padding: 9px 10px; padding: 9px 10px;
height: 18px;
.options { .options {
float: right; float: right;
...@@ -46,7 +45,7 @@ ...@@ -46,7 +45,7 @@
text-align: center; text-align: center;
img { img {
padding: 100px; padding: 100px;
max-width: 300px; max-width: 50%;
} }
} }
......
form {
@extend .form-horizontal;
label {
@extend .control-label;
&.radio-label {
text-align: left;
width: 100%;
margin-left: 0;
input[type="radio"] {
margin-top: 1px !important;
}
}
&.list-label {
float: none;
padding: 0 !important;
margin: 0;
text-align: left;
}
}
}
input.input-xpadding,
.add-on.input-xpadding {
padding: 6px 10px;
}
.control-group {
.control-label {
padding-top: 6px;
}
.controls {
input, textarea {
padding: 6px 10px;
}
input[type="radio"], input[type="checkbox"] {
margin-top: 6px;
}
.add-on {
padding: 6px;
}
}
}
input[type='search'].search-text-input { input[type='search'].search-text-input {
background-image: url("icon-search.png"); background-image: url("icon-search.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 10px; background-position: 10px;
padding-left: 25px; padding-left: 25px;
@include border-radius(4px);
border: 1px solid #ccc;
} }
input[type='text'].danger { input[type='text'].danger {
...@@ -64,7 +13,6 @@ input[type='text'].danger { ...@@ -64,7 +13,6 @@ input[type='text'].danger {
fieldset legend { fieldset legend {
font-size: 16px; font-size: 16px;
margin-bottom: 10px;
} }
.datetime-controls { .datetime-controls {
...@@ -72,3 +20,34 @@ fieldset legend { ...@@ -72,3 +20,34 @@ fieldset legend {
width: 100px; width: 100px;
} }
} }
.form-actions {
padding: 17px 20px 18px;
margin-top: 18px;
margin-bottom: 18px;
background-color: whitesmoke;
border-top: 1px solid #e5e5e5;
padding-left: 17%;
}
label {
&.control-label {
@extend .col-sm-2;
}
&.inline-label {
margin: 0;
}
}
.inline-input-group {
width: 250px;
}
.input-mx-250 {
max-width: 250px;
}
.input-mn-300 {
min-width: 300px;
}
/**
* Issue box:
* Huge block (one per page) for storing title, descripion and other information.
* Used for Issue#show page, MergeRequest#show page etc
*
* CLasses:
* .issue-box - Regular box
*/
.issue-box {
color: #666;
margin:20px 0;
background: #FAFAFA;
border: 1px solid #DDD;
.control-group {
margin-bottom: 0;
}
.title {
font-size: 20px;
font-weight: 500;
line-height: 28px;
margin: 0;
color: #444;
}
.context {
border: none;
background-color: #f5f5f5;
border: none;
border-top: 1px solid #eee;
}
.description {
border-top: 1px solid #eee;
}
.title, .context, .description {
padding: 15px;
.clearfix {
margin: 0;
}
}
}
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
*/ */
.well-list { .well-list {
margin: 0; margin: 0;
padding: 0;
list-style: none; list-style: none;
li { li {
padding: 10px; padding: 10px;
min-height: 20px; min-height: 20px;
......
/** Select2 selectbox style override **/
.select2-container, .select2-container.select2-drop-above {
.select2-choice {
background: #FFF;
border-color: #BBB;
.select2-arrow {
background: #FFF;
}
}
}
.select2-drop-active {
border: 1px solid #BBB;
margin-top: 4px;
.select2-search input {
background: #fafafa;
border-color: #DDD;
}
.select2-results {
max-height: 350px;
.select2-highlighted {
background: $bg_style_color;
}
}
}
select {
&.select2 {
width: 100px;
}
&.select2-sm {
width: 100px;
}
}
@media (min-width: $screen-sm-min) {
select {
&.select2 {
width: 150px;
}
&.select2-sm {
width: 120px;
}
}
}
/* Medium devices (desktops, 992px and up) */
@media (min-width: $screen-md-min) {
select {
&.select2 {
width: 170px;
}
&.select2-sm {
width: 140px;
}
}
}
/* Large devices (large desktops, 1200px and up) */
@media (min-width: $screen-lg-min) {
select {
&.select2 {
width: 200px;
}
&.select2-sm {
width: 150px;
}
}
}
/** Branch/tag selector **/
.project-refs-form .select2-container {
margin-right: 10px;
}
...@@ -2,11 +2,6 @@ ...@@ -2,11 +2,6 @@
* Headers * Headers
* *
*/ */
h1, h2, h3, h4, h5, h6 {
font-weight: 500;
line-height: 1.1;
}
h1.page-title { h1.page-title {
@include page-title; @include page-title;
font-size: 28px; font-size: 28px;
...@@ -99,6 +94,7 @@ a:focus { ...@@ -99,6 +94,7 @@ a:focus {
background: #f5f5f5; background: #f5f5f5;
} }
ul { ul {
padding: 0;
margin: 0 0 9px 25px !important; margin: 0 0 9px 25px !important;
} }
} }
......
/** /**
* =================================== * UI box:
* Contain UI block elements: * Block element for separating information on page.
* Used for storing issues lists, grouped data.
* You can have multiple ui boxes on one page
*
* Classes:
* .ui-box - for any block & widgets * .ui-box - for any block & widgets
* =================================== * .ui-box.ui-box-small - same but with smaller title
*/ * .ui-box.ui-box-danger - with red title
*
/** * Ex. 1: List
* UI Block * .ui-box
* .title
* # title here
* %ul
* # content here
*
* Ex. 2: Block data
* .ui-box
* .title
* # title here
* .body
* # content here
* *
*/ */
.ui-box { .ui-box {
background: #FFF; background: #FFF;
margin-bottom: 20px; margin-bottom: 20px;
border: 1px solid #DDD; border: 1px solid #DDD;
word-wrap: break-word; word-wrap: break-word;
&.small-box { img {
margin-bottom: 10px; max-width: 100%;
.title {
font-size: 13px;
line-height: 30px;
a {
color: #666;
&:hover {
text-decoration: underline;
}
}
}
} }
&.ui-box-show {
color: #666;
margin:20px 0;
background: #FAFAFA;
.control-group {
margin-bottom: 0;
}
}
&.ui-box-danger {
background: #f7f7f7;
border: none;
.title {
background: #D65;
color: #fff;
text-shadow: 0 1px 1px #900;
}
}
img { max-width: 100%; }
pre { pre {
code { code {
background: none !important; background: none !important;
} }
} }
.ui-box-head,
.ui-box-body,
.ui-box-bottom {
padding: 15px;
.clearfix {
margin: 0;
}
}
.ui-box-head {
.box-title {
font-size: 20px;
font-weight: 500;
line-height: 28px;
margin: 0;
color: #444;
}
h3 {
margin: 0;
}
}
.ui-box-body {
border: none;
background-color: #f5f5f5;
border: none;
border-top: 1px solid #eee;
}
.ui-box-bottom {
border-top: 1px solid #eee;
}
ul { ul {
margin: 0; margin: 0;
padding: 0;
} }
.title { .title {
...@@ -146,6 +94,10 @@ ...@@ -146,6 +94,10 @@
} }
} }
.body {
padding: 10px;
}
&.padded { &.padded {
h5, .title { h5, .title {
margin: -20px; margin: -20px;
...@@ -177,13 +129,45 @@ ...@@ -177,13 +129,45 @@
} }
} }
/*
* Small box
*/
.ui-box.ui-box-small {
margin-bottom: 10px;
.title {
font-size: 13px;
line-height: 30px;
a {
color: #666;
&:hover {
text-decoration: underline;
}
}
}
}
/*
* Danger box
*/
.ui-box.ui-box-danger {
background: #f7f7f7;
border: none;
.title {
background: #D65;
color: #fff;
text-shadow: none;
font-weight: 500;
}
}
/*
* Block under tw-bootstrap tabs
*/
.tab-pane { .tab-pane {
.ui-box { .ui-box {
margin: 3px 3px 25px 3px; margin: 3px 3px 25px 3px;
} }
} }
.light-well {
background: #f9f9f9;
padding: 15px;
}
/** Override bootstrap variables **/
$baseFontSize: 13px !default;
$baseLineHeight: 18px !default;
/**
* BOOTSTRAP
*/
@import "bootstrap/variables";
@import "bootstrap/mixins";
@import "bootstrap/reset";
@import "bootstrap/scaffolding";
@import "bootstrap/grid";
@import "bootstrap/layouts";
@import "bootstrap/type";
@import "bootstrap/code";
@import "bootstrap/forms";
@import "bootstrap/tables";
@import "bootstrap/sprites";
@import "bootstrap/dropdowns";
@import "bootstrap/wells";
@import "bootstrap/component-animations";
@import "bootstrap/close";
@import "bootstrap/button-groups";
@import "bootstrap/alerts";
@import "bootstrap/navs";
@import "bootstrap/navbar";
@import "bootstrap/breadcrumbs";
@import "bootstrap/pagination";
@import "bootstrap/pager";
@import "bootstrap/modals";
@import "bootstrap/tooltip";
@import "bootstrap/popovers";
@import "bootstrap/thumbnails";
@import "bootstrap/media";
@import "bootstrap/labels-badges";
@import "bootstrap/progress-bars";
@import "bootstrap/accordion";
@import "bootstrap/carousel";
@import "bootstrap/hero-unit";
@import "bootstrap/utilities";
@import "bootstrap/responsive-utilities";
@import "bootstrap/responsive-1200px-min";
/**
* Font icons
*
*/
@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/avatar.scss";
@import "gitlab_bootstrap/nav.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/lists.scss";
@import "gitlab_bootstrap/forms.scss";
/** COLORS **/
.cgray { color: gray }
.clgray { color: #BBB }
.cred { color: #D12F19 }
.cgreen { color: #4a2 }
.cblue { color: #29A }
.cblack { color: #111 }
.cdark { color: #444 }
.camber { color: #ffc000 }
.cwhite { color: #fff!important }
.bgred { background: #F2DEDE!important }
/** COMMON CLASSES **/
.left { float:left }
.prepend-top-10 { margin-top:10px }
.prepend-top-20 { margin-top:20px }
.prepend-left-10 { margin-left:10px }
.prepend-left-20 { margin-left:20px }
.append-right-10 { margin-right:10px }
.append-right-20 { margin-right:20px }
.append-bottom-10 { margin-bottom:10px }
.append-bottom-20 { margin-bottom:20px }
.inline { display: inline-block }
.padded { padding:20px }
.ipadded { padding:20px!important }
.lborder { border-left:1px solid #eee }
.underlined_link { text-decoration: underline; }
.hint { font-style: italic; color: #999; }
.light { color: #888 }
.tiny { font-weight: normal }
.vtop { vertical-align: top !important; }
/** ALERT MESSAGES **/
.alert.alert-disabled {
background: #EEE;
color: #777;
border-color: #DDD;
}
/** HELPERS **/
.nothing_here_message {
text-align: center;
padding: 20px;
color: #666;
font-weight: normal;
font-size: 16px;
line-height: 36px;
}
.slead {
color: #666;
font-size: 14px;
margin-bottom: 12px;
font-weight: normal;
line-height: 24px;
}
.tab-content {
overflow: visible;
}
@media (max-width: 1200px) {
.only-wide {
display: none;
}
}
.pagination ul > li > a, .pagination ul > li >span {
@include linear-gradient(#f1f1f1, #e1e1e1);
color: #333;
text-shadow: 0 1px 1px #FFF;
}
pre.well-pre {
border: 1px solid #EEE;
background: #f9f9f9;
border-radius: 0;
color: #555;
}
.input-append .btn.active, .input-prepend .btn.active {
background: #CCC;
border-color: #BBB;
text-shadow: 0 1px 1px #fff;
font-weight: bold;
@include box-shadow(inset 0 2px 4px rgba(0,0,0,.15));
}
.label {
padding: 2px 4px;
font-size: 12px;
font-style: normal;
font-weight: normal;
&.label-gray {
background-color: #eee;
color: #999;
text-shadow: none;
}
}
/** Big Labels **/
.state-label {
font-size: 14px;
padding: 5px 15px;
text-align: center;
float: right;
position: relative;
top: -5px;
@include border-radius(4px);
text-shadow: none;
&.state-label-green {
background: #4A4;
color: #FFF;
}
&.state-label-red {
background: #DA4E49;
color: #FFF;
}
}
.dropdown-menu > li > a {
text-shadow: none;
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
background: #29b;
}
/**
* nav-pills
*
*/
.nav-pills {
.active a {
background: $primary_color;
}
> li > a {
@include border-radius(0);
}
&.nav-stacked {
> li > a {
border-left: 4px solid #EEE;
padding: 12px;
color: #777;
}
> .active > a {
border-color: $primary_color;
background: none;
color: #333;
font-weight: bolder;
}
&.nav-stacked-menu {
li > a {
padding: 16px;
}
}
}
&.nav-pills-small {
> li > a {
padding: 8px 12px;
font-size: 12px;
}
}
}
.nav-pills > .active > a > i[class^="icon-"] { background: inherit; }
/**
* nav-tabs
*
*/
.nav-tabs > li > a, .nav-pills > li > a { color: $style_color; }
.nav.nav-tabs {
li {
> a {
padding: 8px 20px;
margin-right: 7px;
line-height: 20px;
border-color: #EEE;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i[class^="icon-"] {
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color: #333;
font-weight: bold;
}
}
}
&.nav-small-tabs > li > a { padding: 6px 9px; }
}
/**
* fix to keep tooltips position in top navigation bar
*
*/
.navbar .nav > li {
position: relative;
white-space: nowrap;
}
/*
* Twitter bootstrap with GitLab customizations/additions
*
* Some unused bootstrap compontents like panels are not included.
* Other components like tabs are modified to GitLab style.
*
*/
$font-size-base: 13px !default;
$nav-pills-active-link-hover-bg: $bg_style_color;
$pagination-active-bg: $bg_style_color;
// Core variables and mixins
@import "bootstrap/variables";
@import "bootstrap/mixins";
// Reset
@import "bootstrap/normalize";
@import "bootstrap/print";
// Core CSS
@import "bootstrap/scaffolding";
@import "bootstrap/type";
@import "bootstrap/code";
@import "bootstrap/grid";
@import "bootstrap/tables";
@import "bootstrap/forms";
// Components
@import "bootstrap/component-animations";
@import "bootstrap/dropdowns";
@import "bootstrap/button-groups";
@import "bootstrap/input-groups";
@import "bootstrap/navs";
@import "bootstrap/navbar";
@import "bootstrap/breadcrumbs";
@import "bootstrap/pagination";
@import "bootstrap/pager";
@import "bootstrap/labels";
@import "bootstrap/badges";
@import "bootstrap/jumbotron";
@import "bootstrap/thumbnails";
@import "bootstrap/alerts";
@import "bootstrap/progress-bars";
@import "bootstrap/list-group";
@import "bootstrap/wells";
@import "bootstrap/close";
// Components w/ JavaScript
@import "bootstrap/modals";
@import "bootstrap/tooltip";
@import "bootstrap/popovers";
@import "bootstrap/carousel";
// Utility classes
.clearfix {
@include clearfix();
}
.center-block {
@include center-block();
}
.pull-right {
float: right !important;
}
.pull-left {
float: left !important;
}
.hide {
display: none;
}
.show {
display: block !important;
}
.invisible {
visibility: hidden;
}
.text-hide {
@include text-hide();
}
.hidden {
display: none !important;
visibility: hidden !important;
}
.affix {
position: fixed;
}
@import "bootstrap/responsive-utilities";
// Labels
.label {
padding: 2px 4px;
font-size: 12px;
font-style: normal;
font-weight: normal;
display: inline-block;
&.label-gray {
background-color: #eee;
color: #999;
text-shadow: none;
}
&.label-inverse {
background-color: #333333;
}
}
// Nav tabs
.nav.nav-tabs {
li {
> a {
padding: 8px 20px;
margin-right: 7px;
line-height: 20px;
border-color: #EEE;
color: #888;
border-bottom: 1px solid #ddd;
.badge {
background-color: #eee;
color: #888;
text-shadow: 0 1px 1px #fff;
}
i[class^="icon-"] {
line-height: 14px;
}
}
&.active {
> a {
border-color: #CCC;
border-bottom: 1px solid #fff;
color: #333;
font-weight: bold;
}
}
}
&.nav-small-tabs > li > a {
padding: 6px 9px;
}
}
.nav-tabs > li > a,
.nav-pills > li > a {
color: #666;
}
.nav-small > li > a {
padding: 3px 5px;
font-size: 12px;
}
/*
* Callouts from Bootstrap3 docs
*
* Not quite alerts, but custom and helpful notes for folks reading the docs.
* Requires a base and modifier class.
*/
/* Common styles for all types */
.bs-callout {
margin: 20px 0;
padding: 20px;
border-left: 3px solid #eee;
color: #666;
background: #f9f9f9;
}
.bs-callout h4 {
margin-top: 0;
margin-bottom: 5px;
}
.bs-callout p:last-child {
margin-bottom: 0;
}
/* Variations */
.bs-callout-danger {
background-color: #fdf7f7;
border-color: #eed3d7;
color: #b94a48;
}
.bs-callout-warning {
background-color: #faf8f0;
border-color: #faebcc;
color: #8a6d3b;
}
.bs-callout-info {
background-color: #f4f8fa;
border-color: #bce8f1;
color: #34789a;
}
.bs-callout-success {
background-color: #dff0d8;
border-color: #5cA64d;
color: #3c763d;
}
// Breadcrumb
ul.breadcrumb {
background: white;
border: none;
li {
display: inline;
text-shadow: 0 1px 0 white
}
a {
font-size: 16px;
}
}
/**
* fix to keep tooltips position in top navigation bar
*
*/
.navbar .nav > li {
position: relative;
white-space: nowrap;
}
html {
overflow-y: scroll;
}
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin-bottom: 20px;
}
.container {
padding-top: 0;
z-index: 5;
}
.container .content {
margin: 0 0;
}
...@@ -79,11 +79,15 @@ ...@@ -79,11 +79,15 @@
color: $style_color; color: $style_color;
text-shadow: 0 1px 1px #FFF; text-shadow: 0 1px 1px #FFF;
font-size: 16px; font-size: 16px;
line-height: 40px; line-height: 44px;
font-weight: normal; font-weight: normal;
} }
@mixin md-typography { @mixin md-typography {
img {
max-width: 100%;
}
*:first-child { *:first-child {
margin-top: 0; margin-top: 0;
} }
...@@ -136,7 +140,7 @@ ...@@ -136,7 +140,7 @@
} }
@mixin page-title { @mixin page-title {
color: $style_color; color: #333;
font-size: 20px; font-size: 20px;
line-height: 1.5; line-height: 1.5;
margin-top: 0px; margin-top: 0px;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
$primary_color: #2FA0BB; $primary_color: #2FA0BB;
$link_color: #3A89A3; $link_color: #3A89A3;
$style_color: #474D57; $style_color: #474D57;
$bg_style_color: #2299BB;
$hover: #D9EDF7; $hover: #D9EDF7;
/** /**
......
...@@ -80,7 +80,7 @@ ...@@ -80,7 +80,7 @@
border-right: 1px solid #ccc; border-right: 1px solid #ccc;
text-align: right; text-align: right;
min-width: 35px; min-width: 35px;
max-width: 35px; max-width: 50px;
width: 35px; width: 35px;
@include user-select(none); @include user-select(none);
a { a {
...@@ -399,8 +399,8 @@ ...@@ -399,8 +399,8 @@
.commits-compare-switch{ .commits-compare-switch{
background: url("switch_icon.png") no-repeat center center; background: url("switch_icon.png") no-repeat center center;
width: 22px; width: 32px;
height: 22px; height: 32px;
text-indent: -9999px; text-indent: -9999px;
float: left; float: left;
margin-right: 9px; margin-right: 9px;
...@@ -481,6 +481,10 @@ li.commit { ...@@ -481,6 +481,10 @@ li.commit {
font-family: $monospace_font; font-family: $monospace_font;
} }
.str-truncated {
max-width: 70%;
}
.commit-row-message { .commit-row-message {
color: #333; color: #333;
font-weight: 500; font-weight: 500;
......
.dashboard { .dashboard {
@extend .row;
.activities {
}
.side { .side {
@extend .pull-right;
.ui-box { .ui-box {
margin: 0px; margin: 0px;
box-shadow: none; box-shadow: none;
...@@ -20,7 +14,7 @@ ...@@ -20,7 +14,7 @@
.search-text-input { .search-text-input {
float:left; float:left;
@extend .span2; @extend .col-md-2;
} }
.btn { .btn {
margin-left: 5px; margin-left: 5px;
...@@ -32,14 +26,15 @@ ...@@ -32,14 +26,15 @@
.dash-filter { .dash-filter {
margin: 7px 0; margin: 7px 0;
padding: 4px 6px; padding: 4px 6px;
width: 202px; width: 220px;
float: left; float: left;
height: inherit;
} }
} }
@media (max-width: 1200px) { @media (max-width: 1200px) {
.dashboard .dash-filter { .dashboard .dash-filter {
width: 132px; width: 150px;
} }
} }
...@@ -66,41 +61,37 @@ ...@@ -66,41 +61,37 @@
} }
.project-row, .group-row { .project-row, .group-row {
padding: 10px 15px !important; padding: 10px 12px !important;
font-size: 14px;
line-height: 24px;
.namespace-name { a {
color: #666; display: block;
font-weight: bold;
} }
.project-name, .group-name { .project-name, .group-name {
font-size: 15px; font-weight: 500;
} }
.arrow { .arrow {
float: right; float: right;
padding: 10px 5px; padding: 0px 5px;
margin: 0; margin: 0;
font-size: 20px; font-size: 20px;
color: #666; color: #666;
} }
.last-activity { .last-activity {
float: right;
font-size: 12px;
color: #AAA; color: #AAA;
display: block; display: block;
margin-top: 5px;
.date { .date {
color: #777; color: #777;
} }
} }
} }
.group-row {
.arrow {
padding: 2px 5px;
}
}
.project-access-icon { .project-access-icon {
margin-left: 10px; margin-left: 10px;
float: left; float: left;
...@@ -111,10 +102,17 @@ ...@@ -111,10 +102,17 @@
padding: 8px 12px; padding: 8px 12px;
border-radius: 50px; border-radius: 50px;
background: #f5f5f5; background: #f5f5f5;
width: 16px;
text-align: center; text-align: center;
i { i {
color: #BBB; color: #BBB;
} }
} }
.dash-project-access-icon {
float: left;
margin-right: 3px;
color: #999;
margin-bottom: 10px;
width: 16px;
}
...@@ -34,15 +34,4 @@ ...@@ -34,15 +34,4 @@
margin: 5px 8px 0 8px; margin: 5px 8px 0 8px;
} }
} }
.commit_message-group {
margin-top: 20px;
label {
font-size: 16px;
line-height: 20px;
}
textarea {
@extend .span8;
}
}
} }
...@@ -75,6 +75,7 @@ ...@@ -75,6 +75,7 @@
margin-top: 4px; margin-top: 4px;
margin-left: 0px; margin-left: 0px;
max-width: 200px; max-width: 200px;
float: none;
} }
p:last-child { p:last-child {
...@@ -147,7 +148,7 @@ ...@@ -147,7 +148,7 @@
float: left; float: left;
padding: 9px 6px; padding: 9px 6px;
font-size: 18px; font-size: 18px;
width: 26px; width: 40px;
@include border-radius(3px); @include border-radius(3px);
} }
......
...@@ -4,17 +4,24 @@ ...@@ -4,17 +4,24 @@
*/ */
header { header {
&.navbar-gitlab { &.navbar-gitlab {
margin-bottom: 0;
min-height: 40px;
.navbar-inner { .navbar-inner {
height: 40px;
padding: 3px;
background: #F1F1F1; background: #F1F1F1;
border-bottom: 1px solid #DDD;
filter: none; filter: none;
.nav > li > a { .nav > li > a {
color: $style_color; color: $style_color;
text-shadow: 0 1px 0 #fff; text-shadow: 0 1px 0 #fff;
font-size: 14px; font-size: 14px;
padding: 10px; line-height: 32px;
padding: 6px 10px;
&:hover {
background: none;
}
} }
/** NAV block with links and profile **/ /** NAV block with links and profile **/
...@@ -35,9 +42,6 @@ header { ...@@ -35,9 +42,6 @@ header {
.app_logo { .app_logo {
float: left; float: left;
margin-right: 9px; margin-right: 9px;
position: relative;
top: -3px;
padding-top: 3px;
a { a {
float: left; float: left;
...@@ -49,7 +53,7 @@ header { ...@@ -49,7 +53,7 @@ header {
background: url('logo-black.png') no-repeat center center; background: url('logo-black.png') no-repeat center center;
background-size: 32px; background-size: 32px;
float: left; float: left;
height: 40px; height: 46px;
width: 40px; width: 40px;
@include header-font; @include header-font;
text-indent: -9999px; text-indent: -9999px;
...@@ -75,7 +79,7 @@ header { ...@@ -75,7 +79,7 @@ header {
.profile-pic { .profile-pic {
position: relative; position: relative;
top: -4px; top: -1px;
img { img {
width: 26px; width: 26px;
height: 26px; height: 26px;
...@@ -91,21 +95,25 @@ header { ...@@ -91,21 +95,25 @@ header {
.search { .search {
margin-right: 10px; margin-right: 10px;
margin-left: 10px; margin-left: 10px;
margin-top: 8px;
form {
margin: 0;
padding: 0;
}
.search-input { .search-input {
@extend .span3;
background-image: url("icon-search.png"); background-image: url("icon-search.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: 10px; background-position: 10px;
height: inherit;
padding: 4px 6px;
padding-left: 25px; padding-left: 25px;
font-size: 13px; font-size: 13px;
@include border-radius(3px); @include border-radius(3px);
border: 1px solid #c6c6c6; border: 1px solid #c6c6c6;
box-shadow: none; box-shadow: none;
@include transition(all 0.15s ease-in 0s); @include transition(all 0.15s ease-in 0s);
&:focus {
@extend .span4;
}
} }
} }
...@@ -181,12 +189,26 @@ header { ...@@ -181,12 +189,26 @@ header {
.separator { .separator {
float: left; float: left;
height: 46px; height: 46px;
width: 1px; width: 2px;
background: white; background: white;
border-left: 1px solid #DDD; border-left: 1px solid #DDD;
margin-top: -3px;
margin-left: 10px; margin-left: 10px;
margin-right: 10px; margin-right: 10px;
} }
} }
.search .search-input {
width: 300px;
&:focus {
width: 400px;
}
}
@media (max-width: 1200px) {
.search .search-input {
width: 200px;
&:focus {
width: 300px;
}
}
}
...@@ -77,8 +77,8 @@ input.check_all_issues { ...@@ -77,8 +77,8 @@ input.check_all_issues {
@media (min-width: 800px) { .issues_filters select { width: 160px; } } @media (min-width: 800px) { .issues_filters select { width: 160px; } }
@media (min-width: 1200px) { .issues_filters select { width: 220px; } } @media (min-width: 1200px) { .issues_filters select { width: 220px; } }
@media (min-width: 800px) { .issues_bulk_update .chosen-container { min-width: 120px; } } @media (min-width: 800px) { .issues_bulk_update .select2-container { min-width: 120px; } }
@media (min-width: 1200px) { .issues_bulk_update .chosen-container { min-width: 160px; } } @media (min-width: 1200px) { .issues_bulk_update .select2-container { min-width: 160px; } }
.issues-holder { .issues-holder {
.issues_filters { .issues_filters {
...@@ -105,7 +105,7 @@ input.check_all_issues { ...@@ -105,7 +105,7 @@ input.check_all_issues {
} }
.issues_bulk_update { .issues_bulk_update {
.chosen-container { .select2-container {
text-shadow: none; text-shadow: none;
} }
} }
...@@ -119,3 +119,11 @@ input.check_all_issues { ...@@ -119,3 +119,11 @@ input.check_all_issues {
background-color: #f4f4f4; background-color: #f4f4f4;
} }
} }
.issue-show-labels .label {
padding: 6px 10px;
}
form.edit-issue {
margin: 0;
}
/* Login Page */ /* Login Page */
body.login-page{ .login-page {
.container > .content { h1 {
padding-top: 20px; font-size: 3em;
font-weight: 200;
} }
}
.login-box{
width: 304px;
position: relative;
@include border-radius(5px);
margin: auto;
padding: 20px;
background: white;
}
.login-box .login-logo{
margin: 10px 0 30px 0;
display: block;
}
.login-box input.text{background-color: #f1f1f1; font-size: 16px; @include border-radius(0); padding: 14px 10px; width: 280px}
.login-box input.text.top{
@include border-radius(5px 5px 0 0);
margin-bottom: 0px;
}
.login-box input.text.bottom{ .login-box{
@include border-radius(0 0 5px 5px); width: 304px;
border-top: 0; position: relative;
margin-bottom: 20px; @include border-radius(5px);
} margin: auto;
padding: 20px;
.login-box input.text.middle{ background: white;
border-top: 0; }
margin-bottom:0px;
}
.login-box a.forgot{float: right; padding-top: 6px} .login-logo{
margin: 10px 0 30px 0;
display: block;
}
.remember_me { .form-control {
text-align: left; background-color: #f1f1f1;
font-size: 16px;
padding: 14px 10px;
width: 280px;
height: auto;
&.top {
@include border-radius(5px 5px 0 0);
margin-bottom: 0px;
}
&.bottom {
@include border-radius(0 0 5px 5px);
border-top: 0;
margin-bottom: 20px;
}
&.middle {
border-top: 0;
margin-bottom:0px;
@include border-radius(0);
}
}
input { .login-box a.forgot {
margin: 2px; float: right;
padding-top: 6px
} }
}
.devise-errors { .devise-errors {
h2 { h2 {
font-size: 14px; font-size: 14px;
color: #a00; color: #a00;
}
} }
} }
...@@ -4,10 +4,6 @@ ...@@ -4,10 +4,6 @@
* *
*/ */
.automerge_widget { .automerge_widget {
&.can_be_merged {
background: #DFF0D8;
}
form { form {
margin-bottom: 0; margin-bottom: 0;
.clearfix { .clearfix {
...@@ -15,32 +11,12 @@ ...@@ -15,32 +11,12 @@
} }
} }
.accept_group { .accept-group {
float: left;
border: 1px solid #ADA;
padding: 2px;
@include border-radius(5px);
background: #CEB;
.accept_merge_request {
font-size: 13px;
float: left;
}
.remove_branch_holder {
margin-left: 20px;
margin-right: 10px;
float: left;
}
label { label {
color: #444; margin: 5px;
text-align: left margin-left: 20px;
} }
} }
.how_to_merge_link {
@extend .primary;
}
} }
.merge-request .nav-tabs{ .merge-request .nav-tabs{
...@@ -53,11 +29,6 @@ ...@@ -53,11 +29,6 @@
} }
} }
.merge-in-progress {
@extend .padded;
@extend .append-bottom-10;
}
.mr_source_commit, .mr_source_commit,
.mr_target_commit { .mr_target_commit {
.commit { .commit {
...@@ -111,12 +82,8 @@ ...@@ -111,12 +82,8 @@
.merge-request-angle { .merge-request-angle {
text-align: center; text-align: center;
margin: 0 auto; margin: 0 auto;
background: #eee; font-size: 2em;
border-radius: 100px; line-height: 1.1;
width: 60px;
line-height: 60px;
color: #777;
text-shadow: 0 1px 2px #FFF;
} }
.merge-request-form-info { .merge-request-form-info {
...@@ -128,8 +95,7 @@ ...@@ -128,8 +95,7 @@
font-weight: normal !important; font-weight: normal !important;
} }
.chosen-container .chosen-single { .select2-container .select2-single {
padding: 2px 0 2px 10px;
span { span {
font-weight: bold; font-weight: bold;
color: #555; color: #555;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
border-bottom: 1px solid #E1E1E1; border-bottom: 1px solid #E1E1E1;
ul { ul {
padding: 0;
margin: auto; margin: auto;
height: 40px; height: 40px;
overflow: hidden; overflow: hidden;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Notes * Notes
*/ */
@-webkit-keyframes target-note { @-webkit-keyframes targe3-note {
from { background:#fffff0; } from { background:#fffff0; }
50% { background:#ffffd3; } 50% { background:#ffffd3; }
to { background:#fffff0; } to { background:#fffff0; }
...@@ -119,9 +119,9 @@ ul.notes { ...@@ -119,9 +119,9 @@ ul.notes {
} }
.file .notes_holder { .file .notes_holder {
font-family: $sansFontFamily;
font-size: 13px; font-size: 13px;
line-height: 18px; line-height: 18px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
td { td {
border: 1px solid #ddd; border: 1px solid #ddd;
...@@ -138,7 +138,7 @@ ul.notes { ...@@ -138,7 +138,7 @@ ul.notes {
border-left: 1px solid #ddd !important; border-left: 1px solid #ddd !important;
} }
&.notes_content { &.notes_content {
background-color: $white; background-color: #fff;
border-width: 1px 0; border-width: 1px 0;
padding-top: 0; padding-top: 0;
...@@ -257,12 +257,12 @@ ul.notes { ...@@ -257,12 +257,12 @@ ul.notes {
.file, .file,
.discussion { .discussion {
.new_note { .new_note {
margin: 8px 5px 8px 0; margin: 0;
border: none;
} }
} }
.new_note { .new_note {
display: none; display: none;
.buttons { .buttons {
float: left; float: left;
margin-top: 8px; margin-top: 8px;
...@@ -303,7 +303,7 @@ ul.notes { ...@@ -303,7 +303,7 @@ ul.notes {
} }
.note-image-attach { .note-image-attach {
@extend .span4; @extend .col-md-4;
@extend .thumbnail; @extend .thumbnail;
margin-left: 45px; margin-left: 45px;
} }
......
.update-notifications { .update-notifications {
margin-bottom: 0; .radio-inline {
label { margin-right: 9%;
margin-bottom: 0;
} }
} }
...@@ -17,7 +16,7 @@ ...@@ -17,7 +16,7 @@
legend { legend {
border: none; border: none;
margin: 0; margin-bottom: 10px;
} }
} }
} }
...@@ -47,3 +46,62 @@ ...@@ -47,3 +46,62 @@
margin: 10px 0; margin: 10px 0;
} }
} }
.user-show-username {
font-weight: 200;
color: #666;
}
/*
* Appearance settings
*
*/
.themes_opts {
label {
margin-right: 20px;
text-align: center;
.prev {
@extend .thumbnail;
height: 30px;
width: 175px;
margin-bottom: 10px;
&.classic {
background: #31363e;
}
&.default {
background: #f1f1f1;
}
&.modern {
background: #345;
}
&.gray {
background: #373737;
}
&.violet {
background: #547;
}
}
}
}
.code_highlight_opts {
margin-top: 10px;
label {
margin-right: 20px;
text-align: center;
.prev {
@extend .thumbnail;
height: 151px;
width: 220px;
margin-bottom: 10px;
}
}
}
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
.project-home-panel { .project-home-panel {
border-bottom: 1px solid #DDD; border-bottom: 1px solid #DDD;
padding-bottom: 25px; padding-bottom: 15px;
margin-bottom: 30px; margin-bottom: 30px;
&.empty-project { &.empty-project {
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
.project-home-title { .project-home-title {
font-size: 18px; font-size: 18px;
color: #777; color: #444;
margin: 0; margin: 0;
line-height: 32px; line-height: 32px;
} }
...@@ -40,25 +40,30 @@ ...@@ -40,25 +40,30 @@
.project-home-desc { .project-home-desc {
float: left; float: left;
color: #999; color: #777;
margin-bottom: 10px;
} }
.project-home-links { .project-home-links {
float: right; float: right;
a { a {
margin-left: 10px; margin-left: 10px;
font-weight: 500;
} }
} }
} }
.visibility-level-label { .visibility-level-label {
font-size: 14px; font-size: 17px;
background: #f1f1f1; background: #f1f1f1;
padding: 8px 10px;
border-radius: 4px; border-radius: 4px;
margin-left: 10px;
color: #888; color: #888;
position: absolute;
margin-left: -55px;
text-shadow: 0 1px 1px #FFF; text-shadow: 0 1px 1px #FFF;
width: 40px;
text-align: center;
padding: 6px;
i { i {
color: inherit; color: inherit;
...@@ -67,76 +72,53 @@ ...@@ -67,76 +72,53 @@
} }
.git-clone-holder { .git-clone-holder {
float: right; .project-home-dropdown + & {
border: 1px solid #E1E1E1; margin-right: 45px;
@include border-radius(4px); }
input[type="text"], .btn,
.btn { .form-control {
border: none; border: 1px solid #E1E1E1;
@include border-radius(0px);
border-left: 1px solid #E1E1E1;
box-shadow: none; box-shadow: none;
padding: 6px 10px; padding: 6px 9px;
} }
.btn { .btn {
float: left;
background: none; background: none;
color: #29b; color: #29b;
&:first-child {
@include border-radius-left(4px);
border-left: 0px;
}
&.active { &.active {
color: #333; color: #333;
font-weight: bold; font-weight: bold;
} }
} }
input[type="text"] { .form-control {
cursor: auto; cursor: auto;
@extend .monospace; @extend .monospace;
background: #FAFAFA; background: #FAFAFA;
width: 100%;
} }
} }
.project-visibility-level-holder { .project-visibility-level-holder {
.controls { .radio {
padding-bottom: 9px; margin-bottom: 10px;
}
.controls { i {
input { margin: 0 3px;
float: left; font-size: 20px;
} }
.descr {
display: block;
margin-left: 1.5em;
&.restricted {
color: #888;
}
label { .option-title {
float: none; font-weight: bold;
padding: 0;
margin: 0;
text-align: left;
}
}
.info {
display: block;
margin-top: 5px;
}
strong {
display: inline-block; display: inline-block;
width: 4em;
} }
}
i { .option-descr {
color: inherit; margin-left: 24px;
color: #666;
}
} }
} }
...@@ -218,11 +200,26 @@ ul.nav.nav-projects-tabs { ...@@ -218,11 +200,26 @@ ul.nav.nav-projects-tabs {
.project-side { .project-side {
.btn-block { .btn-block {
background-image: none; background-image: none;
background-color: #F1f1f1; .btn,
border-color: #EEE; &.btn,
&:hover { &.btn-group ul.dropdown-menu {
background-color: #eee; background-color: #F1f1f1;
border-color: #DDD; border-color: #EEE;
&:hover {
background-color: #eee;
border-color: #DDD;
}
}
&.btn-group-justified {
.btn {
width: 100%;
}
.dropdown-toggle {
width: 26px;
}
}
ul {
width: 100%;
} }
} }
.project-fork-icon { .project-fork-icon {
...@@ -233,42 +230,10 @@ ul.nav.nav-projects-tabs { ...@@ -233,42 +230,10 @@ ul.nav.nav-projects-tabs {
} }
} }
.transfer-project .chosen-container { .transfer-project .select2-container {
min-width: 200px; min-width: 200px;
} }
/** Branch/tag selector **/ .deploy-project-label {
.project-refs-form { margin: 1px;
margin: 0;
span {
background:none !important;
position:static !important;
width:auto !important;
height:auto !important;
}
}
.project-refs-select {
width: 120px;
}
.project-refs-form .chosen-container {
position: relative;
top: 0;
left: 0;
margin-right: 10px;
.chosen-single span {
font-weight: bold;
color: #555;
}
&.chosen-container-active {
.chosen-drop {
min-width: 400px;
}
.chosen-results {
max-height: 400px;
}
}
} }
.snippet.file-holder {
.file-title {
.snippet-file-name {
padding: 4px 10px;
position: relative;
top: -4px;
left: -4px;
}
}
}
.my-snippets li:first-child { .my-snippets li:first-child {
h4 { margin-top: 0; } h4 { margin-top: 0; }
padding-top: 0; padding-top: 0;
......
.themes_opts {
padding-left: 20px;
label {
width: 175px;
margin-right: 40px;
.prev {
@extend .thumbnail;
height: 30px;
width: 175px;
margin-bottom: 10px;
&.classic {
background: #31363e;
}
&.default {
background: #f1f1f1;
}
&.modern {
background: #345;
}
&.gray {
background: #373737;
}
&.violet {
background: #547;
}
}
}
}
.code_highlight_opts {
padding-left: 20px;
label {
width: 220px;
margin-right: 40px;
.prev {
@extend .thumbnail;
height: 151px;
width: 220px;
margin-bottom: 10px;
}
}
}
...@@ -24,10 +24,10 @@ ...@@ -24,10 +24,10 @@
th { th {
font-weight: normal; font-weight: normal;
font-size: 15px; font-size: 15px;
border-bottom: 1px solid #CCC; border-bottom: 1px solid #CCC !important;
} }
td { td {
border-color: #F1F1F1; border-color: #F1F1F1 !important;
} }
&:hover { &:hover {
td { td {
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
.tree-item { .tree-item {
.tree-item-file-name { .tree-item-file-name {
max-width: 320px;
vertical-align: middle; vertical-align: middle;
a { a {
&:hover { &:hover {
...@@ -61,6 +62,14 @@ ...@@ -61,6 +62,14 @@
top:-1px; top:-1px;
} }
} }
.tree_commit {
max-width: 320px;
}
.tree_time_ago {
min-width: 135px;
}
} }
.tree_author { .tree_author {
...@@ -111,5 +120,16 @@ ...@@ -111,5 +120,16 @@
.tree-ref-holder { .tree-ref-holder {
float: left; float: left;
margin-top: 5px; margin-top: 8px;
}
.readme-holder {
border-top: 1px dashed #CCC;
padding-top: 10px;
h4 {
font-size: 14px;
margin-bottom: 20px;
color: #777;
}
} }
...@@ -36,3 +36,8 @@ ...@@ -36,3 +36,8 @@
display: inline-block; display: inline-block;
margin: 0 8px; margin: 0 8px;
} }
.votes-holder {
float: right;
width: 250px;
}
.wall-page { .wall-page {
.wall-note-form { .wall-note-form {
@extend .span12; @extend .col-md-12;
margin: 0; margin: 0;
height: 140px; height: 140px;
......
h3.page-title .edit-wiki-header { .title .edit-wiki-header {
width: 780px; width: 780px;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
......
/** Chosen.js selectbox style override **/
.chosen-container {
min-width: 100px;
.chosen-single {
background: #EEE !important;
border: 1px solid #DDD !important;
@include box-shadow(none !important);
@include border-radius(4px !important);
}
.chosen-results li.highlighted {
background: #29b;
}
.chosen-drop {
margin-top: 10px;
border: 1px solid #DDD !important;
@include border-radius(4px !important);
}
.chosen-search input {
border: 1px solid #CCC !important;
@include box-shadow(none !important);
}
}
/** Select2 styling **/
.select2-container .select2-choice {
@include bg-light-gray-gradient;
}
.select2-container .select2-choice div {
border: none;
background: none;
}
.select2-drop {
padding-top: 8px;
}
.select2-no-results, .select2-searching {
padding: 7px;
color: #666;
}
.chosen-container .chosen-single div b {
background-position-y: 0px !important;
}
.chosen-container .chosen-drop .chosen-search input {
background-position-y: -24px !important;
}
class CommitLoadContext < BaseContext
def execute
result = {
commit: nil,
suppress_diff: false,
line_notes: [],
notes_count: 0,
note: nil,
status: :ok
}
commit = project.repository.commit(params[:id])
if commit
line_notes = project.notes.for_commit_id(commit.id).inline
result[:commit] = commit
result[:note] = project.build_commit_note(commit)
result[:line_notes] = line_notes
result[:notes_count] = project.notes.for_commit_id(commit.id).count
result[:branches] = project.repository.branch_names_contains(commit.id)
begin
result[:suppress_diff] = true if commit.diff_suppress? && !params[:force_show_diff]
result[:force_suppress_diff] = commit.diff_force_suppress?
rescue Grit::Git::GitTimeout
result[:suppress_diff] = true
result[:status] = :huge_commit
end
end
result
end
end
class FilterContext
attr_accessor :items, :params
def initialize(items, params)
@items = items
@params = params
end
def execute
apply_filter(items)
end
def apply_filter items
if params[:project_id].present?
items = items.of_projects(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
module Issues
class ListContext < BaseContext
attr_accessor :issues
def execute
@issues = @project.issues
@issues = case params[:state]
when 'all' then @issues
when 'closed' then @issues.closed
else @issues.opened
end
@issues = case params[:scope]
when 'assigned-to-me' then @issues.assigned_to(current_user)
when 'created-by-me' then @issues.authored(current_user)
else @issues
end
@issues = @issues.tagged_with(params[:label_name]) if params[:label_name].present?
@issues = @issues.includes(:author, :project)
# Filter by specific assignee_id (or lack thereof)?
if params[:assignee_id].present?
@issues = @issues.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id]))
end
# Filter by specific milestone_id (or lack thereof)?
if params[:milestone_id].present?
@issues = @issues.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
end
# Sort by :sort param
@issues = sort(@issues, params[:sort])
@issues
end
private
def sort(issues, condition)
case condition
when 'newest' then issues.except(:order).order('created_at DESC')
when 'oldest' then issues.except(:order).order('created_at ASC')
when 'recently_updated' then issues.except(:order).order('updated_at DESC')
when 'last_updated' then issues.except(:order).order('updated_at ASC')
when 'milestone_due_soon' then issues.except(:order).joins(:milestone).order("milestones.due_date ASC")
when 'milestone_due_later' then issues.except(:order).joins(:milestone).order("milestones.due_date DESC")
else issues
end
end
end
end
# Build collection of Merge Requests
# based on filtering passed via params for @project
class MergeRequestsLoadContext < BaseContext
def execute
merge_requests = @project.merge_requests
merge_requests = case params[:state]
when 'all' then merge_requests
when 'closed' then merge_requests.closed
else merge_requests.opened
end
merge_requests = case params[:scope]
when 'assigned-to-me' then merge_requests.assigned_to(current_user)
when 'created-by-me' then merge_requests.authored(current_user)
else merge_requests
end
merge_requests = merge_requests.page(params[:page]).per(20)
merge_requests = merge_requests.includes(:author, :source_project, :target_project).order("created_at desc")
# Filter by specific assignee_id (or lack thereof)?
if params[:assignee_id].present?
merge_requests = merge_requests.where(assignee_id: (params[:assignee_id] == '0' ? nil : params[:assignee_id]))
end
# Filter by specific milestone_id (or lack thereof)?
if params[:milestone_id].present?
merge_requests = merge_requests.where(milestone_id: (params[:milestone_id] == '0' ? nil : params[:milestone_id]))
end
merge_requests
end
end
class SearchContext
attr_accessor :project_ids, :current_user, :params
def initialize(project_ids, user, params)
@project_ids, @current_user, @params = project_ids, user, params.dup
end
def execute
query = params[:search]
query = Shellwords.shellescape(query) if query.present?
return result unless query.present?
visibility_levels = @current_user ? [ Gitlab::VisibilityLevel::INTERNAL, Gitlab::VisibilityLevel::PUBLIC ] : [ Gitlab::VisibilityLevel::PUBLIC ]
result[:projects] = Project.where("projects.id in (?) OR projects.visibility_level in (?)", project_ids, visibility_levels).search(query).limit(20)
# Search inside single project
single_project_search(Project.where(id: project_ids), query)
result
end
def single_project_search(projects, query)
project = projects.first if projects.length == 1
if params[:search_code].present?
result[:blobs] = project.repository.search_files(query, params[:repository_ref]) unless project.empty_repo?
else
result[:merge_requests] = MergeRequest.in_projects(project_ids).search(query).order('updated_at DESC').limit(20)
result[:issues] = Issue.where(project_id: project_ids).search(query).order('updated_at DESC').limit(20)
result[:wiki_pages] = []
end
end
def result
@result ||= {
projects: [],
merge_requests: [],
issues: [],
wiki_pages: [],
blobs: []
}
end
end
class TestHookContext < BaseContext
def execute
hook = project.hooks.find(params[:id])
data = GitPushService.new.sample_data(project, current_user)
hook.execute(data)
end
end
...@@ -19,7 +19,7 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -19,7 +19,7 @@ class Admin::ProjectsController < Admin::ApplicationController
end end
def transfer def transfer
result = ::Projects::TransferContext.new(@project, current_user, project: params).execute(:admin) result = ::Projects::TransferService.new(@project, current_user, project: params).execute(:admin)
if result if result
redirect_to [:admin, @project] redirect_to [:admin, @project]
......
...@@ -47,7 +47,7 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -47,7 +47,7 @@ class Admin::UsersController < Admin::ApplicationController
@user.admin = (admin && admin.to_i > 0) @user.admin = (admin && admin.to_i > 0)
@user.created_by_id = current_user.id @user.created_by_id = current_user.id
@user.generate_password @user.generate_password
@user.confirm! @user.skip_confirmation!
respond_to do |format| respond_to do |format|
if @user.save if @user.save
......
...@@ -161,6 +161,9 @@ class ApplicationController < ActionController::Base ...@@ -161,6 +161,9 @@ class ApplicationController < ActionController::Base
def default_headers def default_headers
headers['X-Frame-Options'] = 'DENY' headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block' headers['X-XSS-Protection'] = '1; mode=block'
headers['X-UA-Compatible'] = 'IE=edge'
headers['X-Content-Type-Options'] = 'nosniff'
headers['Strict-Transport-Security'] = 'max-age=31536000' if Gitlab.config.gitlab.https
end end
def add_gon_variables def add_gon_variables
...@@ -223,7 +226,7 @@ class ApplicationController < ActionController::Base ...@@ -223,7 +226,7 @@ class ApplicationController < ActionController::Base
end end
def configure_permitted_parameters def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password) } devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :login, :remember_me) }
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :name, :password, :password_confirmation) } devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :name, :password, :password_confirmation) }
end end
end end
...@@ -3,6 +3,8 @@ class DashboardController < ApplicationController ...@@ -3,6 +3,8 @@ class DashboardController < ApplicationController
before_filter :load_projects, except: [:projects] before_filter :load_projects, except: [:projects]
before_filter :event_filter, only: :show before_filter :event_filter, only: :show
before_filter :default_filter, only: [:issues, :merge_requests]
def show def show
# Fetch only 30 projects. # Fetch only 30 projects.
...@@ -41,26 +43,22 @@ class DashboardController < ApplicationController ...@@ -41,26 +43,22 @@ class DashboardController < ApplicationController
@projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present? @projects = @projects.where(namespace_id: Group.find_by_name(params[:group])) if params[:group].present?
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
@projects = @projects.includes(:namespace).sorted_by_activity @projects = @projects.includes(:namespace)
@projects = @projects.tagged_with(params[:label]) if params[:label].present?
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]).per(30)
@labels = current_user.authorized_projects.tags_on(:labels) @labels = current_user.authorized_projects.tags_on(:labels)
@groups = current_user.authorized_groups @groups = current_user.authorized_groups
@projects = @projects.tagged_with(params[:label]) if params[:label].present?
@projects = @projects.page(params[:page]).per(30)
end end
# Get authored or assigned open merge requests
def merge_requests def merge_requests
@merge_requests = current_user.cared_merge_requests @merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = FilterContext.new(@merge_requests, params).execute
@merge_requests = @merge_requests.recent.page(params[:page]).per(20) @merge_requests = @merge_requests.recent.page(params[:page]).per(20)
end end
# Get only assigned issues
def issues def issues
@issues = current_user.assigned_issues @issues = FilteringService.new.execute(Issue, current_user, params)
@issues = FilterContext.new(@issues, params).execute
@issues = @issues.recent.page(params[:page]).per(20) @issues = @issues.recent.page(params[:page]).per(20)
@issues = @issues.includes(:author, :project) @issues = @issues.includes(:author, :project)
...@@ -75,4 +73,9 @@ class DashboardController < ApplicationController ...@@ -75,4 +73,9 @@ class DashboardController < ApplicationController
def load_projects def load_projects
@projects = current_user.authorized_projects.sorted_by_activity.non_archived @projects = current_user.authorized_projects.sorted_by_activity.non_archived
end end
def default_filter
params[:scope] = 'assigned-to-me' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
end
end end
...@@ -10,6 +10,8 @@ class GroupsController < ApplicationController ...@@ -10,6 +10,8 @@ class GroupsController < ApplicationController
# Load group projects # Load group projects
before_filter :projects, except: [:new, :create] before_filter :projects, except: [:new, :create]
before_filter :default_filter, only: [:issues, :merge_requests]
layout :determine_layout layout :determine_layout
before_filter :set_title, only: [:new, :create] before_filter :set_title, only: [:new, :create]
...@@ -45,18 +47,14 @@ class GroupsController < ApplicationController ...@@ -45,18 +47,14 @@ class GroupsController < ApplicationController
end end
end end
# Get authored or assigned open merge requests
def merge_requests def merge_requests
@merge_requests = current_user.cared_merge_requests.of_group(@group) @merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = FilterContext.new(@merge_requests, params).execute @merge_requests = @merge_requests.page(params[:page]).per(20)
@merge_requests = @merge_requests.recent.page(params[:page]).per(20)
end end
# Get only assigned issues
def issues def issues
@issues = current_user.assigned_issues.of_group(@group) @issues = FilteringService.new.execute(Issue, current_user, params)
@issues = FilterContext.new(@issues, params).execute @issues = @issues.page(params[:page]).per(20)
@issues = @issues.recent.page(params[:page]).per(20)
@issues = @issues.includes(:author, :project) @issues = @issues.includes(:author, :project)
respond_to do |format| respond_to do |format|
...@@ -132,4 +130,10 @@ class GroupsController < ApplicationController ...@@ -132,4 +130,10 @@ class GroupsController < ApplicationController
'group' 'group'
end end
end end
def default_filter
params[:scope] = 'assigned-to-me' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
params[:group_id] = @group.id
end
end end
...@@ -13,7 +13,7 @@ class Projects::BlobController < Projects::ApplicationController ...@@ -13,7 +13,7 @@ class Projects::BlobController < Projects::ApplicationController
end end
def destroy def destroy
result = Files::DeleteContext.new(@project, current_user, params, @ref, @path).execute result = Files::DeleteService.new(@project, current_user, params, @ref, @path).execute
if result[:status] == :success if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed" flash[:notice] = "Your changes have been successfully committed"
......
...@@ -6,34 +6,35 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -6,34 +6,35 @@ class Projects::CommitController < Projects::ApplicationController
before_filter :authorize_read_project! before_filter :authorize_read_project!
before_filter :authorize_code_access! before_filter :authorize_code_access!
before_filter :require_non_empty_project before_filter :require_non_empty_project
before_filter :commit
def show def show
result = CommitLoadContext.new(project, current_user, params).execute return git_not_found! unless @commit
@commit = result[:commit] @line_notes = project.notes.for_commit_id(commit.id).inline
@branches = project.repository.branch_names_contains(commit.id)
if @commit.nil? begin
git_not_found! @suppress_diff = true if commit.diff_suppress? && !params[:force_show_diff]
return @force_suppress_diff = commit.diff_force_suppress?
rescue Grit::Git::GitTimeout
@suppress_diff = true
@status = :huge_commit
end end
@suppress_diff = result[:suppress_diff] @note = project.build_commit_note(commit)
@force_suppress_diff = result[:force_suppress_diff] @notes_count = project.notes.for_commit_id(commit.id).count
@notes = project.notes.for_commit_id(@commit.id).not_inline.fresh
@note = result[:note] @noteable = @commit
@line_notes = result[:line_notes]
@branches = result[:branches]
@notes_count = result[:notes_count]
@target_type = :commit
@target_id = @commit.id
@comments_allowed = @reply_allowed = true @comments_allowed = @reply_allowed = true
@comments_target = { noteable_type: 'Commit', @comments_target = {
commit_id: @commit.id } noteable_type: 'Commit',
commit_id: @commit.id
}
respond_to do |format| respond_to do |format|
format.html do format.html do
if result[:status] == :huge_commit if @status == :huge_commit
render "huge_commit" and return render "huge_commit" and return
end end
end end
...@@ -42,4 +43,8 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -42,4 +43,8 @@ class Projects::CommitController < Projects::ApplicationController
format.patch { render text: @commit.to_patch } format.patch { render text: @commit.to_patch }
end end
end end
def commit
@commit ||= project.repository.commit(params[:id])
end
end end
...@@ -7,7 +7,7 @@ class Projects::EditTreeController < Projects::BaseTreeController ...@@ -7,7 +7,7 @@ class Projects::EditTreeController < Projects::BaseTreeController
end end
def update def update
result = Files::UpdateContext.new(@project, current_user, params, @ref, @path).execute result = Files::UpdateService.new(@project, current_user, params, @ref, @path).execute
if result[:status] == :success if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed" flash[:notice] = "Your changes have been successfully committed"
......
...@@ -24,15 +24,20 @@ class Projects::HooksController < Projects::ApplicationController ...@@ -24,15 +24,20 @@ class Projects::HooksController < Projects::ApplicationController
end end
def test def test
TestHookContext.new(project, current_user, params).execute TestHookService.new.execute(hook, current_user)
redirect_to :back redirect_to :back
end end
def destroy def destroy
@hook = @project.hooks.find(params[:id]) hook.destroy
@hook.destroy
redirect_to project_hooks_path(@project) redirect_to project_hooks_path(@project)
end end
private
def hook
@hook ||= @project.hooks.find(params[:id])
end
end end
...@@ -49,8 +49,8 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -49,8 +49,8 @@ class Projects::IssuesController < Projects::ApplicationController
def show def show
@note = @project.notes.new(noteable: @issue) @note = @project.notes.new(noteable: @issue)
@target_type = :issue @notes = @issue.notes.inc_author.fresh
@target_id = @issue.id @noteable = @issue
respond_with(@issue) respond_with(@issue)
end end
...@@ -89,7 +89,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -89,7 +89,7 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def bulk_update def bulk_update
result = Issues::BulkUpdateContext.new(project, current_user, params).execute result = Issues::BulkUpdateService.new(project, current_user, params).execute
redirect_to :back, notice: "#{result[:count]} issues updated" redirect_to :back, notice: "#{result[:count]} issues updated"
end end
...@@ -116,7 +116,9 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -116,7 +116,9 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def issues_filtered def issues_filtered
@issues = Issues::ListContext.new(project, current_user, params).execute params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@issues = FilteringService.new.execute(Issue, current_user, params.merge(project_id: @project.id))
end end
# Since iids are implemented only in 6.1 # Since iids are implemented only in 6.1
......
...@@ -17,7 +17,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -17,7 +17,14 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort] before_filter :authorize_modify_merge_request!, only: [:close, :edit, :update, :sort]
def index def index
@merge_requests = MergeRequestsLoadContext.new(project, current_user, params).execute params[:sort] ||= 'newest'
params[:scope] = 'all' if params[:scope].blank?
params[:state] = 'opened' if params[:state].blank?
@merge_requests = FilteringService.new.execute(MergeRequest, current_user, params.merge(project_id: @project.id))
@merge_requests = @merge_requests.page(params[:page]).per(20)
@sort = params[:sort].humanize
assignee_id, milestone_id = params[:assignee_id], params[:milestone_id] assignee_id, milestone_id = params[:assignee_id], params[:milestone_id]
@assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero? @assignee = @project.team.find(assignee_id) if assignee_id.present? && !assignee_id.to_i.zero?
@milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero? @milestone = @project.milestones.find(milestone_id) if milestone_id.present? && !milestone_id.to_i.zero?
...@@ -123,7 +130,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -123,7 +130,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if @merge_request.opened? && @merge_request.can_be_merged? if @merge_request.opened? && @merge_request.can_be_merged?
@merge_request.should_remove_source_branch = params[:should_remove_source_branch] @merge_request.should_remove_source_branch = params[:should_remove_source_branch]
@merge_request.automerge!(current_user) @merge_request.automerge!(current_user, params[:merge_commit_message])
@status = true @status = true
else else
@status = false @status = false
...@@ -198,6 +205,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -198,6 +205,9 @@ class Projects::MergeRequestsController < Projects::ApplicationController
def define_show_vars def define_show_vars
# Build a note object for comment form # Build a note object for comment form
@note = @project.notes.new(noteable: @merge_request) @note = @project.notes.new(noteable: @merge_request)
@notes = @merge_request.mr_and_commit_notes.inc_author.fresh
@discussions = Note.discussions_from_notes(@notes)
@noteable = @merge_request
# Get commits from repository # Get commits from repository
# or from cache if already merged # or from cache if already merged
...@@ -205,9 +215,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -205,9 +215,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@allowed_to_merge = allowed_to_merge? @allowed_to_merge = allowed_to_merge?
@show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
@target_type = :merge_request
@target_id = @merge_request.id
end end
def allowed_to_merge? def allowed_to_merge?
......
...@@ -6,7 +6,7 @@ class Projects::NewTreeController < Projects::BaseTreeController ...@@ -6,7 +6,7 @@ class Projects::NewTreeController < Projects::BaseTreeController
def update def update
file_path = File.join(@path, File.basename(params[:file_name])) file_path = File.join(@path, File.basename(params[:file_name]))
result = Files::CreateContext.new(@project, current_user, params, @ref, file_path).execute result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
if result[:status] == :success if result[:status] == :success
flash[:notice] = "Your changes have been successfully committed" flash[:notice] = "Your changes have been successfully committed"
......
...@@ -2,71 +2,54 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -2,71 +2,54 @@ class Projects::NotesController < Projects::ApplicationController
# Authorize # Authorize
before_filter :authorize_read_note! before_filter :authorize_read_note!
before_filter :authorize_write_note!, only: [:create] before_filter :authorize_write_note!, only: [:create]
before_filter :authorize_admin_note!, only: [:update, :destroy]
respond_to :js
def index def index
@notes = Notes::LoadContext.new(project, current_user, params).execute @notes = Notes::LoadService.new(project, current_user, params).execute
@target_type = params[:target_type].camelize
@target_id = params[:target_id]
if params[:target_type] == "merge_request" notes_json = { notes: [] }
@discussions = discussions_from_notes
end
respond_to do |format| @notes.each do |note|
format.html { redirect_to :back } notes_json[:notes] << {
format.json do id: note.id,
render json: { html: note_to_html(note)
html: view_to_html_string("projects/notes/_notes") }
}
end
end end
render json: notes_json
end end
def create def create
@note = Notes::CreateContext.new(project, current_user, params).execute @note = Notes::CreateService.new(project, current_user, params).execute
@target_type = params[:target_type].camelize
@target_id = params[:target_id]
respond_to do |format| respond_to do |format|
format.html {redirect_to :back} format.json { render_note_json(@note) }
format.js format.html { redirect_to :back }
end end
end end
def destroy def update
@note = @project.notes.find(params[:id]) note.update_attributes(params[:note])
return access_denied! unless can?(current_user, :admin_note, @note) note.reset_events_cache
@note.destroy
@note.reset_events_cache
respond_to do |format| respond_to do |format|
format.js { render nothing: true } format.json { render_note_json(note) }
format.html { redirect_to :back }
end end
end end
def update def destroy
@note = @project.notes.find(params[:id]) note.destroy
return access_denied! unless can?(current_user, :admin_note, @note) note.reset_events_cache
@note.update_attributes(params[:note])
@note.reset_events_cache
respond_to do |format| respond_to do |format|
format.js do format.js { render nothing: true }
render js: { success: @note.valid?, id: @note.id, note: view_context.markdown(@note.note) }.to_json
end
format.html do
redirect_to :back
end
end end
end end
def delete_attachment def delete_attachment
@note = @project.notes.find(params[:id]) note.remove_attachment!
@note.remove_attachment! note.update_attribute(:attachment, nil)
@note.update_attribute(:attachment, nil)
respond_to do |format| respond_to do |format|
format.js { render nothing: true } format.js { render nothing: true }
...@@ -77,35 +60,40 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -77,35 +60,40 @@ class Projects::NotesController < Projects::ApplicationController
render text: view_context.markdown(params[:note]) render text: view_context.markdown(params[:note])
end end
protected private
def discussion_notes_for(note) def note
@notes.select do |other_note| @note ||= @project.notes.find(params[:id])
note.discussion_id == other_note.discussion_id
end
end end
def discussions_from_notes def note_to_html(note)
discussion_ids = [] render_to_string(
discussions = [] "projects/notes/_note",
layout: false,
formats: [:html],
locals: { note: note }
)
end
@notes.each do |note| def note_to_discussion_html(note)
next if discussion_ids.include?(note.discussion_id) render_to_string(
"projects/notes/_diff_notes_with_reply",
# don't group notes for the main target layout: false,
if note_for_main_target?(note) formats: [:html],
discussions << [note] locals: { notes: [note] }
else )
discussions << discussion_notes_for(note) end
discussion_ids << note.discussion_id
end
end
discussions def render_note_json(note)
render json: {
id: note.id,
discussion_id: note.discussion_id,
html: note_to_html(note),
discussion_html: note_to_discussion_html(note)
}
end end
# Helps to distinguish e.g. commit notes in mr notes list def authorize_admin_note!
def note_for_main_target?(note) return access_denied! unless can?(current_user, :admin_note, note)
(@target_type.camelize == note.noteable_type && !note.for_diff_line?)
end end
end end
...@@ -6,7 +6,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController ...@@ -6,7 +6,7 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
before_filter :authorize_admin_project!, only: [:destroy, :create] before_filter :authorize_admin_project!, only: [:destroy, :create]
def index def index
@branches = @project.protected_branches.all @branches = @project.protected_branches.to_a
@protected_branch = @project.protected_branches.new @protected_branch = @project.protected_branches.new
end end
......
...@@ -16,7 +16,7 @@ class Projects::RepositoriesController < Projects::ApplicationController ...@@ -16,7 +16,7 @@ class Projects::RepositoriesController < Projects::ApplicationController
storage_path = Rails.root.join("tmp", "repositories") storage_path = Rails.root.join("tmp", "repositories")
file_path = @repository.archive_repo(params[:ref], storage_path) file_path = @repository.archive_repo(params[:ref], storage_path, params[:format].downcase)
if file_path if file_path
# Send file to user # Send file to user
......
...@@ -48,8 +48,8 @@ class Projects::SnippetsController < Projects::ApplicationController ...@@ -48,8 +48,8 @@ class Projects::SnippetsController < Projects::ApplicationController
def show def show
@note = @project.notes.new(noteable: @snippet) @note = @project.notes.new(noteable: @snippet)
@target_type = :snippet @notes = @snippet.notes.fresh
@target_id = @snippet.id @noteable = @snippet
end end
def destroy def destroy
......
...@@ -20,7 +20,7 @@ class ProjectsController < ApplicationController ...@@ -20,7 +20,7 @@ class ProjectsController < ApplicationController
end end
def create def create
@project = ::Projects::CreateContext.new(current_user, params[:project]).execute @project = ::Projects::CreateService.new(current_user, params[:project]).execute
respond_to do |format| respond_to do |format|
flash[:notice] = 'Project was successfully created.' if @project.saved? flash[:notice] = 'Project was successfully created.' if @project.saved?
...@@ -36,7 +36,7 @@ class ProjectsController < ApplicationController ...@@ -36,7 +36,7 @@ class ProjectsController < ApplicationController
end end
def update def update
status = ::Projects::UpdateContext.new(@project, current_user, params).execute status = ::Projects::UpdateService.new(@project, current_user, params).execute
respond_to do |format| respond_to do |format|
if status if status
...@@ -51,7 +51,7 @@ class ProjectsController < ApplicationController ...@@ -51,7 +51,7 @@ class ProjectsController < ApplicationController
end end
def transfer def transfer
::Projects::TransferContext.new(project, current_user, params).execute ::Projects::TransferService.new(project, current_user, params).execute
end end
def show def show
...@@ -89,7 +89,7 @@ class ProjectsController < ApplicationController ...@@ -89,7 +89,7 @@ class ProjectsController < ApplicationController
end end
def fork def fork
@forked_project = ::Projects::ForkContext.new(project, current_user).execute @forked_project = ::Projects::ForkService.new(project, current_user).execute
respond_to do |format| respond_to do |format|
format.html do format.html do
......
...@@ -8,6 +8,7 @@ class Public::ProjectsController < ApplicationController ...@@ -8,6 +8,7 @@ class Public::ProjectsController < ApplicationController
def index def index
@projects = Project.public_or_internal_only(current_user) @projects = Project.public_or_internal_only(current_user)
@projects = @projects.search(params[:search]) if params[:search].present? @projects = @projects.search(params[:search]) if params[:search].present?
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page]).per(20) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace).page(params[:page]).per(20)
end end
end end
class SearchController < ApplicationController class SearchController < ApplicationController
def show include SearchHelper
project_id = params[:project_id]
group_id = params[:group_id]
project_ids = current_user.authorized_projects.map(&:id) def show
@project = Project.find_by_id(params[:project_id]) if params[:project_id].present?
@group = Group.find_by_id(params[:group_id]) if params[:group_id].present?
if group_id.present? if @project
@group = Group.find(group_id) return access_denied! unless can?(current_user, :download_code, @project)
group_project_ids = @group.projects.map(&:id) @search_results = Search::ProjectService.new(@project, current_user, params).execute
project_ids.select! { |id| group_project_ids.include?(id)} else
elsif project_id.present? @search_results = Search::GlobalService.new(current_user, params).execute
@project = Project.find(params[:project_id])
project_ids.select! { |id| id == project_id.to_i}
end end
end
result = SearchContext.new(project_ids, current_user, params).execute def autocomplete
term = params[:term]
@project = Project.find(params[:project_id]) if params[:project_id].present?
@ref = params[:project_ref] if params[:project_ref].present?
@projects = result[:projects] render json: search_autocomplete_opts(term).to_json
@merge_requests = result[:merge_requests]
@issues = result[:issues]
@wiki_pages = result[:wiki_pages]
@blobs = Kaminari.paginate_array(result[:blobs]).page(params[:page]).per(20)
@total_results = @projects.count + @merge_requests.count + @issues.count + @wiki_pages.count + @blobs.total_count
end end
end end
...@@ -3,7 +3,7 @@ class UsersController < ApplicationController ...@@ -3,7 +3,7 @@ class UsersController < ApplicationController
def show def show
@user = User.find_by_username!(params[:username]) @user = User.find_by_username!(params[:username])
@projects = @user.authorized_projects.where('projects.id in (?)', current_user.authorized_projects.map(&:id)) @projects = @user.authorized_projects.where(id: current_user.authorized_projects.pluck(:id)).includes(:namespace)
@events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20) @events = @user.recent_events.where(project_id: @projects.map(&:id)).limit(20)
@title = @user.name @title = @user.name
......
This diff is collapsed.
module BroadcastMessagesHelper
def broadcast_styling(broadcast_message)
if(broadcast_message.color || broadcast_message.font)
"background-color:#{broadcast_message.color};color:#{broadcast_message.font}"
else
""
end
end
end
This diff is collapsed.
...@@ -90,14 +90,14 @@ module EventsHelper ...@@ -90,14 +90,14 @@ module EventsHelper
if event.note? && event.note_commit? if event.note? && event.note_commit?
project_commit_path(event.project, event.note_target) project_commit_path(event.project, event.note_target)
else else
url_for([event.project, event.note_target]) polymorphic_path([event.project, event.note_target], anchor: dom_id(event.target))
end end
end end
def event_note_title_html(event) def event_note_title_html(event)
if event.note_target if event.note_target
if event.note_commit? if event.note_commit?
link_to project_commit_path(event.project, event.note_commit_id), class: "commit_short_id" do link_to project_commit_path(event.project, event.note_commit_id, anchor: dom_id(event.target)), class: "commit_short_id" do
"#{event.note_target_type} #{event.note_short_commit_id}" "#{event.note_target_type} #{event.note_short_commit_id}"
end end
elsif event.note_project_snippet? elsif event.note_project_snippet?
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment