Commit 7863319b authored by Raffael Schmid's avatar Raffael Schmid

Merge branch 'master' into dont-depend-on-appid-and-appsecret

* master: (238 commits)
  Version 6.5.1
  Fix selectbox when submit MR from fork to origin
  Fix HELP layout
  No need for code tag here.
  Spelling mistake and add links.
  Warn against RVM.
  Remove GitHub mention because we also have a GitLab issue tracker now.
  Replace 6.0-to-6.4.md with 6.0-to-6.5.md
  Add public assets to gitignore
  Version 6.5.0
  Use 6-5 branch in installation docs
  Remove deprecated twitter handle.
  Further explain userPrincipalName settings
  Update from 6.4 to 6.5 guide
  Explain how to use AD userPrincipalName for logins
  More entries to CHANGELOG. Version to rc1
  Rephrase LDAP check script output
  add O'Reilly sponsorship in CHANGELOG
  Fix select2 css for drop above style
  Rename "Website url" labels to "Website"
  ...
parents 568d1c27 68590fdd
...@@ -34,3 +34,4 @@ doc/code/* ...@@ -34,3 +34,4 @@ doc/code/*
.secret .secret
*.log *.log
public/uploads.* public/uploads.*
public/assets/
v 6.5.1
- Fix branch selectbox when create merge request from fork
v 6.5.0 v 6.5.0
- Dropdown menus on issue#show page for assignee and milestone (Jason Blanchard) - Dropdown menus on issue#show page for assignee and milestone (Jason Blanchard)
- Add color custimization and previewing to broadcast messages - Add color custimization and previewing to broadcast messages
- Fixed notes anchors - Fixed notes anchors
- Load new comments in issues dynamically - Load new comments in issues dynamically
- Added sort options to Public page - Added sort options to Public page
- Added new filters(assigned/authored/all) to Dashboard#issues, Dashboard#merge_request pages - New filters (assigned/authored/all) for Dashboard#issues/merge_requests (sponsored by Say Media)
- Add project visibility icons to dashboard - Add project visibility icons to dashboard
- Enable secure cookies if https used - Enable secure cookies if https used
- Protect users/confirmation with rack_attack - 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 v6.4.3
- Don't use unicorn worker killer if PhusionPassenger is defined - Don't use unicorn worker killer if PhusionPassenger is defined
......
This diff is collapsed.
...@@ -14,7 +14,6 @@ gem "protected_attributes" ...@@ -14,7 +14,6 @@ gem "protected_attributes"
gem 'rails-observers' gem 'rails-observers'
gem 'actionpack-page_caching' gem 'actionpack-page_caching'
gem 'actionpack-action_caching' gem 'actionpack-action_caching'
gem 'activerecord-deprecated_finders'
# Supported DBs # Supported DBs
gem "mysql2", group: :mysql gem "mysql2", group: :mysql
...@@ -52,6 +51,9 @@ gem "grape", "~> 0.6.1" ...@@ -52,6 +51,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"
...@@ -60,7 +62,7 @@ gem "stamp" ...@@ -60,7 +62,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"
...@@ -120,7 +122,7 @@ gem "redis-rails" ...@@ -120,7 +122,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"
...@@ -144,17 +146,16 @@ gem "therubyracer" ...@@ -144,17 +146,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
remote: https://github.com/gitlabhq/gon.git
revision: 58ca8e17273051cb370182cabd3602d1da6783ab
ref: 58ca8e17273051cb370182cabd3602d1da6783ab
specs:
gon (4.1.1)
actionpack (>= 2.3.0)
json
GIT GIT
remote: https://github.com/gitlabhq/markup.git remote: https://github.com/gitlabhq/markup.git
revision: 61ade389c1e1c159359338f570d18464a44ddbc4 revision: 61ade389c1e1c159359338f570d18464a44ddbc4
...@@ -64,7 +55,7 @@ GEM ...@@ -64,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)
...@@ -80,12 +71,6 @@ GEM ...@@ -80,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
...@@ -101,12 +86,6 @@ GEM ...@@ -101,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)
...@@ -135,6 +114,8 @@ GEM ...@@ -135,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)
...@@ -170,7 +151,6 @@ GEM ...@@ -170,7 +151,6 @@ 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
...@@ -212,6 +192,9 @@ GEM ...@@ -212,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
...@@ -247,7 +230,7 @@ GEM ...@@ -247,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)
...@@ -276,7 +259,7 @@ GEM ...@@ -276,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)
...@@ -298,7 +281,7 @@ GEM ...@@ -298,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)
...@@ -568,17 +551,15 @@ PLATFORMS ...@@ -568,17 +551,15 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
actionpack-action_caching actionpack-action_caching
actionpack-page_caching actionpack-page_caching
activerecord-deprecated_finders
acts-as-taggable-on acts-as-taggable-on
annotate (~> 2.6.0.beta2) annotate (~> 2.6.0.beta2)
asciidoctor asciidoctor
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
...@@ -587,6 +568,7 @@ DEPENDENCIES ...@@ -587,6 +568,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
...@@ -603,21 +585,21 @@ DEPENDENCIES ...@@ -603,21 +585,21 @@ DEPENDENCIES
gitlab_git (~> 4.0.0) 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.
......
...@@ -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()
......
...@@ -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)
......
...@@ -37,6 +37,9 @@ class Notes ...@@ -37,6 +37,9 @@ class Notes
# attachment button # attachment button
$(document).on "click", ".js-choose-note-attachment-button", @chooseNoteAttachment $(document).on "click", ".js-choose-note-attachment-button", @chooseNoteAttachment
# update the file name when an attachment is selected
$(document).on "change", ".js-note-attachment-input", @updateFormAttachment
# reply to diff/discussion notes # reply to diff/discussion notes
$(document).on "click", ".js-discussion-reply-button", @replyToDiscussionNote $(document).on "click", ".js-discussion-reply-button", @replyToDiscussionNote
...@@ -429,4 +432,16 @@ class Notes ...@@ -429,4 +432,16 @@ class Notes
updateVotes: -> updateVotes: ->
(new NotesVotes).updateVotes() (new NotesVotes).updateVotes()
###
Called after an attachment file has been selected.
Updates the file name for the selected attachment.
###
updateFormAttachment: ->
form = $(this).closest("form")
# get only the basename
filename = $(this).val().replace(/^.*[\\\/]/, "")
form.find(".js-attachment-filename").text filename
@Notes = Notes @Notes = Notes
...@@ -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
......
...@@ -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";
...@@ -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;
-moz-osx-font-smoothing: grayscale; font-weight: normal;
margin-bottom: 20px; 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 **/
...@@ -71,6 +155,31 @@ table a code { ...@@ -71,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;
...@@ -92,19 +201,6 @@ span.update-author { ...@@ -92,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 {
...@@ -119,18 +215,6 @@ p.time { ...@@ -119,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;
} }
...@@ -209,7 +293,7 @@ li.note { ...@@ -209,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 {
...@@ -236,6 +320,7 @@ li.note { ...@@ -236,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 {
...@@ -344,12 +429,6 @@ table { ...@@ -344,12 +429,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;
...@@ -395,3 +474,14 @@ table { ...@@ -395,3 +474,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;
}
}
&.form-tiny {
margin: 0;
}
}
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 {
...@@ -68,7 +13,6 @@ input[type='text'].danger { ...@@ -68,7 +13,6 @@ input[type='text'].danger {
fieldset legend { fieldset legend {
font-size: 16px; font-size: 16px;
margin-bottom: 10px;
} }
.datetime-controls { .datetime-controls {
...@@ -76,3 +20,34 @@ fieldset legend { ...@@ -76,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;
}
...@@ -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;
} }
} }
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
ul { ul {
margin: 0; margin: 0;
padding: 0;
} }
.title { .title {
...@@ -157,7 +158,8 @@ ...@@ -157,7 +158,8 @@
.title { .title {
background: #D65; background: #D65;
color: #fff; color: #fff;
text-shadow: 0 1px 1px #900; text-shadow: none;
font-weight: 500;
} }
} }
......
/** 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/ui_box.scss";
@import "gitlab_bootstrap/issue_box.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: 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;
}
}
.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;
} }
......
...@@ -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;
} }
} }
...@@ -107,7 +102,6 @@ ...@@ -107,7 +102,6 @@
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 {
......
...@@ -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;
} }
} }
...@@ -120,11 +120,6 @@ input.check_all_issues { ...@@ -120,11 +120,6 @@ input.check_all_issues {
} }
} }
.edit-issue.inline-update select {
width: 100%;
max-width: 200px;
}
.issue-show-labels .label { .issue-show-labels .label {
padding: 6px 10px; padding: 6px 10px;
} }
......
/* 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;
...@@ -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 {
...@@ -41,24 +41,29 @@ ...@@ -41,24 +41,29 @@
.project-home-desc { .project-home-desc {
float: left; float: left;
color: #777; 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 9px; 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,46 +230,10 @@ ul.nav.nav-projects-tabs { ...@@ -233,46 +230,10 @@ ul.nav.nav-projects-tabs {
} }
} }
.transfer-project .chosen-container { .transfer-project .select2-container {
min-width: 200px; min-width: 200px;
} }
/** Branch/tag selector **/
.project-refs-form {
margin: 0;
span {
background:none !important;
position:static !important;
width:auto !important;
height:auto !important;
}
}
.project-refs-select {
width: 120px;
}
.project-refs-form .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;
}
}
}
.deploy-project-label { .deploy-project-label {
margin: 1px; margin: 1px;
} }
.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,7 +120,7 @@ ...@@ -111,7 +120,7 @@
.tree-ref-holder { .tree-ref-holder {
float: left; float: left;
margin-top: 5px; margin-top: 8px;
} }
.readme-holder { .readme-holder {
......
...@@ -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;
......
/** 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;
}
.chosen-compact {
max-width: 170px !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
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
...@@ -52,6 +52,6 @@ class Admin::GroupsController < Admin::ApplicationController ...@@ -52,6 +52,6 @@ class Admin::GroupsController < Admin::ApplicationController
private private
def group def group
@group = Group.find_by_path(params[:id]) @group = Group.find_by(path: params[:id])
end end
end end
...@@ -5,7 +5,7 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -5,7 +5,7 @@ class Admin::ProjectsController < Admin::ApplicationController
def index def index
owner_id = params[:owner_id] owner_id = params[:owner_id]
user = User.find_by_id(owner_id) user = User.find_by(id: owner_id)
@projects = user ? user.owned_projects : Project.all @projects = user ? user.owned_projects : Project.all
@projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present? @projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
...@@ -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]
......
...@@ -100,6 +100,6 @@ class Admin::UsersController < Admin::ApplicationController ...@@ -100,6 +100,6 @@ class Admin::UsersController < Admin::ApplicationController
protected protected
def user def user
@user ||= User.find_by_username!(params[:id]) @user ||= User.find_by!(username: params[:id])
end end
end end
...@@ -161,6 +161,8 @@ class ApplicationController < ActionController::Base ...@@ -161,6 +161,8 @@ class ApplicationController < ActionController::Base
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-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
...@@ -205,7 +207,7 @@ class ApplicationController < ActionController::Base ...@@ -205,7 +207,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.
...@@ -39,7 +41,7 @@ class DashboardController < ApplicationController ...@@ -39,7 +41,7 @@ class DashboardController < ApplicationController
current_user.authorized_projects current_user.authorized_projects
end end
@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) @projects = @projects.includes(:namespace)
@projects = @projects.tagged_with(params[:label]) if params[:label].present? @projects = @projects.tagged_with(params[:label]) if params[:label].present?
...@@ -51,12 +53,12 @@ class DashboardController < ApplicationController ...@@ -51,12 +53,12 @@ class DashboardController < ApplicationController
end end
def merge_requests def merge_requests
@merge_requests = FilterContext.new(MergeRequest, current_user, params).execute @merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = @merge_requests.recent.page(params[:page]).per(20) @merge_requests = @merge_requests.recent.page(params[:page]).per(20)
end end
def issues def issues
@issues = FilterContext.new(Issue, current_user, params).execute @issues = FilteringService.new.execute(Issue, current_user, params)
@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)
...@@ -71,4 +73,9 @@ class DashboardController < ApplicationController ...@@ -71,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]
...@@ -43,18 +45,14 @@ class GroupsController < ApplicationController ...@@ -43,18 +45,14 @@ class GroupsController < ApplicationController
end end
end end
# Get authored or assigned open merge requests
def merge_requests def merge_requests
@merge_requests = FilterContext.new(MergeRequest, current_user, params).execute @merge_requests = FilteringService.new.execute(MergeRequest, current_user, params)
@merge_requests = @merge_requests.of_group(@group) @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 = FilterContext.new(Issue, current_user, params).execute @issues = FilteringService.new.execute(Issue, current_user, params)
@issues = @issues.of_group(@group) @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|
...@@ -89,7 +87,7 @@ class GroupsController < ApplicationController ...@@ -89,7 +87,7 @@ class GroupsController < ApplicationController
protected protected
def group def group
@group ||= Group.find_by_path(params[:id]) @group ||= Group.find_by(path: params[:id])
end end
def projects def projects
...@@ -130,4 +128,10 @@ class GroupsController < ApplicationController ...@@ -130,4 +128,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
...@@ -19,6 +19,6 @@ class Profiles::GroupsController < ApplicationController ...@@ -19,6 +19,6 @@ class Profiles::GroupsController < ApplicationController
private private
def group def group
@group ||= Group.find_by_path(params[:id]) @group ||= Group.find_by(path: params[:id])
end 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
@note = result[:note]
@line_notes = result[:line_notes]
@branches = result[:branches]
@notes_count = result[:notes_count]
@notes = project.notes.for_commit_id(@commit.id).not_inline.fresh @notes = project.notes.for_commit_id(@commit.id).not_inline.fresh
@noteable = @commit @noteable = @commit
@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
...@@ -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
...@@ -97,7 +97,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -97,7 +97,7 @@ class Projects::IssuesController < Projects::ApplicationController
def issue def issue
@issue ||= begin @issue ||= begin
@project.issues.find_by_iid!(params[:id]) @project.issues.find_by!(iid: params[:id])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
redirect_old redirect_old
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
...@@ -125,7 +127,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -125,7 +127,7 @@ class Projects::IssuesController < Projects::ApplicationController
# To prevent 404 errors we provide a redirect to correct iids until 7.0 release # To prevent 404 errors we provide a redirect to correct iids until 7.0 release
# #
def redirect_old def redirect_old
issue = @project.issues.find_by_id(params[:id]) issue = @project.issues.find_by(id: params[:id])
if issue if issue
redirect_to project_issue_path(@project, issue) redirect_to project_issue_path(@project, issue)
......
...@@ -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
...@@ -145,6 +152,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -145,6 +152,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
@target_project = selected_target_project @target_project = selected_target_project
@target_branches = @target_project.repository.branch_names @target_branches = @target_project.repository.branch_names
@target_branches @target_branches
respond_to do |format|
format.js
end
end end
def ci_status def ci_status
...@@ -161,7 +172,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -161,7 +172,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end end
def merge_request def merge_request
@merge_request ||= @project.merge_requests.find_by_iid!(params[:id]) @merge_request ||= @project.merge_requests.find_by!(iid: params[:id])
end end
def closes_issues def closes_issues
......
...@@ -76,7 +76,7 @@ class Projects::MilestonesController < Projects::ApplicationController ...@@ -76,7 +76,7 @@ class Projects::MilestonesController < Projects::ApplicationController
protected protected
def milestone def milestone
@milestone ||= @project.milestones.find_by_iid!(params[:id]) @milestone ||= @project.milestones.find_by!(iid: params[:id])
end end
def authorize_admin_milestone! def authorize_admin_milestone!
......
...@@ -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"
......
...@@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -5,7 +5,7 @@ class Projects::NotesController < Projects::ApplicationController
before_filter :authorize_admin_note!, only: [:update, :destroy] before_filter :authorize_admin_note!, only: [:update, :destroy]
def index def index
@notes = Notes::LoadContext.new(project, current_user, params).execute @notes = Notes::LoadService.new(project, current_user, params).execute
notes_json = { notes: [] } notes_json = { notes: [] }
...@@ -20,7 +20,7 @@ class Projects::NotesController < Projects::ApplicationController ...@@ -20,7 +20,7 @@ class Projects::NotesController < Projects::ApplicationController
end end
def create def create
@note = Notes::CreateContext.new(project, current_user, params).execute @note = Notes::CreateService.new(project, current_user, params).execute
respond_to do |format| respond_to do |format|
format.json { render_note_json(@note) } format.json { render_note_json(@note) }
......
...@@ -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
......
...@@ -26,7 +26,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -26,7 +26,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end end
def update def update
@user_project_relation = project.users_projects.find_by_user_id(member) @user_project_relation = project.users_projects.find_by(user_id: member)
@user_project_relation.update_attributes(params[:team_member]) @user_project_relation.update_attributes(params[:team_member])
unless @user_project_relation.valid? unless @user_project_relation.valid?
...@@ -36,7 +36,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -36,7 +36,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end end
def destroy def destroy
@user_project_relation = project.users_projects.find_by_user_id(member) @user_project_relation = project.users_projects.find_by(user_id: member)
@user_project_relation.destroy @user_project_relation.destroy
respond_to do |format| respond_to do |format|
...@@ -46,7 +46,7 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -46,7 +46,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end end
def leave def leave
project.users_projects.find_by_user_id(current_user).destroy project.users_projects.find_by(user_id: current_user).destroy
respond_to do |format| respond_to do |format|
format.html { redirect_to :back } format.html { redirect_to :back }
...@@ -65,6 +65,6 @@ class Projects::TeamMembersController < Projects::ApplicationController ...@@ -65,6 +65,6 @@ class Projects::TeamMembersController < Projects::ApplicationController
protected protected
def member def member
@member ||= User.find_by_username(params[:id]) @member ||= User.find_by(username: params[:id])
end end
end end
...@@ -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
......
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
...@@ -18,7 +18,7 @@ class SnippetsController < ApplicationController ...@@ -18,7 +18,7 @@ class SnippetsController < ApplicationController
end end
def user_index def user_index
@user = User.find_by_username(params[:username]) @user = User.find_by(username: params[:username])
@snippets = @user.snippets.fresh.non_expired @snippets = @user.snippets.fresh.non_expired
if @user == current_user if @user == current_user
......
...@@ -2,8 +2,8 @@ class UsersController < ApplicationController ...@@ -2,8 +2,8 @@ class UsersController < ApplicationController
layout 'navless' layout 'navless'
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
......
...@@ -30,7 +30,7 @@ class UsersGroupsController < ApplicationController ...@@ -30,7 +30,7 @@ class UsersGroupsController < ApplicationController
protected protected
def group def group
@group ||= Group.find_by_path(params[:group_id]) @group ||= Group.find_by(path: params[:group_id])
end end
def authorize_admin_group! def authorize_admin_group!
......
...@@ -50,7 +50,7 @@ module ApplicationHelper ...@@ -50,7 +50,7 @@ module ApplicationHelper
end end
def avatar_icon(user_email = '', size = nil) def avatar_icon(user_email = '', size = nil)
user = User.find_by_email(user_email) user = User.find_by(email: user_email)
if user && user.avatar.present? if user && user.avatar.present?
user.avatar.url user.avatar.url
else else
...@@ -72,7 +72,7 @@ module ApplicationHelper ...@@ -72,7 +72,7 @@ module ApplicationHelper
def last_commit(project) def last_commit(project)
if project.repo_exists? if project.repo_exists?
time_ago_with_tooltip(project.repository.commit.committed_date) + " ago" time_ago_with_tooltip(project.repository.commit.committed_date)
else else
"Never" "Never"
end end
...@@ -210,11 +210,15 @@ module ApplicationHelper ...@@ -210,11 +210,15 @@ module ApplicationHelper
def time_ago_with_tooltip(date, placement = 'top', html_class = 'time_ago') def time_ago_with_tooltip(date, placement = 'top', html_class = 'time_ago')
capture_haml do capture_haml do
haml_tag :time, time_ago_in_words(date), haml_tag :time, date.to_s,
class: html_class, datetime: date, title: date.stamp("Aug 21, 2011 9:23pm"), class: html_class, datetime: date.getutc.iso8601, title: date.stamp("Aug 21, 2011 9:23pm"),
data: { toggle: 'tooltip', placement: placement } data: { toggle: 'tooltip', placement: placement }
haml_tag :script, "$('." + html_class + "').tooltip()" haml_tag :script, "$('." + html_class + "').timeago().tooltip()"
end.html_safe end.html_safe
end end
def render_markup(file_name, file_content)
GitHub::Markup.render(file_name, file_content).html_safe
end
end end
module DashboardHelper module DashboardHelper
def filter_path(entity, options={}) def filter_path(entity, options={})
exist_opts = { exist_opts = {
status: params[:status], state: params[:state],
scope: params[:scope], scope: params[:scope],
project_id: params[:project_id], project_id: params[:project_id],
} }
......
...@@ -16,11 +16,11 @@ module LabelsHelper ...@@ -16,11 +16,11 @@ module LabelsHelper
when *klass.warning_labels when *klass.warning_labels
'label-warning' 'label-warning'
when *klass.neutral_labels when *klass.neutral_labels
'label-inverse' 'label-primary'
when *klass.positive_labels when *klass.positive_labels
'label-success' 'label-success'
when *klass.important_labels when *klass.important_labels
'label-important' 'label-danger'
else else
'label-info' 'label-info'
end end
......
...@@ -23,11 +23,11 @@ module NotesHelper ...@@ -23,11 +23,11 @@ module NotesHelper
def note_timestamp(note) def note_timestamp(note)
# Shows the created at time and the updated at time if different # Shows the created at time and the updated at time if different
ts = "#{time_ago_with_tooltip(note.created_at, 'bottom', 'note_created_ago')} ago" ts = "#{time_ago_with_tooltip(note.created_at, 'bottom', 'note_created_ago')}"
if note.updated_at != note.created_at if note.updated_at != note.created_at
ts << capture_haml do ts << capture_haml do
haml_tag :small do haml_tag :small do
haml_concat " (Edited #{time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago')} ago)" haml_concat " (Edited #{time_ago_with_tooltip(note.updated_at, 'bottom', 'note_edited_ago')})"
end end
end end
end end
......
...@@ -153,7 +153,7 @@ module ProjectsHelper ...@@ -153,7 +153,7 @@ module ProjectsHelper
"#{@project.path}\/#{@path} at #{@ref} - " + title "#{@project.path}\/#{@path} at #{@ref} - " + title
elsif current_controller?(:issues) elsif current_controller?(:issues)
if current_action?(:show) if current_action?(:show)
"Issue ##{@issue.iid} - " + title "Issue ##{@issue.iid} - #{@issue.title} - " + title
else else
"Issues - " + title "Issues - " + title
end end
...@@ -180,8 +180,9 @@ module ProjectsHelper ...@@ -180,8 +180,9 @@ module ProjectsHelper
title title
end end
def default_url_to_repo def default_url_to_repo(project = nil)
current_user ? @project.url_to_repo : @project.http_url_to_repo project = project || @project
current_user ? project.url_to_repo : project.http_url_to_repo
end end
def default_clone_protocol def default_clone_protocol
...@@ -190,7 +191,7 @@ module ProjectsHelper ...@@ -190,7 +191,7 @@ module ProjectsHelper
def project_last_activity(project) def project_last_activity(project)
if project.last_activity_at if project.last_activity_at
time_ago_with_tooltip(project.last_activity_at, 'bottom', 'last_activity_time_ago') + " ago" time_ago_with_tooltip(project.last_activity_at, 'bottom', 'last_activity_time_ago')
else else
"Never" "Never"
end end
......
module SearchHelper module SearchHelper
def search_autocomplete_source def search_autocomplete_opts(term)
return unless current_user return unless current_user
resources_results = [
groups_autocomplete(term),
projects_autocomplete(term),
public_projects_autocomplete(term),
].flatten
generic_results = project_autocomplete + default_autocomplete + help_autocomplete
generic_results.select! { |result| result[:label] =~ Regexp.new(term, "i") }
[ [
groups_autocomplete, resources_results,
projects_autocomplete, generic_results
public_projects_autocomplete,
default_autocomplete,
project_autocomplete,
help_autocomplete
].flatten.uniq do |item| ].flatten.uniq do |item|
item[:label] item[:label]
end.to_json end
end end
private private
...@@ -43,7 +49,7 @@ module SearchHelper ...@@ -43,7 +49,7 @@ module SearchHelper
# Autocomplete results for the current project, if it's defined # Autocomplete results for the current project, if it's defined
def project_autocomplete def project_autocomplete
if @project && @project.repository.exists? && @project.repository.root_ref if @project && @project.repository.exists? && @project.repository.root_ref
prefix = simple_sanitize(@project.name_with_namespace) prefix = search_result_sanitize(@project.name_with_namespace)
ref = @ref || @project.repository.root_ref ref = @ref || @project.repository.root_ref
[ [
...@@ -65,23 +71,36 @@ module SearchHelper ...@@ -65,23 +71,36 @@ module SearchHelper
end end
# Autocomplete results for the current user's groups # Autocomplete results for the current user's groups
def groups_autocomplete def groups_autocomplete(term, limit = 5)
current_user.authorized_groups.map do |group| current_user.authorized_groups.search(term).limit(limit).map do |group|
{ label: "group: #{simple_sanitize(group.name)}", url: group_path(group) } {
label: "group: #{search_result_sanitize(group.name)}",
url: group_path(group)
}
end end
end end
# Autocomplete results for the current user's projects # Autocomplete results for the current user's projects
def projects_autocomplete def projects_autocomplete(term, limit = 5)
current_user.authorized_projects.non_archived.map do |p| current_user.authorized_projects.search_by_title(term).non_archived.limit(limit).map do |p|
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } {
label: "project: #{search_result_sanitize(p.name_with_namespace)}",
url: project_path(p)
}
end end
end end
# Autocomplete results for the current user's projects # Autocomplete results for the current user's projects
def public_projects_autocomplete def public_projects_autocomplete(term, limit = 5)
Project.public_or_internal_only(current_user).non_archived.map do |p| Project.public_or_internal_only(current_user).search_by_title(term).non_archived.limit(limit).map do |p|
{ label: "project: #{simple_sanitize(p.name_with_namespace)}", url: project_path(p) } {
label: "project: #{search_result_sanitize(p.name_with_namespace)}",
url: project_path(p)
}
end end
end end
def search_result_sanitize(str)
Sanitize.clean(str)
end
end end
...@@ -8,7 +8,7 @@ module Emails ...@@ -8,7 +8,7 @@ module Emails
def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id)
@issue = Issue.find(issue_id) @issue = Issue.find(issue_id)
@previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @issue.project @project = @issue.project
mail(to: recipient(recipient_id), subject: subject("Changed issue ##{@issue.iid}", @issue.title)) mail(to: recipient(recipient_id), subject: subject("Changed issue ##{@issue.iid}", @issue.title))
end end
......
...@@ -8,7 +8,7 @@ module Emails ...@@ -8,7 +8,7 @@ module Emails
def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id)
@merge_request = MergeRequest.find(merge_request_id) @merge_request = MergeRequest.find(merge_request_id)
@previous_assignee = User.find_by_id(previous_assignee_id) if previous_assignee_id @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id
@project = @merge_request.project @project = @merge_request.project
mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title)) mail(to: recipient(recipient_id), subject: subject("Changed merge request ##{@merge_request.iid}", @merge_request.title))
end end
......
...@@ -45,6 +45,18 @@ module Issuable ...@@ -45,6 +45,18 @@ module Issuable
def search(query) def search(query)
where("title like :query", query: "%#{query}%") where("title like :query", query: "%#{query}%")
end end
def sort(method)
case method.to_s
when 'newest' then reorder('created_at DESC')
when 'oldest' then reorder('created_at ASC')
when 'recently_updated' then reorder('updated_at DESC')
when 'last_updated' then reorder('updated_at ASC')
when 'milestone_due_soon' then joins(:milestone).reorder("milestones.due_date ASC")
when 'milestone_due_later' then joins(:milestone).reorder("milestones.due_date DESC")
else reorder('created_at DESC')
end
end
end end
def today? def today?
......
...@@ -214,8 +214,8 @@ class MergeRequest < ActiveRecord::Base ...@@ -214,8 +214,8 @@ class MergeRequest < ActiveRecord::Base
self.merge self.merge
end end
def automerge!(current_user) def automerge!(current_user, commit_message = nil)
if Gitlab::Satellite::MergeAction.new(current_user, self).merge! && self.unmerged_commits.empty? if Gitlab::Satellite::MergeAction.new(current_user, self).merge!(commit_message) && self.unmerged_commits.empty?
self.merge!(current_user.id) self.merge!(current_user.id)
true true
end end
...@@ -319,6 +319,15 @@ class MergeRequest < ActiveRecord::Base ...@@ -319,6 +319,15 @@ class MergeRequest < ActiveRecord::Base
update_all(updated_at: Time.now) update_all(updated_at: Time.now)
end end
def merge_commit_message
message = "Merge branch '#{source_branch}' into '#{target_branch}'"
message << "\n\n"
message << title.to_s
message << "\n\n"
message << description.to_s
message
end
private private
def dump_commits(commits) def dump_commits(commits)
......
...@@ -82,6 +82,18 @@ class Note < ActiveRecord::Base ...@@ -82,6 +82,18 @@ class Note < ActiveRecord::Base
}, without_protection: true) }, without_protection: true)
end end
def create_assignee_change_note(noteable, project, author, assignee)
body = assignee.nil? ? '_Assignee removed_' : "_Reassigned to @#{assignee.username}_"
create({
noteable: noteable,
project: project,
author: author,
note: body,
system: true
}, without_protection: true)
end
def discussions_from_notes(notes) def discussions_from_notes(notes)
discussion_ids = [] discussion_ids = []
discussions = [] discussions = []
...@@ -111,8 +123,8 @@ class Note < ActiveRecord::Base ...@@ -111,8 +123,8 @@ class Note < ActiveRecord::Base
def commit_author def commit_author
@commit_author ||= @commit_author ||=
project.users.find_by_email(noteable.author_email) || project.users.find_by(email: noteable.author_email) ||
project.users.find_by_name(noteable.author_name) project.users.find_by(name: noteable.author_name)
rescue rescue
nil nil
end end
......
...@@ -138,13 +138,17 @@ class Project < ActiveRecord::Base ...@@ -138,13 +138,17 @@ class Project < ActiveRecord::Base
joins(:namespace).where("projects.archived = ?", false).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%") joins(:namespace).where("projects.archived = ?", false).where("projects.name LIKE :query OR projects.path LIKE :query OR namespaces.name LIKE :query OR projects.description LIKE :query", query: "%#{query}%")
end end
def search_by_title query
where("projects.archived = ?", false).where("LOWER(projects.name) LIKE :query", query: "%#{query.downcase}%")
end
def find_with_namespace(id) def find_with_namespace(id)
if id.include?("/") if id.include?("/")
id = id.split("/") id = id.split("/")
namespace = Namespace.find_by_path(id.first) namespace = Namespace.find_by(path: id.first)
return nil unless namespace return nil unless namespace
where(namespace_id: namespace.id).find_by_path(id.second) where(namespace_id: namespace.id).find_by(path: id.second)
else else
where(path: id, namespace_id: nil).last where(path: id, namespace_id: nil).last
end end
...@@ -201,6 +205,10 @@ class Project < ActiveRecord::Base ...@@ -201,6 +205,10 @@ class Project < ActiveRecord::Base
[Gitlab.config.gitlab.url, path_with_namespace].join("/") [Gitlab.config.gitlab.url, path_with_namespace].join("/")
end end
def web_url_without_protocol
web_url.split("://")[1]
end
def build_commit_note(commit) def build_commit_note(commit)
notes.new(commit_id: commit.id, noteable_type: "Commit") notes.new(commit_id: commit.id, noteable_type: "Commit")
end end
...@@ -270,9 +278,7 @@ class Project < ActiveRecord::Base ...@@ -270,9 +278,7 @@ class Project < ActiveRecord::Base
end end
def send_move_instructions def send_move_instructions
team.members.each do |user| NotificationService.new.project_was_moved(self)
Notify.delay.project_was_moved_email(self.id, user.id)
end
end end
def owner def owner
...@@ -290,7 +296,7 @@ class Project < ActiveRecord::Base ...@@ -290,7 +296,7 @@ class Project < ActiveRecord::Base
# Get Team Member record by user id # Get Team Member record by user id
def team_member_by_id(user_id) def team_member_by_id(user_id)
users_projects.find_by_user_id(user_id) users_projects.find_by(user_id: user_id)
end end
def name_with_namespace def name_with_namespace
......
...@@ -22,22 +22,22 @@ class ProjectTeam ...@@ -22,22 +22,22 @@ class ProjectTeam
end end
def find(user_id) def find(user_id)
user = project.users.find_by_id(user_id) user = project.users.find_by(id: user_id)
if group if group
user ||= group.users.find_by_id(user_id) user ||= group.users.find_by(id: user_id)
end end
user user
end end
def find_tm(user_id) def find_tm(user_id)
tm = project.users_projects.find_by_user_id(user_id) tm = project.users_projects.find_by(user_id: user_id)
# If user is not in project members # If user is not in project members
# we should check for group membership # we should check for group membership
if group && !tm if group && !tm
tm = group.users_groups.find_by_user_id(user_id) tm = group.users_groups.find_by(user_id: user_id)
end end
tm tm
......
...@@ -41,7 +41,8 @@ ...@@ -41,7 +41,8 @@
# confirmed_at :datetime # confirmed_at :datetime
# confirmation_sent_at :datetime # confirmation_sent_at :datetime
# unconfirmed_email :string(255) # unconfirmed_email :string(255)
# hide_no_ssh_key :boolean default(FALSE), not null # hide_no_ssh_key :boolean default(FALSE)
# website_url :string(255) default(""), not null
# #
require 'carrierwave/orm/activerecord' require 'carrierwave/orm/activerecord'
...@@ -52,7 +53,7 @@ class User < ActiveRecord::Base ...@@ -52,7 +53,7 @@ class User < ActiveRecord::Base
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable
attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username, attr_accessible :email, :password, :password_confirmation, :remember_me, :bio, :name, :username,
:skype, :linkedin, :twitter, :color_scheme_id, :theme_id, :force_random_password, :skype, :linkedin, :twitter, :website_url, :color_scheme_id, :theme_id, :force_random_password,
:extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key, :extern_uid, :provider, :password_expires_at, :avatar, :hide_no_ssh_key,
as: [:default, :admin] as: [:default, :admin]
...@@ -103,7 +104,7 @@ class User < ActiveRecord::Base ...@@ -103,7 +104,7 @@ class User < ActiveRecord::Base
# Validations # Validations
# #
validates :name, presence: true validates :name, presence: true
validates :email, presence: true, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/ }, uniqueness: true validates :email, presence: true, email: {strict_mode: true}, uniqueness: true
validates :bio, length: { maximum: 255 }, allow_blank: true validates :bio, length: { maximum: 255 }, allow_blank: true
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider} validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0} validates :projects_limit, presence: true, numericality: {greater_than_or_equal_to: 0}
...@@ -238,7 +239,7 @@ class User < ActiveRecord::Base ...@@ -238,7 +239,7 @@ class User < ActiveRecord::Base
def namespace_uniq def namespace_uniq
namespace_name = self.username namespace_name = self.username
if Namespace.find_by_path(namespace_name) if Namespace.find_by(path: namespace_name)
self.errors.add :username, "already exist" self.errors.add :username, "already exist"
end end
end end
...@@ -382,7 +383,7 @@ class User < ActiveRecord::Base ...@@ -382,7 +383,7 @@ class User < ActiveRecord::Base
end end
def created_by def created_by
User.find_by_id(created_by_id) if created_by_id User.find_by(id: created_by_id) if created_by_id
end end
def sanitize_attrs def sanitize_attrs
...@@ -424,4 +425,14 @@ class User < ActiveRecord::Base ...@@ -424,4 +425,14 @@ class User < ActiveRecord::Base
order('id DESC').limit(1000). order('id DESC').limit(1000).
update_all(updated_at: Time.now) update_all(updated_at: Time.now)
end end
def full_website_url
return "http://#{website_url}" if website_url !~ /^https?:\/\//
website_url
end
def short_website_url
website_url.gsub(/https?:\/\//, '')
end
end end
...@@ -28,7 +28,7 @@ class WebHook < ActiveRecord::Base ...@@ -28,7 +28,7 @@ class WebHook < ActiveRecord::Base
def execute(data) def execute(data)
parsed_url = URI.parse(url) parsed_url = URI.parse(url)
if parsed_url.userinfo.blank? if parsed_url.userinfo.blank?
WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }) WebHook.post(url, body: data.to_json, headers: { "Content-Type" => "application/json" }, verify: false)
else else
post_url = url.gsub("#{parsed_url.userinfo}@", "") post_url = url.gsub("#{parsed_url.userinfo}@", "")
auth = { auth = {
...@@ -38,6 +38,7 @@ class WebHook < ActiveRecord::Base ...@@ -38,6 +38,7 @@ class WebHook < ActiveRecord::Base
WebHook.post(post_url, WebHook.post(post_url,
body: data.to_json, body: data.to_json,
headers: {"Content-Type" => "application/json"}, headers: {"Content-Type" => "application/json"},
verify: false,
basic_auth: auth) basic_auth: auth)
end end
end end
......
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.
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