Commit 44727525 authored by Alfredo Sumaran's avatar Alfredo Sumaran

Merge branch 'master' into issue_14206

parents 38a4f5ce 7998725e
...@@ -691,7 +691,7 @@ Style/ZeroLengthPredicate: ...@@ -691,7 +691,7 @@ Style/ZeroLengthPredicate:
# branches, and conditions. # branches, and conditions.
Metrics/AbcSize: Metrics/AbcSize:
Enabled: true Enabled: true
Max: 70 Max: 60
# Avoid excessive block nesting. # Avoid excessive block nesting.
Metrics/BlockNesting: Metrics/BlockNesting:
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.7.0 (unreleased) v 8.7.0 (unreleased)
- Enable gzip for assets, makes the page size significantly smaller. !3544 / !3632 (Connor Shea)
- Load award emoji images separately unless opening the full picker. Saves several hundred KBs of data for most pages. (Connor Shea)
- All images in discussions and wikis now link to their source files !3464 (Connor Shea). - All images in discussions and wikis now link to their source files !3464 (Connor Shea).
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu)
- Improved Markdown rendering performance !3389 (Yorick Peterse) - Improved Markdown rendering performance !3389 (Yorick Peterse)
- Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu) - Don't attempt to look up an avatar in repo if repo directory does not exist (Stan Hu)
- Expose project badges in project settings
- Preserve time notes/comments have been updated at when moving issue - Preserve time notes/comments have been updated at when moving issue
- Make HTTP(s) label consistent on clone bar (Stan Hu) - Make HTTP(s) label consistent on clone bar (Stan Hu)
- Expose label description in API (Mariusz Jachimowicz) - Expose label description in API (Mariusz Jachimowicz)
- Allow back dating on issues when created through the API - Allow back dating on issues when created through the API
- Fix Error 500 after renaming a project path (Stan Hu) - Fix Error 500 after renaming a project path (Stan Hu)
- Fix avatar stretching by providing a cropping feature - Fix avatar stretching by providing a cropping feature
- API: Expose `subscribed` for issues and merge requests (Robert Schilling)
- Allow SAML to handle external users based on user's information !3530
- Add endpoints to archive or unarchive a project !3372 - Add endpoints to archive or unarchive a project !3372
- Add links to CI setup documentation from project settings and builds pages - Add links to CI setup documentation from project settings and builds pages
- Handle nil descriptions in Slack issue messages (Stan Hu) - Handle nil descriptions in Slack issue messages (Stan Hu)
- Add default scope to projects to exclude projects pending deletion - Add default scope to projects to exclude projects pending deletion
- Ensure empty recipients are rejected in BuildsEmailService - Ensure empty recipients are rejected in BuildsEmailService
- API: Ability to filter milestones by state `active` and `closed` (Robert Schilling)
- Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.) - Implement 'Groups View' as an option for dashboard preferences !3379 (Elias W.)
- Better errors handling when creating milestones inside groups
- Implement 'TODOs View' as an option for dashboard preferences !3379 (Elias W.) - Implement 'TODOs View' as an option for dashboard preferences !3379 (Elias W.)
- Gracefully handle notes on deleted commits in merge requests (Stan Hu) - Gracefully handle notes on deleted commits in merge requests (Stan Hu)
- Fix creation of merge requests for orphaned branches (Stan Hu) - Fix creation of merge requests for orphaned branches (Stan Hu)
- Fall back to `In-Reply-To` and `References` headers when sub-addressing is not available (David Padilla) - Fall back to `In-Reply-To` and `References` headers when sub-addressing is not available (David Padilla)
- Remove "Congratulations!" tweet button on newly-created project. (Connor Shea) - Remove "Congratulations!" tweet button on newly-created project. (Connor Shea)
- Improved UX of the navigation sidebar - Fix admin/projects when using visibility levels on search (PotHix)
- Build status notifications - Build status notifications
- API: Expose user location (Robert Schilling) - API: Expose user location (Robert Schilling)
- ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591
v 8.6.5 (unreleased) - Update number of Todos in the sidebar when it's marked as "Done". !3600
- Check permissions when user attempts to import members from another project
v 8.6.5
- Fix importing from GitHub Enterprise. !3529
- Perform the language detection after updating merge requests in `GitPushService`, leading to faster visual feedback for the end-user. !3533
- Check permissions when user attempts to import members from another project. !3535
- Only update repository language if it is not set to improve performance. !3556
- Return status code 303 after a branch DELETE operation to avoid project deletion (Stan Hu). !3583
- Unblock user when active_directory is disabled and it can be found !3550
- Fix a 2FA authentication spoofing vulnerability.
v 8.6.4 v 8.6.4
- Don't attempt to fetch any tags from a forked repo (Stan Hu) - Don't attempt to fetch any tags from a forked repo (Stan Hu)
- Redesign the Labels page
v 8.6.3 v 8.6.3
- Mentions on confidential issues doesn't create todos for non-members. !3374 - Mentions on confidential issues doesn't create todos for non-members. !3374
...@@ -146,6 +163,9 @@ v 8.6.0 ...@@ -146,6 +163,9 @@ v 8.6.0
- Trigger a todo for mentions on commits page - Trigger a todo for mentions on commits page
- Let project owners and admins soft delete issues and merge requests - Let project owners and admins soft delete issues and merge requests
v 8.5.10
- Fix a 2FA authentication spoofing vulnerability.
v 8.5.9 v 8.5.9
- Don't attempt to fetch any tags from a forked repo (Stan Hu). - Don't attempt to fetch any tags from a forked repo (Stan Hu).
...@@ -290,6 +310,9 @@ v 8.5.0 ...@@ -290,6 +310,9 @@ v 8.5.0
- Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul) - Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul)
- Add Todos - Add Todos
v 8.4.8
- Fix a 2FA authentication spoofing vulnerability.
v 8.4.7 v 8.4.7
- Don't attempt to fetch any tags from a forked repo (Stan Hu). - Don't attempt to fetch any tags from a forked repo (Stan Hu).
...@@ -409,6 +432,9 @@ v 8.4.0 ...@@ -409,6 +432,9 @@ v 8.4.0
- Add IP check against DNSBLs at account sign-up - Add IP check against DNSBLs at account sign-up
- Added cache:key to .gitlab-ci.yml allowing to fine tune the caching - Added cache:key to .gitlab-ci.yml allowing to fine tune the caching
v 8.3.7
- Fix a 2FA authentication spoofing vulnerability.
v 8.3.6 v 8.3.6
- Don't attempt to fetch any tags from a forked repo (Stan Hu). - Don't attempt to fetch any tags from a forked repo (Stan Hu).
......
...@@ -448,7 +448,7 @@ merge request: ...@@ -448,7 +448,7 @@ merge request:
- multi-line method chaining style **Option B**: dot `.` on previous line - multi-line method chaining style **Option B**: dot `.` on previous line
- string literal quoting style **Option A**: single quoted by default - string literal quoting style **Option A**: single quoted by default
1. [Rails](https://github.com/bbatsov/rails-style-guide) 1. [Rails](https://github.com/bbatsov/rails-style-guide)
1. [Testing](https://github.com/thoughtbot/guides/tree/master/style/testing) 1. [Testing](doc/development/testing.md)
1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style/coffeescript) 1. [CoffeeScript](https://github.com/thoughtbot/guides/tree/master/style/coffeescript)
1. [SCSS styleguide][scss-styleguide] 1. [SCSS styleguide][scss-styleguide]
1. [Shell commands](doc/development/shell_commands.md) created by GitLab 1. [Shell commands](doc/development/shell_commands.md) created by GitLab
......
source "https://rubygems.org" source "https://rubygems.org"
gem 'rails', '4.2.5.2' gem 'rails', '4.2.6'
gem 'rails-deprecated_sanitizer', '~> 1.0.3' gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Responders respond_to and respond_with # Responders respond_to and respond_with
...@@ -8,7 +8,7 @@ gem 'responders', '~> 2.0' ...@@ -8,7 +8,7 @@ gem 'responders', '~> 2.0'
# Specify a sprockets version due to increased performance # Specify a sprockets version due to increased performance
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/6069 # See https://gitlab.com/gitlab-org/gitlab-ce/issues/6069
gem 'sprockets', '~> 3.3.5' gem 'sprockets', '~> 3.6.0'
# Default values for AR models # Default values for AR models
gem "default_value_for", "~> 3.0.0" gem "default_value_for", "~> 3.0.0"
...@@ -149,6 +149,10 @@ gem 'version_sorter', '~> 2.0.0' ...@@ -149,6 +149,10 @@ gem 'version_sorter', '~> 2.0.0'
# Cache # Cache
gem "redis-rails", '~> 4.0.0' gem "redis-rails", '~> 4.0.0'
# Redis
gem 'redis', '~> 3.2'
gem 'connection_pool', '~> 2.0'
# Campfire integration # Campfire integration
gem 'tinder', '~> 1.10.0' gem 'tinder', '~> 1.10.0'
...@@ -229,14 +233,13 @@ group :metrics do ...@@ -229,14 +233,13 @@ group :metrics do
gem 'allocations', '~> 1.0', require: false, platform: :mri gem 'allocations', '~> 1.0', require: false, platform: :mri
gem 'method_source', '~> 0.8', require: false gem 'method_source', '~> 0.8', require: false
gem 'influxdb', '~> 0.2', require: false gem 'influxdb', '~> 0.2', require: false
gem 'connection_pool', '~> 2.0', require: false
end end
group :development do group :development do
gem "foreman" gem "foreman"
gem 'brakeman', '~> 3.2.0', require: false gem 'brakeman', '~> 3.2.0', require: false
gem "annotate", "~> 2.6.0" gem "annotate", "~> 2.7.0"
gem "letter_opener", '~> 1.1.2' gem "letter_opener", '~> 1.1.2'
gem 'quiet_assets', '~> 1.0.2' gem 'quiet_assets', '~> 1.0.2'
gem 'rerun', '~> 0.11.0' gem 'rerun', '~> 0.11.0'
...@@ -290,7 +293,7 @@ group :development, :test do ...@@ -290,7 +293,7 @@ group :development, :test do
gem 'rubocop', '~> 0.38.0', require: false gem 'rubocop', '~> 0.38.0', require: false
gem 'scss_lint', '~> 0.47.0', require: false gem 'scss_lint', '~> 0.47.0', require: false
gem 'coveralls', '~> 0.8.2', require: false gem 'coveralls', '~> 0.8.2', require: false
gem 'simplecov', '~> 0.10.0', require: false gem 'simplecov', '~> 0.11.0', require: false
gem 'flog', require: false gem 'flog', require: false
gem 'flay', require: false gem 'flay', require: false
gem 'bundler-audit', require: false gem 'bundler-audit', require: false
......
...@@ -4,41 +4,41 @@ GEM ...@@ -4,41 +4,41 @@ GEM
CFPropertyList (2.3.2) CFPropertyList (2.3.2)
RedCloth (4.2.9) RedCloth (4.2.9)
ace-rails-ap (2.0.1) ace-rails-ap (2.0.1)
actionmailer (4.2.5.2) actionmailer (4.2.6)
actionpack (= 4.2.5.2) actionpack (= 4.2.6)
actionview (= 4.2.5.2) actionview (= 4.2.6)
activejob (= 4.2.5.2) activejob (= 4.2.6)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.5.2) actionpack (4.2.6)
actionview (= 4.2.5.2) actionview (= 4.2.6)
activesupport (= 4.2.5.2) activesupport (= 4.2.6)
rack (~> 1.6) rack (~> 1.6)
rack-test (~> 0.6.2) rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.5.2) actionview (4.2.6)
activesupport (= 4.2.5.2) activesupport (= 4.2.6)
builder (~> 3.1) builder (~> 3.1)
erubis (~> 2.7.0) erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5) rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.0.2)
activejob (4.2.5.2) activejob (4.2.6)
activesupport (= 4.2.5.2) activesupport (= 4.2.6)
globalid (>= 0.3.0) globalid (>= 0.3.0)
activemodel (4.2.5.2) activemodel (4.2.6)
activesupport (= 4.2.5.2) activesupport (= 4.2.6)
builder (~> 3.1) builder (~> 3.1)
activerecord (4.2.5.2) activerecord (4.2.6)
activemodel (= 4.2.5.2) activemodel (= 4.2.6)
activesupport (= 4.2.5.2) activesupport (= 4.2.6)
arel (~> 6.0) arel (~> 6.0)
activerecord-deprecated_finders (1.0.4) activerecord-deprecated_finders (1.0.4)
activerecord-session_store (0.1.2) activerecord-session_store (0.1.2)
actionpack (>= 4.0.0, < 5) actionpack (>= 4.0.0, < 5)
activerecord (>= 4.0.0, < 5) activerecord (>= 4.0.0, < 5)
railties (>= 4.0.0, < 5) railties (>= 4.0.0, < 5)
activesupport (4.2.5.2) activesupport (4.2.6)
i18n (~> 0.7) i18n (~> 0.7)
json (~> 1.7, >= 1.7.7) json (~> 1.7, >= 1.7.7)
minitest (~> 5.1) minitest (~> 5.1)
...@@ -51,8 +51,8 @@ GEM ...@@ -51,8 +51,8 @@ GEM
activerecord (>= 3.0) activerecord (>= 3.0)
akismet (2.0.0) akismet (2.0.0)
allocations (1.0.4) allocations (1.0.4)
annotate (2.6.10) annotate (2.7.0)
activerecord (>= 3.2, <= 4.3) activerecord (>= 3.2, < 6.0)
rake (~> 10.4) rake (~> 10.4)
arel (6.0.3) arel (6.0.3)
asana (0.4.0) asana (0.4.0)
...@@ -136,17 +136,16 @@ GEM ...@@ -136,17 +136,16 @@ GEM
colorize (0.7.7) colorize (0.7.7)
concurrent-ruby (1.0.0) concurrent-ruby (1.0.0)
connection_pool (2.2.0) connection_pool (2.2.0)
coveralls (0.8.9) coveralls (0.8.13)
json (~> 1.8) json (~> 1.8)
rest-client (>= 1.6.8, < 2) simplecov (~> 0.11.0)
simplecov (~> 0.10.0)
term-ansicolor (~> 1.3) term-ansicolor (~> 1.3)
thor (~> 0.19.1) thor (~> 0.19.1)
tins (~> 1.6.0) tins (~> 1.6.0)
crack (0.4.3) crack (0.4.3)
safe_yaml (~> 1.0.0) safe_yaml (~> 1.0.0)
creole (0.5.0) creole (0.5.0)
css_parser (1.3.7) css_parser (1.4.1)
addressable addressable
d3_rails (3.5.11) d3_rails (3.5.11)
railties (>= 3.1.0) railties (>= 3.1.0)
...@@ -176,8 +175,6 @@ GEM ...@@ -176,8 +175,6 @@ GEM
diff-lcs (1.2.5) diff-lcs (1.2.5)
diffy (3.0.7) diffy (3.0.7)
docile (1.1.5) docile (1.1.5)
domain_name (0.5.25)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (2.2.2) doorkeeper (2.2.2)
railties (>= 3.2) railties (>= 3.2)
dropzonejs-rails (0.7.2) dropzonejs-rails (0.7.2)
...@@ -421,8 +418,6 @@ GEM ...@@ -421,8 +418,6 @@ GEM
nokogiri (~> 1.6.0) nokogiri (~> 1.6.0)
ruby_parser (~> 3.5) ruby_parser (~> 3.5)
htmlentities (4.3.4) htmlentities (4.3.4)
http-cookie (1.0.2)
domain_name (~> 0.5)
http_parser.rb (0.5.3) http_parser.rb (0.5.3)
httparty (0.13.7) httparty (0.13.7)
json (~> 1.8) json (~> 1.8)
...@@ -464,8 +459,8 @@ GEM ...@@ -464,8 +459,8 @@ GEM
nokogiri (>= 1.5.9) nokogiri (>= 1.5.9)
macaddr (1.7.1) macaddr (1.7.1)
systemu (~> 2.6.2) systemu (~> 2.6.2)
mail (2.6.3) mail (2.6.4)
mime-types (>= 1.16, < 3) mime-types (>= 1.16, < 4)
mail_room (0.6.1) mail_room (0.6.1)
method_source (0.8.2) method_source (0.8.2)
mime-types (1.25.1) mime-types (1.25.1)
...@@ -480,7 +475,6 @@ GEM ...@@ -480,7 +475,6 @@ GEM
nested_form (0.3.2) nested_form (0.3.2)
net-ldap (0.12.1) net-ldap (0.12.1)
net-ssh (3.0.1) net-ssh (3.0.1)
netrc (0.11.0)
newrelic_rpm (3.14.1.311) newrelic_rpm (3.14.1.311)
nokogiri (1.6.7.2) nokogiri (1.6.7.2)
mini_portile2 (~> 2.0.0.rc2) mini_portile2 (~> 2.0.0.rc2)
...@@ -565,8 +559,8 @@ GEM ...@@ -565,8 +559,8 @@ GEM
premailer (1.8.6) premailer (1.8.6)
css_parser (>= 1.3.6) css_parser (>= 1.3.6)
htmlentities (>= 4.0.0) htmlentities (>= 4.0.0)
premailer-rails (1.9.0) premailer-rails (1.9.2)
actionmailer (>= 3, < 5) actionmailer (>= 3, < 6)
premailer (~> 1.7, >= 1.7.9) premailer (~> 1.7, >= 1.7.9)
pry (0.10.3) pry (0.10.3)
coderay (~> 1.1.0) coderay (~> 1.1.0)
...@@ -595,16 +589,16 @@ GEM ...@@ -595,16 +589,16 @@ GEM
rack rack
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
rails (4.2.5.2) rails (4.2.6)
actionmailer (= 4.2.5.2) actionmailer (= 4.2.6)
actionpack (= 4.2.5.2) actionpack (= 4.2.6)
actionview (= 4.2.5.2) actionview (= 4.2.6)
activejob (= 4.2.5.2) activejob (= 4.2.6)
activemodel (= 4.2.5.2) activemodel (= 4.2.6)
activerecord (= 4.2.5.2) activerecord (= 4.2.6)
activesupport (= 4.2.5.2) activesupport (= 4.2.6)
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0, < 2.0)
railties (= 4.2.5.2) railties (= 4.2.6)
sprockets-rails sprockets-rails
rails-deprecated_sanitizer (1.0.3) rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha) activesupport (>= 4.2.0.alpha)
...@@ -614,9 +608,9 @@ GEM ...@@ -614,9 +608,9 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1) rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.3) rails-html-sanitizer (1.0.3)
loofah (~> 2.0) loofah (~> 2.0)
railties (4.2.5.2) railties (4.2.6)
actionpack (= 4.2.5.2) actionpack (= 4.2.6)
activesupport (= 4.2.5.2) activesupport (= 4.2.6)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rainbow (2.1.0) rainbow (2.1.0)
...@@ -657,10 +651,6 @@ GEM ...@@ -657,10 +651,6 @@ GEM
listen (~> 3.0) listen (~> 3.0)
responders (2.1.1) responders (2.1.1)
railties (>= 4.2.0, < 5.1) railties (>= 4.2.0, < 5.1)
rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rinku (1.7.3) rinku (1.7.3)
rotp (2.1.1) rotp (2.1.1)
rouge (1.10.1) rouge (1.10.1)
...@@ -754,7 +744,7 @@ GEM ...@@ -754,7 +744,7 @@ GEM
rufus-scheduler (>= 2.0.24) rufus-scheduler (>= 2.0.24)
sidekiq (>= 4.0.0) sidekiq (>= 4.0.0)
simple_oauth (0.1.9) simple_oauth (0.1.9)
simplecov (0.10.0) simplecov (0.11.2)
docile (~> 1.1.0) docile (~> 1.1.0)
json (~> 1.8) json (~> 1.8)
simplecov-html (~> 0.10.0) simplecov-html (~> 0.10.0)
...@@ -786,12 +776,13 @@ GEM ...@@ -786,12 +776,13 @@ GEM
spring (>= 0.9.1) spring (>= 0.9.1)
spring-commands-teaspoon (0.0.2) spring-commands-teaspoon (0.0.2)
spring (>= 0.9.1) spring (>= 0.9.1)
sprockets (3.3.5) sprockets (3.6.0)
concurrent-ruby (~> 1.0)
rack (> 1, < 3) rack (> 1, < 3)
sprockets-rails (2.3.3) sprockets-rails (3.0.4)
actionpack (>= 3.0) actionpack (>= 4.0)
activesupport (>= 3.0) activesupport (>= 4.0)
sprockets (>= 2.8, < 4.0) sprockets (>= 3.0.0)
state_machines (0.4.0) state_machines (0.4.0)
state_machines-activemodel (0.3.0) state_machines-activemodel (0.3.0)
activemodel (~> 4.1) activemodel (~> 4.1)
...@@ -845,7 +836,7 @@ GEM ...@@ -845,7 +836,7 @@ GEM
underscore-rails (1.8.3) underscore-rails (1.8.3)
unf (0.1.4) unf (0.1.4)
unf_ext unf_ext
unf_ext (0.0.7.1) unf_ext (0.0.7.2)
unicode-display_width (1.0.2) unicode-display_width (1.0.2)
unicorn (4.9.0) unicorn (4.9.0)
kgio (~> 2.6) kgio (~> 2.6)
...@@ -897,7 +888,7 @@ DEPENDENCIES ...@@ -897,7 +888,7 @@ DEPENDENCIES
after_commit_queue after_commit_queue
akismet (~> 2.0) akismet (~> 2.0)
allocations (~> 1.0) allocations (~> 1.0)
annotate (~> 2.6.0) annotate (~> 2.7.0)
asana (~> 0.4.0) asana (~> 0.4.0)
asciidoctor (~> 1.5.2) asciidoctor (~> 1.5.2)
attr_encrypted (~> 1.3.4) attr_encrypted (~> 1.3.4)
...@@ -1002,13 +993,14 @@ DEPENDENCIES ...@@ -1002,13 +993,14 @@ DEPENDENCIES
rack-attack (~> 4.3.1) rack-attack (~> 4.3.1)
rack-cors (~> 0.4.0) rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.2.1) rack-oauth2 (~> 1.2.1)
rails (= 4.2.5.2) rails (= 4.2.6)
rails-deprecated_sanitizer (~> 1.0.3) rails-deprecated_sanitizer (~> 1.0.3)
raphael-rails (~> 2.1.2) raphael-rails (~> 2.1.2)
rblineprof rblineprof
rdoc (~> 3.6) rdoc (~> 3.6)
recaptcha recaptcha
redcarpet (~> 3.3.3) redcarpet (~> 3.3.3)
redis (~> 3.2)
redis-namespace redis-namespace
redis-rails (~> 4.0.0) redis-rails (~> 4.0.0)
request_store (~> 1.3.0) request_store (~> 1.3.0)
...@@ -1032,7 +1024,7 @@ DEPENDENCIES ...@@ -1032,7 +1024,7 @@ DEPENDENCIES
shoulda-matchers (~> 2.8.0) shoulda-matchers (~> 2.8.0)
sidekiq (~> 4.0) sidekiq (~> 4.0)
sidekiq-cron (~> 0.4.0) sidekiq-cron (~> 0.4.0)
simplecov (~> 0.10.0) simplecov (~> 0.11.0)
sinatra (~> 1.4.4) sinatra (~> 1.4.4)
six (~> 0.2.0) six (~> 0.2.0)
slack-notifier (~> 1.2.0) slack-notifier (~> 1.2.0)
...@@ -1042,7 +1034,7 @@ DEPENDENCIES ...@@ -1042,7 +1034,7 @@ DEPENDENCIES
spring-commands-rspec (~> 1.0.4) spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.0.0) spring-commands-spinach (~> 1.0.0)
spring-commands-teaspoon (~> 0.0.2) spring-commands-teaspoon (~> 0.0.2)
sprockets (~> 3.3.5) sprockets (~> 3.6.0)
state_machines-activerecord (~> 0.3.0) state_machines-activerecord (~> 0.3.0)
task_list (~> 1.0.2) task_list (~> 1.0.2)
teaspoon (~> 1.1.0) teaspoon (~> 1.1.0)
......
...@@ -22,8 +22,19 @@ class @AwardsHandler ...@@ -22,8 +22,19 @@ class @AwardsHandler
emoji = $(this) emoji = $(this)
.find(".icon") .find(".icon")
.data "emoji" .data "emoji"
if emoji is "thumbsup" and awards_handler.didUserClickEmoji $(this), "thumbsdown"
awards_handler.addAward "thumbsdown"
else if emoji is "thumbsdown" and awards_handler.didUserClickEmoji $(this), "thumbsup"
awards_handler.addAward "thumbsup"
awards_handler.addAward emoji awards_handler.addAward emoji
didUserClickEmoji: (that, emoji) ->
if $(that).siblings("button:has([data-emoji=#{emoji}])").attr("data-original-title")
$(that).siblings("button:has([data-emoji=#{emoji}])").attr("data-original-title").indexOf('me') > -1
showEmojiMenu: -> showEmojiMenu: ->
if $(".emoji-menu").length if $(".emoji-menu").length
if $(".emoji-menu").is ".is-visible" if $(".emoji-menu").is ".is-visible"
...@@ -105,7 +116,7 @@ class @AwardsHandler ...@@ -105,7 +116,7 @@ class @AwardsHandler
if origTitle if origTitle
authors = origTitle.split(', ') authors = origTitle.split(', ')
authors.push("me") authors.push("me")
award_block.attr("title", authors.join(", ")) award_block.attr("data-original-title", authors.join(", "))
@resetTooltip(award_block) @resetTooltip(award_block)
resetTooltip: (award) -> resetTooltip: (award) ->
...@@ -122,7 +133,7 @@ class @AwardsHandler ...@@ -122,7 +133,7 @@ class @AwardsHandler
nodes = [] nodes = []
nodes.push( nodes.push(
"<button class='btn award-control js-emoji-btn has-tooltip active' title='me'>", "<button class='btn award-control js-emoji-btn has-tooltip active' data-original-title='me'>",
"<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>", "<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>",
"<span class='award-control-text js-counter'>1</span>", "<span class='award-control-text js-counter'>1</span>",
"</button>" "</button>"
......
class @Compare
constructor: (@opts) ->
@source_loading = $ ".js-source-loading"
@target_loading = $ ".js-target-loading"
$('.js-compare-dropdown').each (i, dropdown) =>
$dropdown = $(dropdown)
$dropdown.glDropdown(
selectable: true
fieldName: $dropdown.data 'field-name'
filterable: true
id: (obj, $el) ->
$el.data 'id'
toggleLabel: (obj, $el) ->
$el.text().trim()
clicked: (e, el) =>
if $dropdown.is '.js-target-branch'
@getTargetHtml()
else if $dropdown.is '.js-source-branch'
@getSourceHtml()
else if $dropdown.is '.js-target-project'
@getTargetProject()
)
@initialState()
initialState: ->
@getSourceHtml()
@getTargetHtml()
getTargetProject: ->
$.ajax(
url: @opts.targetProjectUrl
data:
target_project_id: $("input[name='merge_request[target_project_id]']").val()
beforeSend: ->
$('.mr_target_commit').empty()
success: (html) ->
$('.js-target-branch-dropdown .dropdown-content').html html
)
getSourceHtml: ->
@sendAjax(@opts.sourceBranchUrl, @source_loading, '.mr_source_commit',
ref: $("input[name='merge_request[source_branch]']").val()
)
getTargetHtml: ->
@sendAjax(@opts.targetBranchUrl, @target_loading, '.mr_target_commit',
target_project_id: $("input[name='merge_request[target_project_id]']").val()
ref: $("input[name='merge_request[target_branch]']").val()
)
sendAjax: (url, loading, target, data) ->
$target = $(target)
$.ajax(
url: url
data: data
beforeSend: ->
loading.show()
$target.empty()
success: (html) ->
loading.hide()
$target.html html
$('.js-timeago', $target).timeago()
)
...@@ -57,14 +57,30 @@ class GitLabDropdownFilter ...@@ -57,14 +57,30 @@ class GitLabDropdownFilter
filter: (search_text) -> filter: (search_text) ->
data = @options.data() data = @options.data()
results = data
if search_text isnt "" if data?
results = fuzzaldrinPlus.filter(data, search_text, results = data
key: @options.keys
)
@options.callback results if search_text isnt ''
results = fuzzaldrinPlus.filter(data, search_text,
key: @options.keys
)
@options.callback results
else
elements = @options.elements()
if search_text
elements.each ->
$el = $(@)
matches = fuzzaldrinPlus.match($el.text().trim(), search_text)
if matches.length
$el.show()
else
$el.hide()
else
elements.show()
class GitLabDropdownRemote class GitLabDropdownRemote
constructor: (@dataEndpoint, @options) -> constructor: (@dataEndpoint, @options) ->
...@@ -123,7 +139,7 @@ class GitLabDropdown ...@@ -123,7 +139,7 @@ class GitLabDropdown
if _.isString(@filterInput) if _.isString(@filterInput)
@filterInput = @getElement(@filterInput) @filterInput = @getElement(@filterInput)
search_fields = if @options.search then @options.search.fields else []; searchFields = if @options.search then @options.search.fields else [];
if @options.data if @options.data
# If data is an array # If data is an array
...@@ -147,7 +163,14 @@ class GitLabDropdown ...@@ -147,7 +163,14 @@ class GitLabDropdown
filterInputBlur: @filterInputBlur filterInputBlur: @filterInputBlur
remote: @options.filterRemote remote: @options.filterRemote
query: @options.data query: @options.data
keys: @options.search.fields keys: searchFields
elements: =>
selector = '.dropdown-content li:not(.divider)'
if @dropdown.find('.dropdown-toggle-page').length
selector = ".dropdown-page-one #{selector}"
return $(selector)
data: => data: =>
return @fullData return @fullData
callback: (data) => callback: (data) =>
...@@ -376,7 +399,7 @@ class GitLabDropdown ...@@ -376,7 +399,7 @@ class GitLabDropdown
# Toggle the dropdown label # Toggle the dropdown label
if @options.toggleLabel if @options.toggleLabel
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject) $(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject, el)
if value? if value?
if !field.length and fieldName if !field.length and fieldName
# Create hidden input for form # Create hidden input for form
......
...@@ -73,7 +73,8 @@ class @MergeRequestTabs ...@@ -73,7 +73,8 @@ class @MergeRequestTabs
@expandView() @expandView()
else if action == 'diffs' else if action == 'diffs'
@loadDiff($target.attr('href')) @loadDiff($target.attr('href'))
@shrinkView() if bp? and bp.getBreakpointSize() isnt 'lg'
@shrinkView()
else if action == 'builds' else if action == 'builds'
@loadBuilds($target.attr('href')) @loadBuilds($target.attr('href'))
@expandView() @expandView()
......
...@@ -15,6 +15,8 @@ class @MergeRequestWidget ...@@ -15,6 +15,8 @@ class @MergeRequestWidget
@pollCIStatus() @pollCIStatus()
notifyPermissions() notifyPermissions()
setOpts: (@opts) ->
mergeInProgress: (deleteSourceBranch = false)-> mergeInProgress: (deleteSourceBranch = false)->
$.ajax $.ajax
type: 'GET' type: 'GET'
...@@ -48,7 +50,7 @@ class @MergeRequestWidget ...@@ -48,7 +50,7 @@ class @MergeRequestWidget
@getCIStatus(true) @getCIStatus(true)
@readyForCICheck = false @readyForCICheck = false
), 5000 ), 10000
getCIStatus: (showNotification) -> getCIStatus: (showNotification) ->
_this = @ _this = @
...@@ -61,6 +63,10 @@ class @MergeRequestWidget ...@@ -61,6 +63,10 @@ class @MergeRequestWidget
@firstCICheck = false @firstCICheck = false
@opts.ci_status = data.status @opts.ci_status = data.status
if @opts.ci_status is ''
@opts.ci_status = data.status
return
if data.status isnt @opts.ci_status if data.status isnt @opts.ci_status
@showCIStatus data.status @showCIStatus data.status
if data.coverage if data.coverage
......
...@@ -85,15 +85,21 @@ class @MilestoneSelect ...@@ -85,15 +85,21 @@ class @MilestoneSelect
# display:block overrides the hide-collapse rule # display:block overrides the hide-collapse rule
$value.removeAttr('style') $value.removeAttr('style')
clicked: (selected) -> clicked: (selected) ->
page = $('body').data 'page'
isIssueIndex = page is 'projects:issues:index'
isMRIndex = page is page is 'projects:merge_requests:index'
if $dropdown.hasClass 'js-filter-bulk-update' if $dropdown.hasClass 'js-filter-bulk-update'
return return
if $dropdown.hasClass('js-filter-submit') if $dropdown.hasClass('js-filter-submit') and (isIssueIndex or isMRIndex)
if selected.name? if selected.name?
selectedMilestone = selected.name selectedMilestone = selected.name
else else
selectedMilestone = '' selectedMilestone = ''
Issues.filterResults $dropdown.closest('form') Issues.filterResults $dropdown.closest('form')
else if $dropdown.hasClass('js-filter-submit')
$dropdown.closest('form').submit()
else else
selected = $selectbox selected = $selectbox
.find('input[type="hidden"]') .find('input[type="hidden"]')
......
...@@ -4,6 +4,7 @@ expanded = 'page-sidebar-expanded' ...@@ -4,6 +4,7 @@ expanded = 'page-sidebar-expanded'
toggleSidebar = -> toggleSidebar = ->
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}") $('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
$('header').toggleClass("header-collapsed header-expanded") $('header').toggleClass("header-collapsed header-expanded")
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' }) $.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
setTimeout ( -> setTimeout ( ->
......
...@@ -10,10 +10,10 @@ class @Subscription ...@@ -10,10 +10,10 @@ class @Subscription
btn = $(event.currentTarget) btn = $(event.currentTarget)
action = btn.find('span').text() action = btn.find('span').text()
current_status = @subscription_status.attr('data-status') current_status = @subscription_status.attr('data-status')
btn.prop('disabled', true) btn.addClass('disabled')
$.post @url, => $.post @url, =>
btn.prop('disabled', false) btn.removeClass('disabled')
status = if current_status == 'subscribed' then 'unsubscribed' else 'subscribed' status = if current_status == 'subscribed' then 'unsubscribed' else 'subscribed'
@subscription_status.attr('data-status', status) @subscription_status.attr('data-status', status)
action = if status == 'subscribed' then 'Unsubscribe' else 'Subscribe' action = if status == 'subscribed' then 'Unsubscribe' else 'Subscribe'
......
...@@ -57,5 +57,10 @@ class @Todos ...@@ -57,5 +57,10 @@ class @Todos
$('.todos-pending .badge, .todos-pending-count').text data.count $('.todos-pending .badge, .todos-pending-count').text data.count
$('.todos-done .badge').text data.done_count $('.todos-done .badge').text data.done_count
goToTodoUrl: -> goToTodoUrl: (e)->
Turbolinks.visit($(this).data('url')) todoLink = $(this).data('url')
if e.metaKey
e.preventDefault()
window.open(todoLink,'_blank')
else
Turbolinks.visit(todoLink)
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
&:focus, &:focus,
&:active { &:active {
outline: none; outline: none;
background-color: $btn-active-gray;
@include box-shadow($gl-btn-active-background); @include box-shadow($gl-btn-active-background);
} }
} }
...@@ -27,7 +28,8 @@ ...@@ -27,7 +28,8 @@
color: $color; color: $color;
} }
&:active { &:active,
&.active {
@include box-shadow ($gl-btn-active-background); @include box-shadow ($gl-btn-active-background);
background-color: $dark; background-color: $dark;
...@@ -61,7 +63,7 @@ ...@@ -61,7 +63,7 @@
} }
@mixin btn-white { @mixin btn-white {
@include btn-color($white-light, $border-white-light, $white-normal, $border-white-normal, $white-dark, $border-white-dark, #313236); @include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-white-dark, $btn-white-active);
} }
.btn { .btn {
...@@ -218,3 +220,26 @@ ...@@ -218,3 +220,26 @@
margin-right: 5px; margin-right: 5px;
} }
} }
.btn-text-field {
width: 100%;
text-align: left;
padding: 6px 16px;
border-color: $border-color;
color: $btn-placeholder-gray;
background-color: $background-color;
&:hover,
&:active,
&:focus {
cursor: text;
box-shadow: none;
border-color: $border-color;
color: $btn-placeholder-gray;
background-color: $background-color;
}
}
.btn-file-option {
background: linear-gradient(180deg, $white-light 25%, $gray-light 100%);
}
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
.dropdown-title { .dropdown-title {
position: relative; position: relative;
padding: 0 0 15px; padding: 0 25px 15px;
margin: 0 10px 10px; margin: 0 10px 10px;
font-weight: 600; font-weight: 600;
line-height: 1; line-height: 1;
...@@ -275,7 +275,7 @@ ...@@ -275,7 +275,7 @@
} }
.dropdown-menu-close { .dropdown-menu-close {
right: 7px; right: 5px;
width: 20px; width: 20px;
height: 20px; height: 20px;
top: -1px; top: -1px;
......
...@@ -15,11 +15,13 @@ ...@@ -15,11 +15,13 @@
.file-title { .file-title {
position: relative; position: relative;
background: $background-color; background-color: $background-color;
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
margin: 0; margin: 0;
text-align: left; text-align: left;
padding: 10px $gl-padding; padding: 10px $gl-padding;
word-wrap: break-word;
border-radius: 3px 3px 0 0;
.file-actions { .file-actions {
float: right; float: right;
...@@ -48,7 +50,7 @@ ...@@ -48,7 +50,7 @@
} }
} }
a { a:not(.btn) {
color: $gl-dark-link-color; color: $gl-dark-link-color;
} }
......
...@@ -33,15 +33,10 @@ ...@@ -33,15 +33,10 @@
background: $color; background: $color;
} }
.complex-sidebar .nav-primary {
border-right: 1px solid lighten($color, 3%);
}
.sidebar-wrapper { .sidebar-wrapper {
background: $color-darker; background: $color-darker;
.sidebar-user { .sidebar-user {
border-top: 1px solid lighten($color, 3%);
background: $color-darker; background: $color-darker;
color: $color-light; color: $color-light;
...@@ -67,6 +62,7 @@ ...@@ -67,6 +62,7 @@
.count { .count {
color: $color-light; color: $color-light;
background: $color-dark;
} }
} }
......
...@@ -123,11 +123,11 @@ header { ...@@ -123,11 +123,11 @@ header {
} }
@mixin collapsed-header { @mixin collapsed-header {
margin-left: 40px; margin-left: $sidebar_collapsed_width;
} }
.header-collapsed { .header-collapsed {
margin-left: 40px; margin-left: $sidebar_collapsed_width;
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
@include collapsed-header; @include collapsed-header;
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
.md-preview-holder { .md-preview-holder {
min-height: 167px; min-height: 167px;
padding: 10px 0; padding: 10px 0;
overflow-x: auto;
} }
.markdown-area { .markdown-area {
......
...@@ -144,7 +144,7 @@ ...@@ -144,7 +144,7 @@
} }
a { a {
padding: 7px 12px; padding: 7px 15px;
font-size: $gl-font-size; font-size: $gl-font-size;
line-height: 24px; line-height: 24px;
color: $gray; color: $gray;
...@@ -169,12 +169,10 @@ ...@@ -169,12 +169,10 @@
} }
.count { .count {
&:before { float: right;
content: '('; background: #eee;
} padding: 0 8px;
&:after { @include border-radius(6px);
content: ')';
}
} }
&.back-link i { &.back-link i {
...@@ -193,27 +191,6 @@ ...@@ -193,27 +191,6 @@
} }
} }
.expand-nav a {
color: $gl-icon-color;
width: 60px;
position: fixed;
top: 0;
left: 0;
font-size: 20px;
background: #fff;
height: 59px;
text-align: center;
line-height: 59px;
border-bottom: 1px solid #eee;
transition-duration: .3s;
outline: none;
z-index: 100;
&:hover {
text-decoration: none;
}
}
.collapse-nav a { .collapse-nav a {
width: $sidebar_width; width: $sidebar_width;
position: fixed; position: fixed;
...@@ -233,12 +210,55 @@ ...@@ -233,12 +210,55 @@
} }
.page-sidebar-collapsed { .page-sidebar-collapsed {
padding-left: $sidebar_collapsed_width;
.sidebar-wrapper { .sidebar-wrapper {
display: none; width: $sidebar_collapsed_width;
.header-logo {
width: $sidebar_collapsed_width;
a {
padding-left: ($sidebar_collapsed_width - 36) / 2;
.gitlab-text-container {
display: none;
}
}
}
.nav-sidebar {
width: $sidebar_collapsed_width;
li {
width: auto;
a {
span {
display: none;
}
}
}
}
.collapse-nav a {
width: $sidebar_collapsed_width;
}
.sidebar-user {
padding-left: ($sidebar_collapsed_width - 36) / 2;
width: $sidebar_collapsed_width;
.username {
display: none;
}
}
} }
} }
.page-sidebar-expanded { .page-sidebar-expanded {
padding-left: $sidebar_collapsed_width;
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
padding-left: $sidebar_width; padding-left: $sidebar_width;
} }
...@@ -289,48 +309,3 @@ ...@@ -289,48 +309,3 @@
padding-right: $sidebar_collapsed_width; padding-right: $sidebar_collapsed_width;
} }
} }
.complex-sidebar {
display: inline-block;
.nav-primary {
width: 61px;
float: left;
height: 100vh;
.nav-sidebar {
width: 60px;
li a {
width: 60px;
span {
display: none;
}
}
}
}
.nav-secondary {
$nav-secondary-width: 168px;
float: left;
width: $nav-secondary-width;
.nav-sidebar {
width: $nav-secondary-width;
li {
width: $nav-secondary-width;
a {
width: $nav-secondary-width;
i {
display: none;
}
}
}
}
}
}
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
background: $row-hover; background: $row-hover;
} }
&:last-child {
border-bottom: none;
}
.avatar { .avatar {
margin-right: 15px; margin-right: 15px;
} }
......
...@@ -10,10 +10,10 @@ $gutter_inner_width: 258px; ...@@ -10,10 +10,10 @@ $gutter_inner_width: 258px;
/* /*
* UI elements * UI elements
*/ */
$border-color: #efeff1; $border-color: #e5e5e5;
$focus-border-color: #3aabf0; $focus-border-color: #3aabf0;
$table-border-color: #eef0f2; $table-border-color: #eef0f2;
$background-color: #faf9f9; $background-color: #fafafa;
/* /*
* Text * Text
...@@ -81,7 +81,7 @@ $provider-btn-not-active-color: #4688f1; ...@@ -81,7 +81,7 @@ $provider-btn-not-active-color: #4688f1;
$white-light: #fff; $white-light: #fff;
$white-normal: #ededed; $white-normal: #ededed;
$white-dark: #ededed; $white-dark: #ececec;
$gray-light: #faf9f9; $gray-light: #faf9f9;
$gray-normal: #f5f5f5; $gray-normal: #f5f5f5;
...@@ -108,6 +108,8 @@ $red-light: #e52c5a; ...@@ -108,6 +108,8 @@ $red-light: #e52c5a;
$red-normal: #d22852; $red-normal: #d22852;
$red-dark: darken($red-normal, 5%); $red-dark: darken($red-normal, 5%);
$black-transparent: rgba(0, 0, 0, 0.3);
$border-white-light: #f1f2f4; $border-white-light: #f1f2f4;
$border-white-normal: #d6dae2; $border-white-normal: #d6dae2;
$border-white-dark: #c6cacf; $border-white-dark: #c6cacf;
...@@ -150,15 +152,22 @@ $gl-success: $green-normal; ...@@ -150,15 +152,22 @@ $gl-success: $green-normal;
$gl-info: $blue-normal; $gl-info: $blue-normal;
$gl-warning: $orange-normal; $gl-warning: $orange-normal;
$gl-danger: $red-normal; $gl-danger: $red-normal;
$gl-btn-active-background: rgba(0, 0, 0, 0.12); $gl-btn-active-background: rgba(0, 0, 0, 0.16);
$gl-btn-active-gradient: inset 0 0 4px $gl-btn-active-background; $gl-btn-active-gradient: inset 0 2px 3px $gl-btn-active-background;
/* /*
* Commit Diff Colors * Commit Diff Colors
*/ */
$added: #63c363; $added: #63c363;
$deleted: #f77; $deleted: #f77;
$line-added: #ecfdf0;
$line-added-dark: #c7f0d2;
$line-removed: #fbe9eb;
$line-removed-dark: #fac5cd;
$line-number-old: #f9d7dc;
$line-number-new: #ddfbe6;
$match-line: #fafafa;
$table-border-gray: #f0f0f0;
/* /*
* Fonts * Fonts
*/ */
...@@ -191,6 +200,13 @@ $dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 15%); ...@@ -191,6 +200,13 @@ $dropdown-toggle-hover-border-color: darken($dropdown-toggle-border-color, 15%);
$dropdown-toggle-icon-color: #c4c4c4; $dropdown-toggle-icon-color: #c4c4c4;
$dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color; $dropdown-toggle-hover-icon-color: $dropdown-toggle-hover-border-color;
/*
* Buttons
*/
$btn-active-gray: #ececec;
$btn-placeholder-gray: #c7c7c7;
$btn-white-active: #848484;
/* /*
* Award emoji * Award emoji
*/ */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
} }
.diff-line-num, .diff-line-num a { .diff-line-num, .diff-line-num a {
color: rgba(0, 0, 0, 0.3); color: $black-transparent;
} }
// Code itself // Code itself
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
} }
.line_content.match { .line_content.match {
color: rgba(0, 0, 0, 0.3); color: $black-transparent;
background: rgba(255, 255, 255, 0.4); background: rgba(255, 255, 255, 0.4);
} }
} }
......
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
} }
.diff-line-num, .diff-line-num a { .diff-line-num, .diff-line-num a {
color: rgba(0, 0, 0, 0.3); color: $black-transparent;
} }
// Code itself // Code itself
pre.code, .diff-line-num { pre.code, .diff-line-num {
border-color: $border-color; border-color: $table-border-gray;
} }
&, pre.code, .line_holder .line_content { &, pre.code, .line_holder .line_content {
...@@ -23,36 +23,36 @@ ...@@ -23,36 +23,36 @@
.line_holder { .line_holder {
.diff-line-num { .diff-line-num {
&.old { &.old {
background: #fdd; background-color: $line-number-old;
border-color: #f1c0c0; border-color: $line-removed-dark;
} }
&.new { &.new {
background: #dbffdb; background-color: $line-number-new;
border-color: #c1e9c1; border-color: $line-added-dark;
} }
} }
.line_content { .line_content {
&.old { &.old {
background: #ffecec; background: $line-removed;
span.idiff { span.idiff {
background-color: #f8cbcb; background-color: $line-removed-dark;
} }
} }
&.new { &.new {
background: #eaffea; background-color: $line-added;
span.idiff { span.idiff {
background-color: #a6f3a6; background-color: $line-added-dark;
} }
} }
&.match { &.match {
color: rgba(0, 0, 0, 0.3); color: $black-transparent;
background: #fafafa; background: $match-line;
} }
} }
} }
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
margin-top: 10px; margin-top: 10px;
word-break: normal;
white-space: pre-wrap;
} }
.commit-info-row { .commit-info-row {
......
...@@ -47,6 +47,7 @@ li.commit { ...@@ -47,6 +47,7 @@ li.commit {
.commit_short_id { .commit_short_id {
min-width: 65px; min-width: 65px;
color: $gl-dark-link-color;
font-family: $monospace_font; font-family: $monospace_font;
} }
...@@ -88,6 +89,10 @@ li.commit { ...@@ -88,6 +89,10 @@ li.commit {
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
a {
color: $gl-dark-link-color;
}
} }
.commit-row-info { .commit-row-info {
......
...@@ -33,8 +33,12 @@ ...@@ -33,8 +33,12 @@
.description { .description {
margin-top: 6px; margin-top: 6px;
p:last-child { p {
margin-bottom: 0; overflow-x: auto;
&:last-child {
margin-bottom: 0;
}
} }
} }
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
.diff-file { .diff-file {
border: 1px solid $border-color; border: 1px solid $border-color;
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
border-radius: 3px;
.diff-header { .diff-header {
position: relative; position: relative;
...@@ -10,6 +11,7 @@ ...@@ -10,6 +11,7 @@
padding: 10px 16px; padding: 10px 16px;
color: #555; color: #555;
z-index: 10; z-index: 10;
border-radius: 3px 3px 0 0;
.diff-title { .diff-title {
font-family: $monospace_font; font-family: $monospace_font;
...@@ -31,6 +33,7 @@ ...@@ -31,6 +33,7 @@
overflow-y: hidden; overflow-y: hidden;
background: #fff; background: #fff;
color: #333; color: #333;
border-radius: 0 0 3px 3px;
.unfold { .unfold {
cursor: pointer; cursor: pointer;
...@@ -59,9 +62,14 @@ ...@@ -59,9 +62,14 @@
border-collapse: separate; border-collapse: separate;
margin: 0; margin: 0;
padding: 0; padding: 0;
.line_holder td { .line_holder td {
line-height: $code_line_height; line-height: $code_line_height;
font-size: $code_font_size; font-size: $code_font_size;
span {
white-space: pre;
}
} }
} }
...@@ -104,6 +112,10 @@ ...@@ -104,6 +112,10 @@
display: table-cell; display: table-cell;
} }
} }
.text-file.diff-wrap-lines table .line_holder td span {
white-space: pre-wrap;
}
} }
.image { .image {
background: #ddd; background: #ddd;
...@@ -316,6 +328,16 @@ ...@@ -316,6 +328,16 @@
float: right; float: right;
} }
.diffs {
.content-block {
border-bottom: none;
}
}
.files-changed {
border-bottom: none;
}
// Mobile // Mobile
@media (max-width: 480px) { @media (max-width: 480px) {
.diff-title { .diff-title {
......
...@@ -59,6 +59,9 @@ ...@@ -59,6 +59,9 @@
position: relative; position: relative;
overflow-y: auto; overflow-y: auto;
padding: 15px; padding: 15px;
.form-actions {
margin: -$gl-padding+1;
}
} }
body.modal-open { body.modal-open {
......
...@@ -49,6 +49,15 @@ ...@@ -49,6 +49,15 @@
} }
.label-row { .label-row {
.label-name {
display: inline-block;
width: 200px;
@media (max-width: $screen-xs-min) {
display: block;
}
}
.label { .label {
padding: 9px; padding: 9px;
font-size: 14px; font-size: 14px;
...@@ -69,3 +78,52 @@ ...@@ -69,3 +78,52 @@
background-color: $gl-danger; background-color: $gl-danger;
color: $white-light; color: $white-light;
} }
.manage-labels-list {
.prepend-left-10 {
display: inline-block;
width: 40%;
vertical-align: middle;
@media (max-width: $screen-xs-min) {
display: block;
width: 100%;
margin-left: 0;
padding: 10px 0;
}
}
.pull-info-right {
float: right;
@media (max-width: $screen-xs-min) {
float: none;
}
.action-buttons {
border-color: transparent;
padding: 6px;
color: $gl-text-color;
&.subscribe-button {
padding-left: 0;
}
}
i {
color: $gl-text-color;
}
.append-right-20 {
a {
color: $gl-text-color;
}
@media (max-width: $screen-xs-min) {
display: block;
margin-bottom: 10px;
}
}
}
}
...@@ -123,6 +123,8 @@ ...@@ -123,6 +123,8 @@
.mr_source_commit, .mr_source_commit,
.mr_target_commit { .mr_target_commit {
margin-bottom: 0;
.commit { .commit {
margin: 0; margin: 0;
padding: 2px 0; padding: 2px 0;
...@@ -174,10 +176,6 @@ ...@@ -174,10 +176,6 @@
display: none; display: none;
} }
.merge-request-form .select2-container {
width: 250px !important;
}
#modal_merge_info .modal-dialog { #modal_merge_info .modal-dialog {
width: 600px; width: 600px;
...@@ -200,3 +198,76 @@ ...@@ -200,3 +198,76 @@
overflow-x: scroll; overflow-x: scroll;
} }
} }
.panel-new-merge-request {
.panel-heading {
padding: 5px 10px;
font-weight: 600;
line-height: 25px;
}
.panel-body {
padding: 10px 5px;
}
.panel-footer {
padding: 5px 10px;
}
.commit {
.commit-row-title {
margin-bottom: 4px;
}
.avatar {
width: 20px;
height: 20px;
margin-right: 5px;
}
.commit-row-info {
line-height: 20px;
}
}
.btn-clipboard {
margin-right: 5px;
padding: 0;
background: transparent;
}
.ci-status-link {
margin-right: 5px;
}
}
.merge-request-select {
padding-left: 5px;
padding-right: 5px;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
@media (min-width: $screen-sm-min) {
float: left;
width: 50%;
margin-bottom: 0;
}
.dropdown-menu-toggle {
width: 100%;
}
.dropdown-menu {
left: 5px;
right: 5px;
width: auto;
}
}
.issuable-form-select-holder {
display: inline-block;
width: 250px;
}
/** /**
* Note Form * Note Form
*/ */
.reply-btn { .comment-btn {
@extend .btn-primary; @extend .btn-create;
margin: 10px $gl-padding;
} }
.diff-file .diff-content { .diff-file .diff-content {
tr.line_holder:hover > td .line_note_link { tr.line_holder:hover > td .line_note_link {
opacity: 1.0; opacity: 1.0;
...@@ -113,13 +113,12 @@ ...@@ -113,13 +113,12 @@
.discussion-body, .discussion-body,
.diff-file { .diff-file {
.notes .note { .notes .note {
border-color: #ddd;
padding: 10px 15px; padding: 10px 15px;
} }
.discussion-reply-holder { .discussion-reply-holder {
background: $background-color; background-color: $white-light;
border-top: 1px solid $border-color; padding: 10px 16px;
} }
} }
......
...@@ -58,6 +58,7 @@ ul.notes { ...@@ -58,6 +58,7 @@ ul.notes {
.note { .note {
display: block; display: block;
position: relative; position: relative;
border-bottom: 1px solid $table-border-gray;
&.is-editting { &.is-editting {
.note-header, .note-header,
...@@ -82,7 +83,7 @@ ul.notes { ...@@ -82,7 +83,7 @@ ul.notes {
// On diffs code should wrap nicely and not overflow // On diffs code should wrap nicely and not overflow
pre { pre {
code { code {
white-space: pre-wrap; white-space: pre;
} }
} }
...@@ -117,9 +118,6 @@ ul.notes { ...@@ -117,9 +118,6 @@ ul.notes {
padding-bottom: 3px; padding-bottom: 3px;
} }
&:last-child {
border-bottom: 1px solid $border-color;
}
} }
} }
...@@ -137,14 +135,14 @@ ul.notes { ...@@ -137,14 +135,14 @@ ul.notes {
font-family: $regular_font; font-family: $regular_font;
td { td {
border: 1px solid #ddd; border: 1px solid $table-border-gray;
border-left: none; border-left: none;
&.notes_line { &.notes_line {
vertical-align: middle; vertical-align: middle;
text-align: center; text-align: center;
padding: 10px 0; padding: 10px 0;
background: #fff; background: $background-color;
color: $text-color; color: $text-color;
} }
&.notes_line2 { &.notes_line2 {
...@@ -175,9 +173,6 @@ ul.notes { ...@@ -175,9 +173,6 @@ ul.notes {
} }
} }
.author_link {
font-weight: 600;
}
} }
.note-headline-light, .note-headline-light,
...@@ -203,14 +198,26 @@ ul.notes { ...@@ -203,14 +198,26 @@ ul.notes {
line-height: 24px; line-height: 24px;
.fa { .fa {
color: $notes-action-color;
position: relative; position: relative;
top: 1px; top: 1px;
font-size: 17px; font-size: 17px;
} }
.fa-trash-o { &.js-note-delete {
top: 0; i {
font-size: 16px; &:hover {
color: $gl-text-red;
}
}
}
&.js-note-edit {
i {
&:hover {
color: $gl-link-color;
}
}
} }
} }
......
...@@ -5,7 +5,7 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -5,7 +5,7 @@ class Admin::ProjectsController < Admin::ApplicationController
def index def index
@projects = Project.all @projects = Project.all
@projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present? @projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present?
@projects = @projects.where("visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present? @projects = @projects.where("projects.visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
@projects = @projects.with_push if params[:with_push].present? @projects = @projects.with_push if params[:with_push].present?
@projects = @projects.abandoned if params[:abandoned].present? @projects = @projects.abandoned if params[:abandoned].present?
@projects = @projects.non_archived unless params[:with_archived].present? @projects = @projects.non_archived unless params[:with_archived].present?
......
...@@ -47,6 +47,16 @@ class ApplicationController < ActionController::Base ...@@ -47,6 +47,16 @@ class ApplicationController < ActionController::Base
email: current_user.email, email: current_user.email,
username: current_user.username, username: current_user.username,
) )
Raven.tags_context(program: sentry_program_context)
end
end
def sentry_program_context
if Sidekiq.server?
'sidekiq'
else
'rails'
end end
end end
......
...@@ -18,14 +18,14 @@ class Groups::MilestonesController < Groups::ApplicationController ...@@ -18,14 +18,14 @@ class Groups::MilestonesController < Groups::ApplicationController
end end
def create def create
project_ids = params[:milestone][:project_ids] project_ids = params[:milestone][:project_ids].reject(&:blank?)
title = milestone_params[:title] title = milestone_params[:title]
@projects.where(id: project_ids).each do |project| if create_milestones(project_ids)
Milestones::CreateService.new(project, current_user, milestone_params).execute redirect_to milestone_path(title)
else
render_new_with_error(project_ids.empty?)
end end
redirect_to milestone_path(title)
end end
def show def show
...@@ -41,6 +41,27 @@ class Groups::MilestonesController < Groups::ApplicationController ...@@ -41,6 +41,27 @@ class Groups::MilestonesController < Groups::ApplicationController
private private
def create_milestones(project_ids)
return false unless project_ids.present?
ActiveRecord::Base.transaction do
@projects.where(id: project_ids).each do |project|
Milestones::CreateService.new(project, current_user, milestone_params).execute
end
end
true
rescue ActiveRecord::ActiveRecordError => e
flash.now[:alert] = "An error occurred while creating the milestone: #{e.message}"
false
end
def render_new_with_error(empty_project_ids)
@milestone = Milestone.new(milestone_params)
@milestone.errors.add(:project_id, "Please select at least one project.") if empty_project_ids
render :new
end
def authorize_admin_milestones! def authorize_admin_milestones!
return render_404 unless can?(current_user, :admin_milestones, group) return render_404 unless can?(current_user, :admin_milestones, group)
end end
......
...@@ -55,7 +55,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -55,7 +55,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end end
else else
saml_user = Gitlab::Saml::User.new(oauth) saml_user = Gitlab::Saml::User.new(oauth)
saml_user.save saml_user.save if saml_user.changed?
@user = saml_user.gl_user @user = saml_user.gl_user
continue_login_process continue_login_process
......
...@@ -68,7 +68,9 @@ class Projects::ApplicationController < ApplicationController ...@@ -68,7 +68,9 @@ class Projects::ApplicationController < ApplicationController
end end
def require_non_empty_project def require_non_empty_project
redirect_to namespace_project_path(@project.namespace, @project) if @project.empty_repo? # Be sure to return status code 303 to avoid a double DELETE:
# http://api.rubyonrails.org/classes/ActionController/Redirecting.html
redirect_to namespace_project_path(@project.namespace, @project), status: 303 if @project.empty_repo?
end end
def require_branch_head def require_branch_head
......
class Projects::BadgesController < Projects::ApplicationController class Projects::BadgesController < Projects::ApplicationController
before_action :no_cache_headers layout 'project_settings'
before_action :authorize_admin_project!, only: [:index]
before_action :no_cache_headers, except: [:index]
def index
@ref = params[:ref] || @project.default_branch || 'master'
@build_badge = Gitlab::Badge::Build.new(@project, @ref)
end
def build def build
badge = Gitlab::Badge::Build.new(project, params[:ref]) badge = Gitlab::Badge::Build.new(project, params[:ref])
......
...@@ -48,7 +48,7 @@ class Projects::BranchesController < Projects::ApplicationController ...@@ -48,7 +48,7 @@ class Projects::BranchesController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
redirect_to namespace_project_branches_path(@project.namespace, redirect_to namespace_project_branches_path(@project.namespace,
@project) @project), status: 303
end end
format.js { render status: status[:return_code] } format.js { render status: status[:return_code] }
end end
......
...@@ -207,20 +207,20 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -207,20 +207,20 @@ class Projects::MergeRequestsController < Projects::ApplicationController
#This is always source #This is always source
@source_project = @merge_request.nil? ? @project : @merge_request.source_project @source_project = @merge_request.nil? ? @project : @merge_request.source_project
@commit = @repository.commit(params[:ref]) if params[:ref].present? @commit = @repository.commit(params[:ref]) if params[:ref].present?
render layout: false
end end
def branch_to def branch_to
@target_project = selected_target_project @target_project = selected_target_project
@commit = @target_project.commit(params[:ref]) if params[:ref].present? @commit = @target_project.commit(params[:ref]) if params[:ref].present?
render layout: false
end end
def update_branches def update_branches
@target_project = selected_target_project @target_project = selected_target_project
@target_branches = @target_project.repository.branch_names @target_branches = @target_project.repository.branch_names
respond_to do |format| render layout: false
format.js
end
end end
def ci_status def ci_status
......
...@@ -24,6 +24,8 @@ class Projects::RefsController < Projects::ApplicationController ...@@ -24,6 +24,8 @@ class Projects::RefsController < Projects::ApplicationController
namespace_project_find_file_path(@project.namespace, @project, @id) namespace_project_find_file_path(@project.namespace, @project, @id)
when "graphs_commits" when "graphs_commits"
commits_namespace_project_graph_path(@project.namespace, @project, @id) commits_namespace_project_graph_path(@project.namespace, @project, @id)
when "badges"
namespace_project_badges_path(@project.namespace, @project, ref: @id)
else else
namespace_project_commits_path(@project.namespace, @project, @id) namespace_project_commits_path(@project.namespace, @project, @id)
end end
......
...@@ -88,6 +88,20 @@ class Projects::WikisController < Projects::ApplicationController ...@@ -88,6 +88,20 @@ class Projects::WikisController < Projects::ApplicationController
) )
end end
def markdown_preview
text = params[:text]
ext = Gitlab::ReferenceExtractor.new(@project, current_user, current_user)
ext.analyze(text)
render json: {
body: view_context.markdown(text, pipeline: :wiki, project_wiki: @project_wiki),
references: {
users: ext.users.map(&:username)
}
}
end
def git_access def git_access
end end
......
...@@ -5,7 +5,8 @@ class SessionsController < Devise::SessionsController ...@@ -5,7 +5,8 @@ class SessionsController < Devise::SessionsController
skip_before_action :check_2fa_requirement, only: [:destroy] skip_before_action :check_2fa_requirement, only: [:destroy]
prepend_before_action :check_initial_setup, only: [:new] prepend_before_action :check_initial_setup, only: [:new]
prepend_before_action :authenticate_with_two_factor, only: [:create] prepend_before_action :authenticate_with_two_factor,
if: :two_factor_enabled?, only: [:create]
prepend_before_action :store_redirect_path, only: [:new] prepend_before_action :store_redirect_path, only: [:new]
before_action :auto_sign_in_with_provider, only: [:new] before_action :auto_sign_in_with_provider, only: [:new]
...@@ -56,10 +57,10 @@ class SessionsController < Devise::SessionsController ...@@ -56,10 +57,10 @@ class SessionsController < Devise::SessionsController
end end
def find_user def find_user
if user_params[:login] if session[:otp_user_id]
User.by_login(user_params[:login])
elsif user_params[:otp_attempt] && session[:otp_user_id]
User.find(session[:otp_user_id]) User.find(session[:otp_user_id])
elsif user_params[:login]
User.by_login(user_params[:login])
end end
end end
...@@ -83,11 +84,13 @@ class SessionsController < Devise::SessionsController ...@@ -83,11 +84,13 @@ class SessionsController < Devise::SessionsController
end end
end end
def two_factor_enabled?
find_user.try(:two_factor_enabled?)
end
def authenticate_with_two_factor def authenticate_with_two_factor
user = self.resource = find_user user = self.resource = find_user
return unless user && user.two_factor_enabled?
if user_params[:otp_attempt].present? && session[:otp_user_id] if user_params[:otp_attempt].present? && session[:otp_user_id]
if valid_otp_attempt?(user) if valid_otp_attempt?(user)
# Remove any lingering user data from login # Remove any lingering user data from login
......
...@@ -27,9 +27,9 @@ module BlobHelper ...@@ -27,9 +27,9 @@ module BlobHelper
link_opts) link_opts)
if !on_top_of_branch?(project, ref) if !on_top_of_branch?(project, ref)
button_tag "Edit", class: "btn btn-default disabled has-tooltip", title: "You can only edit files when you are on a branch", data: { container: 'body' } button_tag "Edit", class: "btn disabled has-tooltip btn-file-option", title: "You can only edit files when you are on a branch", data: { container: 'body' }
elsif can_edit_blob?(blob, project, ref) elsif can_edit_blob?(blob, project, ref)
link_to "Edit", edit_path, class: 'btn' link_to "Edit", edit_path, class: 'btn btn-file-option'
elsif can?(current_user, :fork_project, project) elsif can?(current_user, :fork_project, project)
continue_params = { continue_params = {
to: edit_path, to: edit_path,
...@@ -38,7 +38,7 @@ module BlobHelper ...@@ -38,7 +38,7 @@ module BlobHelper
} }
fork_path = namespace_project_forks_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params) fork_path = namespace_project_forks_path(project.namespace, project, namespace_key: current_user.namespace.id, continue: continue_params)
link_to "Edit", fork_path, class: 'btn', method: :post link_to "Edit", fork_path, class: 'btn btn-file-option', method: :post
end end
end end
......
...@@ -28,7 +28,7 @@ module CommitsHelper ...@@ -28,7 +28,7 @@ module CommitsHelper
def commit_to_html(commit, project, inline = true) def commit_to_html(commit, project, inline = true)
template = inline ? "inline_commit" : "commit" template = inline ? "inline_commit" : "commit"
escape_javascript(render "projects/commits/#{template}", commit: commit, project: project) unless commit.nil? render "projects/commits/#{template}", commit: commit, project: project unless commit.nil?
end end
# Breadcrumb links for a Project and, if applicable, a tree path # Breadcrumb links for a Project and, if applicable, a tree path
...@@ -117,7 +117,7 @@ module CommitsHelper ...@@ -117,7 +117,7 @@ module CommitsHelper
end end
end end
link_to( link_to(
"Browse Files »", "Browse Files",
namespace_project_tree_path(project.namespace, project, commit), namespace_project_tree_path(project.namespace, project, commit),
class: "pull-right" class: "pull-right"
) )
...@@ -197,7 +197,7 @@ module CommitsHelper ...@@ -197,7 +197,7 @@ module CommitsHelper
link_to( link_to(
namespace_project_blob_path(project.namespace, project, namespace_project_blob_path(project.namespace, project,
tree_join(commit_sha, diff.new_path)), tree_join(commit_sha, diff.new_path)),
class: 'btn view-file js-view-file' class: 'btn view-file js-view-file btn-file-option'
) do ) do
raw('View file @') + content_tag(:span, commit_sha[0..6], raw('View file @') + content_tag(:span, commit_sha[0..6],
class: 'commit-short-id') class: 'commit-short-id')
......
module FormHelper
def form_errors(model)
return unless model.errors.any?
pluralized = 'error'.pluralize(model.errors.count)
headline = "The form contains the following #{pluralized}:"
content_tag(:div, class: 'alert alert-danger', id: 'error_explanation') do
content_tag(:h4, headline) <<
content_tag(:ul) do
model.errors.full_messages.
map { |msg| content_tag(:li, msg) }.
join.
html_safe
end
end
end
end
...@@ -116,29 +116,6 @@ module GitlabMarkdownHelper ...@@ -116,29 +116,6 @@ module GitlabMarkdownHelper
end end
end end
MARKDOWN_TIPS = [
"End a line with two or more spaces for a line-break, or soft-return",
"Inline code can be denoted by `surrounding it with backticks`",
"Blocks of code can be denoted by three backticks ``` or four leading spaces",
"Emoji can be added by :emoji_name:, for example :thumbsup:",
"Notify other participants using @user_name",
"Notify a specific group using @group_name",
"Notify the entire team using @all",
"Reference an issue using a hash, for example issue #123",
"Reference a merge request using an exclamation point, for example MR !123",
"Italicize words or phrases using *asterisks* or _underscores_",
"Bold words or phrases using **double asterisks** or __double underscores__",
"Strikethrough words or phrases using ~~two tildes~~",
"Make a bulleted list using + pluses, - minuses, or * asterisks",
"Denote blockquotes using > at the beginning of a line",
"Make a horizontal line using three or more hyphens ---, asterisks ***, or underscores ___"
].freeze
# Returns a random markdown tip for use as a textarea placeholder
def random_markdown_tip
MARKDOWN_TIPS.sample
end
private private
# Return +text+, truncated to +max_chars+ characters, excluding any HTML # Return +text+, truncated to +max_chars+ characters, excluding any HTML
......
...@@ -115,17 +115,32 @@ module IssuesHelper ...@@ -115,17 +115,32 @@ module IssuesHelper
icon('eye-slash') if issue.confidential? icon('eye-slash') if issue.confidential?
end end
def emoji_icon(name, unicode = nil, aliases = []) def emoji_icon(name, unicode = nil, aliases = [], sprite: true)
unicode ||= Emoji.emoji_filename(name) rescue "" unicode ||= Emoji.emoji_filename(name) rescue ""
content_tag :div, "", data = {
class: "icon emoji-icon emoji-#{unicode}", aliases: aliases.join(" "),
title: name, emoji: name,
data: { unicode_name: unicode
aliases: aliases.join(' '), }
emoji: name,
unicode_name: unicode if sprite
} # Emoji icons for the emoji menu, these use a spritesheet.
content_tag :div, "",
class: "icon emoji-icon emoji-#{unicode}",
title: name,
data: data
else
# Emoji icons displayed separately, used for the awards already given
# to an issue or merge request.
content_tag :img, "",
class: "icon emoji",
title: name,
height: "20px",
width: "20px",
src: url_to_image("#{unicode}.png"),
data: data
end
end end
def emoji_author_list(notes, current_user) def emoji_author_list(notes, current_user)
......
...@@ -69,10 +69,7 @@ module NotesHelper ...@@ -69,10 +69,7 @@ module NotesHelper
line_type: line_type line_type: line_type
} }
button_tag class: 'btn btn-nr reply-btn js-discussion-reply-button', button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
data: data, title: 'Add a reply' do data: data, title: 'Add a reply'
link_text = icon('comment')
link_text << ' Reply'
end
end end
end end
...@@ -331,6 +331,8 @@ class Repository ...@@ -331,6 +331,8 @@ class Repository
# Runs code after a repository has been created. # Runs code after a repository has been created.
def after_create def after_create
expire_exists_cache expire_exists_cache
expire_root_ref_cache
expire_emptiness_caches
end end
# Runs code just before a repository is deleted. # Runs code just before a repository is deleted.
......
...@@ -55,15 +55,15 @@ class GitPushService < BaseService ...@@ -55,15 +55,15 @@ class GitPushService < BaseService
end end
def update_main_language def update_main_language
# Performance can be bad so for now only check main_language once
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/14937
return if @project.main_language.present?
return unless is_default_branch? return unless is_default_branch?
return unless push_to_new_branch? || push_to_existing_branch? return unless push_to_new_branch? || push_to_existing_branch?
current_language = @project.repository.main_language current_language = @project.repository.main_language
@project.update_attributes(main_language: current_language)
unless current_language == @project.main_language
return @project.update_attributes(main_language: current_language)
end
true true
end end
......
...@@ -3,7 +3,7 @@ module Milestones ...@@ -3,7 +3,7 @@ module Milestones
def execute def execute
milestone = project.milestones.new(params) milestone = project.milestones.new(params)
if milestone.save if milestone.save!
event_service.open_milestone(milestone, current_user) event_service.open_milestone(milestone, current_user)
end end
......
...@@ -3,11 +3,9 @@ ...@@ -3,11 +3,9 @@
%p Please use this form to report users who create spam issues, comments or behave inappropriately. %p Please use this form to report users who create spam issues, comments or behave inappropriately.
%hr %hr
= form_for @abuse_report, html: { class: 'form-horizontal js-quick-submit js-requires-input'} do |f| = form_for @abuse_report, html: { class: 'form-horizontal js-quick-submit js-requires-input'} do |f|
= form_errors(@abuse_report)
= f.hidden_field :user_id = f.hidden_field :user_id
- if @abuse_report.errors.any?
.alert.alert-danger
- @abuse_report.errors.full_messages.each do |msg|
%p= msg
.form-group .form-group
= f.label :user_id, class: 'control-label' = f.label :user_id, class: 'control-label'
.col-sm-10 .col-sm-10
......
= form_for @appearance, url: admin_appearances_path, html: { class: 'form-horizontal'} do |f| = form_for @appearance, url: admin_appearances_path, html: { class: 'form-horizontal'} do |f|
- if @appearance.errors.any? = form_errors(@appearance)
.alert.alert-danger
- @appearance.errors.full_messages.each do |msg|
%p= msg
%fieldset.sign-in %fieldset.sign-in
%legend %legend
......
= form_for @application_setting, url: admin_application_settings_path, html: { class: 'form-horizontal fieldset-form' } do |f| = form_for @application_setting, url: admin_application_settings_path, html: { class: 'form-horizontal fieldset-form' } do |f|
- if @application_setting.errors.any? = form_errors(@application_setting)
#error_explanation
.alert.alert-danger
- @application_setting.errors.full_messages.each do |msg|
%p= msg
%fieldset %fieldset
%legend Visibility and Access Controls %legend Visibility and Access Controls
......
= form_for [:admin, @application], url: @url, html: {class: 'form-horizontal', role: 'form'} do |f| = form_for [:admin, @application], url: @url, html: {class: 'form-horizontal', role: 'form'} do |f|
- if application.errors.any? = form_errors(application)
.alert.alert-danger
%button{ type: "button", class: "close", "data-dismiss" => "alert"} &times;
- application.errors.full_messages.each do |msg|
%p= msg
= content_tag :div, class: 'form-group' do = content_tag :div, class: 'form-group' do
= f.label :name, class: 'col-sm-2 control-label' = f.label :name, class: 'col-sm-2 control-label'
.col-sm-10 .col-sm-10
......
...@@ -4,10 +4,8 @@ ...@@ -4,10 +4,8 @@
= render_broadcast_message(@broadcast_message.message.presence || "Your message here") = render_broadcast_message(@broadcast_message.message.presence || "Your message here")
= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-quick-submit js-requires-input'} do |f| = form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-quick-submit js-requires-input'} do |f|
-if @broadcast_message.errors.any? = form_errors(@broadcast_message)
.alert.alert-danger
- @broadcast_message.errors.full_messages.each do |msg|
%p= msg
.form-group .form-group
= f.label :message, class: 'control-label' = f.label :message, class: 'control-label'
.col-sm-10 .col-sm-10
......
...@@ -4,11 +4,7 @@ ...@@ -4,11 +4,7 @@
%div %div
= form_for [:admin, @deploy_key], html: { class: 'deploy-key-form form-horizontal' } do |f| = form_for [:admin, @deploy_key], html: { class: 'deploy-key-form form-horizontal' } do |f|
-if @deploy_key.errors.any? = form_errors(@deploy_key)
.alert.alert-danger
%ul
- @deploy_key.errors.full_messages.each do |msg|
%li= msg
.form-group .form-group
= f.label :title, class: "control-label" = f.label :title, class: "control-label"
......
= form_for [:admin, @group], html: { class: "form-horizontal" } do |f| = form_for [:admin, @group], html: { class: "form-horizontal" } do |f|
- if @group.errors.any? = form_errors(@group)
.alert.alert-danger
%span= @group.errors.full_messages.first
= render 'shared/group_form', f: f = render 'shared/group_form', f: f
.form-group.group-description-holder .form-group.group-description-holder
......
...@@ -10,10 +10,8 @@ ...@@ -10,10 +10,8 @@
= form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-horizontal' } do |f| = form_for @hook, as: :hook, url: admin_hooks_path, html: { class: 'form-horizontal' } do |f|
-if @hook.errors.any? = form_errors(@hook)
.alert.alert-danger
- @hook.errors.full_messages.each do |msg|
%p= msg
.form-group .form-group
= f.label :url, "URL:", class: 'control-label' = f.label :url, "URL:", class: 'control-label'
.col-sm-10 .col-sm-10
......
= form_for [:admin, @user, @identity], html: { class: 'form-horizontal fieldset-form' } do |f| = form_for [:admin, @user, @identity], html: { class: 'form-horizontal fieldset-form' } do |f|
- if @identity.errors.any? = form_errors(@identity)
#error_explanation
.alert.alert-danger
- @identity.errors.full_messages.each do |msg|
%p= msg
.form-group .form-group
= f.label :provider, class: 'control-label' = f.label :provider, class: 'control-label'
......
= form_for [:admin, @label], html: { class: 'form-horizontal label-form js-requires-input' } do |f| = form_for [:admin, @label], html: { class: 'form-horizontal label-form js-requires-input' } do |f|
-if @label.errors.any? = form_errors(@label)
.row
.col-sm-offset-2.col-sm-10
.alert.alert-danger
- @label.errors.full_messages.each do |msg|
%span= msg
%br
.form-group .form-group
= f.label :title, class: 'control-label' = f.label :title, class: 'control-label'
......
.user_new .user_new
= form_for [:admin, @user], html: { class: 'form-horizontal fieldset-form' } do |f| = form_for [:admin, @user], html: { class: 'form-horizontal fieldset-form' } do |f|
-if @user.errors.any? = form_errors(@user)
#error_explanation
.alert.alert-danger
- @user.errors.full_messages.each do |msg|
%p= msg
%fieldset %fieldset
%legend Account %legend Account
......
= form_for application, url: doorkeeper_submit_path(application), html: {role: 'form'} do |f| = form_for application, url: doorkeeper_submit_path(application), html: {role: 'form'} do |f|
- if application.errors.any? = form_errors(application)
.alert.alert-danger
%ul
- application.errors.full_messages.each do |msg|
%li= msg
.form-group .form-group
= f.label :name, class: 'label-light' = f.label :name, class: 'label-light'
......
...@@ -5,9 +5,7 @@ ...@@ -5,9 +5,7 @@
Group settings Group settings
.panel-body .panel-body
= form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f| = form_for @group, html: { multipart: true, class: "form-horizontal" }, authenticity_token: true do |f|
- if @group.errors.any? = form_errors(@group)
.alert.alert-danger
%span= @group.errors.full_messages.first
= render 'shared/group_form', f: f = render 'shared/group_form', f: f
.form-group .form-group
......
...@@ -10,6 +10,14 @@ ...@@ -10,6 +10,14 @@
= form_for @milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-quick-submit js-requires-input' } do |f| = form_for @milestone, url: group_milestones_path(@group), html: { class: 'form-horizontal milestone-form gfm-form js-quick-submit js-requires-input' } do |f|
.row .row
- if @milestone.errors.any?
#error_explanation
.alert.alert-danger
%ul
- @milestone.errors.full_messages.each do |msg|
%li
= msg
.col-md-6 .col-md-6
.form-group .form-group
= f.label :title, "Title", class: "control-label" = f.label :title, "Title", class: "control-label"
......
...@@ -6,10 +6,7 @@ ...@@ -6,10 +6,7 @@
%hr %hr
= form_for @group, html: { class: 'group-form form-horizontal' } do |f| = form_for @group, html: { class: 'group-form form-horizontal' } do |f|
- if @group.errors.any? = form_errors(@group)
.alert.alert-danger
%span= @group.errors.full_messages.first
= render 'shared/group_form', f: f, autofocus: true = render 'shared/group_form', f: f, autofocus: true
.form-group.group-description-holder .form-group.group-description-holder
......
- if nav_menu_collapsed?
= link_to icon('angle-right'), '#', class: 'toggle-nav-collapse', title: "Open/Close"
- else
= link_to icon('angle-left'), '#', class: 'toggle-nav-collapse', title: "Open/Close"
.page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" } .page-with-sidebar{ class: "#{page_sidebar_class} #{page_gutter_class}" }
= render "layouts/broadcast" = render "layouts/broadcast"
.expand-nav
= link_to icon('bars'), '#', class: 'toggle-nav-collapse', title: "Open sidebar"
.sidebar-wrapper.nicescroll{ class: nav_sidebar_class } .sidebar-wrapper.nicescroll{ class: nav_sidebar_class }
.header-logo .header-logo
%a#logo %a#logo
...@@ -10,19 +8,15 @@ ...@@ -10,19 +8,15 @@
.gitlab-text-container .gitlab-text-container
%h3 GitLab %h3 GitLab
- primary_sidebar = current_user ? 'dashboard' : 'explore' - if defined?(sidebar) && sidebar
= render "layouts/nav/#{sidebar}"
- if defined?(sidebar) && sidebar && sidebar != primary_sidebar - elsif current_user
.complex-sidebar = render 'layouts/nav/dashboard'
.nav-primary
= render "layouts/nav/#{primary_sidebar}"
.nav-secondary
= render "layouts/nav/#{sidebar}"
- else - else
= render "layouts/nav/#{primary_sidebar}" = render 'layouts/nav/explore'
.collapse-nav .collapse-nav
= link_to icon('angle-left'), '#', class: 'toggle-nav-collapse', title: "Hide sidebar" = render partial: 'layouts/collapse_button'
- if current_user - if current_user
= link_to current_user, class: 'sidebar-user', title: "Profile" do = link_to current_user, class: 'sidebar-user', title: "Profile" do
= image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s36' = image_tag avatar_icon(current_user, 60), alt: 'Profile', class: 'avatar avatar s36'
......
- if controller.controller_path =~ /^groups/ - if controller.controller_path =~ /^groups/ && @group.persisted?
- label = 'This group' - label = 'This group'
- if controller.controller_path =~ /^projects/ - if controller.controller_path =~ /^projects/ && @project.persisted?
- label = 'This project' - label = 'This project'
.search.search-form{class: "#{'has-location-badge' if label.present?}"} .search.search-form{class: "#{'has-location-badge' if label.present?}"}
......
...@@ -95,7 +95,7 @@ ...@@ -95,7 +95,7 @@
Spam Logs Spam Logs
%span.count= number_with_delimiter(SpamLog.count(:all)) %span.count= number_with_delimiter(SpamLog.count(:all))
= nav_link(controller: :application_settings) do = nav_link(controller: :application_settings, html_options: { class: 'separate-item'}) do
= link_to admin_application_settings_path, title: 'Settings' do = link_to admin_application_settings_path, title: 'Settings' do
= icon('cogs fw') = icon('cogs fw')
%span %span
......
...@@ -9,18 +9,18 @@ ...@@ -9,18 +9,18 @@
= icon('bell fw') = icon('bell fw')
%span %span
Todos Todos
%span.count= number_with_delimiter(todos_pending_count) %span.count.todos-pending-count= number_with_delimiter(todos_pending_count)
= nav_link(path: 'dashboard#activity') do = nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do = link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do
= icon('dashboard fw') = icon('dashboard fw')
%span %span
Activity Activity
= nav_link(path: ['dashboard/groups#index', 'explore/groups#index']) do = nav_link(controller: :groups) do
= link_to dashboard_groups_path, title: 'Groups' do = link_to dashboard_groups_path, title: 'Groups' do
= icon('group fw') = icon('group fw')
%span %span
Groups Groups
= nav_link(path: 'dashboard#milestones') do = nav_link(controller: :milestones) do
= link_to dashboard_milestones_path, title: 'Milestones' do = link_to dashboard_milestones_path, title: 'Milestones' do
= icon('clock-o fw') = icon('clock-o fw')
%span %span
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
%span %span
Help Help
%li.separate-item
= nav_link(controller: :profile) do = nav_link(controller: :profile) do
= link_to profile_path, title: 'Profile Settings', data: {placement: 'bottom'} do = link_to profile_path, title: 'Profile Settings', data: {placement: 'bottom'} do
= icon('user fw') = icon('user fw')
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do
= link_to root_path, title: 'Go to dashboard', class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Go to dashboard
%li.separate-item
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do = nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= link_to group_path(@group), title: 'Home' do = link_to group_path(@group), title: 'Home' do
= icon('group fw') = icon('group fw')
...@@ -34,7 +42,7 @@ ...@@ -34,7 +42,7 @@
%span %span
Members Members
- if can?(current_user, :admin_group, @group) - if can?(current_user, :admin_group, @group)
= nav_link do = nav_link(html_options: { class: "separate-item" }) do
= link_to edit_group_path(@group), title: 'Settings' do = link_to edit_group_path(@group), title: 'Settings' do
= icon ('cogs fw') = icon ('cogs fw')
%span %span
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
= nav_link do
= link_to root_path, title: 'Go to dashboard', class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Go to dashboard
%li.separate-item
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile Settings' do = link_to profile_path, title: 'Profile Settings' do
= icon('user fw') = icon('user fw')
......
%ul.nav.nav-sidebar %ul.nav.nav-sidebar
- if @project.group
= nav_link do
= link_to group_path(@project.group), title: 'Go to group', class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Go to group
- else
= nav_link do
= link_to root_path, title: 'Go to dashboard', class: 'back-link' do
= icon('caret-square-o-left fw')
%span
Go to dashboard
%li.separate-item
= nav_link(path: 'projects#show', html_options: {class: 'home'}) do = nav_link(path: 'projects#show', html_options: {class: 'home'}) do
= link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do = link_to project_path(@project), title: 'Project', class: 'shortcuts-project' do
= icon('bookmark fw') = icon('bookmark fw')
...@@ -98,7 +113,7 @@ ...@@ -98,7 +113,7 @@
Snippets Snippets
- if project_nav_tab? :settings - if project_nav_tab? :settings
= nav_link(html_options: {class: "#{project_tab_class}"}) do = nav_link(html_options: {class: "#{project_tab_class} separate-item"}) do
= link_to edit_project_path(@project), title: 'Settings' do = link_to edit_project_path(@project), title: 'Settings' do
= icon('cogs fw') = icon('cogs fw')
%span %span
......
...@@ -51,8 +51,13 @@ ...@@ -51,8 +51,13 @@
= icon('code fw') = icon('code fw')
%span %span
Variables Variables
= nav_link path: 'triggers#index' do = nav_link(controller: :triggers) do
= link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do = link_to namespace_project_triggers_path(@project.namespace, @project), title: 'Triggers' do
= icon('retweet fw') = icon('retweet fw')
%span %span
Triggers Triggers
= nav_link(controller: :badges) do
= link_to namespace_project_badges_path(@project.namespace, @project), title: 'Badges' do
= icon('star-half-empty fw')
%span
Badges
...@@ -5,10 +5,14 @@ ...@@ -5,10 +5,14 @@
- content_for :scripts_body_top do - content_for :scripts_body_top do
- project = @target_project || @project - project = @target_project || @project
- if @project_wiki
- markdown_preview_path = namespace_project_wikis_markdown_preview_path(project.namespace, project)
- else
- markdown_preview_path = markdown_preview_namespace_project_path(project.namespace, project)
- if current_user - if current_user
:javascript :javascript
window.project_uploads_path = "#{namespace_project_uploads_path project.namespace,project}"; window.project_uploads_path = "#{namespace_project_uploads_path project.namespace,project}";
window.markdown_preview_path = "#{markdown_preview_namespace_project_path(project.namespace, project)}"; window.markdown_preview_path = "#{markdown_preview_path}";
- content_for :scripts_body do - content_for :scripts_body do
= render "layouts/init_auto_complete" if current_user = render "layouts/init_auto_complete" if current_user
......
%div %div
= form_for [:profile, @key], html: { class: 'js-requires-input' } do |f| = form_for [:profile, @key], html: { class: 'js-requires-input' } do |f|
- if @key.errors.any? = form_errors(@key)
.alert.alert-danger
%ul
- @key.errors.full_messages.each do |msg|
%li= msg
.form-group .form-group
= f.label :key, class: 'label-light' = f.label :key, class: 'label-light'
......
...@@ -2,11 +2,7 @@ ...@@ -2,11 +2,7 @@
- header_title page_title, profile_notifications_path - header_title page_title, profile_notifications_path
= form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications prepend-top-default' } do |f| = form_for @user, url: profile_notifications_path, method: :put, html: { class: 'update-notifications prepend-top-default' } do |f|
-if @user.errors.any? = form_errors(@user)
%div.alert.alert-danger
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
= hidden_field_tag :notification_type, 'global' = hidden_field_tag :notification_type, 'global'
.row .row
......
...@@ -13,11 +13,8 @@ ...@@ -13,11 +13,8 @@
- unless @user.password_automatically_set? - unless @user.password_automatically_set?
or recover your current one or recover your current one
= form_for @user, url: profile_password_path, method: :put, html: {class: "update-password"} do |f| = form_for @user, url: profile_password_path, method: :put, html: {class: "update-password"} do |f|
-if @user.errors.any? = form_errors(@user)
.alert.alert-danger
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
- unless @user.password_automatically_set? - unless @user.password_automatically_set?
.form-group .form-group
= f.label :current_password, class: 'label-light' = f.label :current_password, class: 'label-light'
......
...@@ -7,11 +7,8 @@ ...@@ -7,11 +7,8 @@
Please set a new password before proceeding. Please set a new password before proceeding.
%br %br
After a successful password update you will be redirected to login screen. After a successful password update you will be redirected to login screen.
-if @user.errors.any?
.alert.alert-danger = form_errors(@user)
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
- unless @user.password_automatically_set? - unless @user.password_automatically_set?
.form-group .form-group
......
= form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit-user prepend-top-default" }, authenticity_token: true do |f| = form_for @user, url: profile_path, method: :put, html: { multipart: true, class: "edit-user prepend-top-default" }, authenticity_token: true do |f|
-if @user.errors.any? = form_errors(@user)
%div.alert.alert-danger
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
.row .row
.col-lg-3.profile-settings-sidebar .col-lg-3.profile-settings-sidebar
%h4.prepend-top-0 %h4.prepend-top-0
......
- if @project.errors.any? = form_errors(@project)
.alert.alert-danger
%button{ type: "button", class: "close", "data-dismiss" => "alert"} &times;
= @project.errors.full_messages.first
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
.md-header .md-header
%ul.nav-links %ul.nav-links
%li.active %li.active
%a.js-md-write-button{ href: "#md-write-holder" } %a.js-md-write-button{ href: "#md-write-holder", tabindex: -1 }
Write Write
%li %li
%a.js-md-preview-button{ href: "#md-preview-holder" } %a.js-md-preview-button{ href: "#md-preview-holder", tabindex: -1 }
Preview Preview
%li.pull-right %li.pull-right
%button.zen-cotrol.zen-control-full.js-zen-enter{ type: 'button' } %button.zen-cotrol.zen-control-full.js-zen-enter{ type: 'button', tabindex: -1 }
Go full screen Go full screen
.md-write-holder .md-write-holder
......
- page_title 'Badges'
- badges_path = namespace_project_badges_path(@project.namespace, @project)
- header_title project_title(@project, 'Badges', badges_path)
.prepend-top-10
.panel.panel-default
.panel-heading
%b Builds badge &middot;
= @build_badge.to_html
.pull-right
= render 'shared/ref_switcher', destination: 'badges'
.panel-body
.row
.col-md-2.text-center
Markdown
.col-md-10.code.js-syntax-highlight
= highlight('.md', @build_badge.to_markdown)
.row
%hr
.row
.col-md-2.text-center
HTML
.col-md-10.code.js-syntax-highlight
= highlight('.html', @build_badge.to_html)
...@@ -19,24 +19,17 @@ ...@@ -19,24 +19,17 @@
.pull-right .pull-right
- if ci_commit - if ci_commit
= render_ci_status(ci_commit) = render_ci_status(ci_commit)
&nbsp;
= clipboard_button(clipboard_text: commit.id) = clipboard_button(clipboard_text: commit.id)
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id" = link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit_short_id"
.notes_count
- if note_count > 0
%span.light
%i.fa.fa-comments
= note_count
- if commit.description? - if commit.description?
.commit-row-description.js-toggle-content .commit-row-description.js-toggle-content
%pre %pre
= preserve(markdown(escape_once(commit.description), pipeline: :single_line)) = preserve(markdown(escape_once(commit.description), pipeline: :single_line))
.commit-row-info .commit-row-info
by
= commit_author_link(commit, avatar: true, size: 24) = commit_author_link(commit, avatar: true, size: 24)
authored
.committed_ago .committed_ago
#{time_ago_with_tooltip(commit.committed_date, skip_js: true)} &nbsp; #{time_ago_with_tooltip(commit.committed_date, skip_js: true)} &nbsp;
= link_to_browse_code(project, commit) = link_to_browse_code(project, commit)
%div %div
= form_for [@project.namespace.becomes(Namespace), @project, @key], url: namespace_project_deploy_keys_path, html: { class: 'deploy-key-form form-horizontal js-requires-input' } do |f| = form_for [@project.namespace.becomes(Namespace), @project, @key], url: namespace_project_deploy_keys_path, html: { class: 'deploy-key-form form-horizontal js-requires-input' } do |f|
-if @key.errors.any? = form_errors(@key)
.alert.alert-danger
%ul
- @key.errors.full_messages.each do |msg|
%li= msg
.form-group .form-group
= f.label :title, class: "control-label" = f.label :title, class: "control-label"
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- diff_files = safe_diff_files(diffs, diff_refs) - diff_files = safe_diff_files(diffs, diff_refs)
.content-block.oneline-block .content-block.oneline-block.files-changed
.inline-parallel-buttons .inline-parallel-buttons
.btn-group .btn-group
= inline_diff_btn = inline_diff_btn
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- if diff_file.diff.submodule? - if diff_file.diff.submodule?
%span %span
= icon('archive fw') = icon('archive fw')
%strong %span
= submodule_link(blob, @commit.id, project.repository) = submodule_link(blob, @commit.id, project.repository)
- else - else
= blob_icon blob.mode, blob.name = blob_icon blob.mode, blob.name
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
= link_to "#diff-#{i}" do = link_to "#diff-#{i}" do
- if diff_file.renamed_file - if diff_file.renamed_file
- old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path) - old_path, new_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
%strong.filename.old .filename.old
= old_path = old_path
&rarr; &rarr;
%strong.filename.new .filename.new
= new_path = new_path
- else - else
%strong %span
= diff_file.new_path = diff_file.new_path
- if diff_file.deleted_file - if diff_file.deleted_file
deleted deleted
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
.file-actions.hidden-xs .file-actions.hidden-xs
- if blob_text_viewable?(blob) - if blob_text_viewable?(blob)
= link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: "Toggle comments for this file" do = link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip btn-file-option', title: "Toggle comments for this file" do
= icon('comments') = icon('comment')
\ \
- if editable_diff?(diff_file) - if editable_diff?(diff_file)
......
...@@ -9,10 +9,8 @@ ...@@ -9,10 +9,8 @@
%hr.clearfix %hr.clearfix
= form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: namespace_project_hooks_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f| = form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: namespace_project_hooks_path(@project.namespace, @project), html: { class: 'form-horizontal' } do |f|
-if @hook.errors.any? = form_errors(@hook)
.alert.alert-danger
- @hook.errors.full_messages.each do |msg|
%p= msg
.form-group .form-group
= f.label :url, "URL", class: 'control-label' = f.label :url, "URL", class: 'control-label'
.col-sm-10 .col-sm-10
......
= form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form js-quick-submit js-requires-input' } do |f| = form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form js-quick-submit js-requires-input' } do |f|
-if @label.errors.any? = form_errors(@label)
.row
.col-sm-offset-2.col-sm-10
.alert.alert-danger
- @label.errors.full_messages.each do |msg|
%span= msg
%br
.form-group .form-group
= f.label :title, class: 'control-label' = f.label :title, class: 'control-label'
......
%li{id: dom_id(label)} %li{id: dom_id(label)}
= render "shared/label_row", label: label = render "shared/label_row", label: label
.pull-right .pull-info-right
%strong.append-right-20 %span.append-right-20
= link_to_label(label, type: :merge_request) do = link_to_label(label, type: :merge_request) do
= pluralize label.open_merge_requests_count, 'open merge request' = pluralize label.open_merge_requests_count, 'merge request'
%strong.append-right-20 %span.append-right-20
= link_to_label(label) do = link_to_label(label) do
= pluralize label.open_issues_count(current_user), 'open issue' = pluralize label.open_issues_count(current_user), 'open issue'
- if current_user - if current_user
.label-subscription{data: {url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label)}} .label-subscription{data: {url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label)}}
.subscription-status{data: {status: label_subscription_status(label)}} .subscription-status{data: {status: label_subscription_status(label)}}
%button.btn.btn-sm.btn-info.subscribe-button
%a.subscribe-button.btn.action-buttons{data: {toggle: "tooltip"}}
%span= label_subscription_toggle_button_text(label) %span= label_subscription_toggle_button_text(label)
- if can? current_user, :admin_label, @project - if can? current_user, :admin_label, @project
= link_to 'Edit', edit_namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm' = link_to edit_namespace_project_label_path(@project.namespace, @project, label), title: "Edit", class: 'btn action-buttons', data: {toggle: "tooltip"} do
= link_to 'Delete', namespace_project_label_path(@project.namespace, @project, label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?"} %i.fa.fa-pencil-square-o
= link_to namespace_project_label_path(@project.namespace, @project, label), title: "Delete", class: 'btn action-buttons remove-row', method: :delete, remote: true, data: {confirm: "Remove this label? Are you sure?", toggle: "tooltip"} do
%i.fa.fa-trash-o
- if current_user - if current_user
:javascript :javascript
......
...@@ -5,33 +5,74 @@ ...@@ -5,33 +5,74 @@
.hide.alert.alert-danger.mr-compare-errors .hide.alert.alert-danger.mr-compare-errors
.merge-request-branches.row .merge-request-branches.row
.col-md-6 .col-md-6
.panel.panel-default .panel.panel-default.panel-new-merge-request
.panel-heading .panel-heading
%strong Source branch Source branch
.panel-body .panel-body.clearfix
= f.select(:source_project_id, [[@merge_request.source_project_path,@merge_request.source_project.id]] , {}, { class: 'source_project select2 span3', disabled: @merge_request.persisted?, required: true }) .merge-request-select.dropdown
&nbsp; = f.hidden_field :source_project_id
= f.select(:source_branch, @merge_request.source_branches, { include_blank: true }, { class: 'source_branch select2 span2', required: true, data: { placeholder: "Select source branch" } }) = dropdown_toggle @merge_request.source_project_path, { toggle: "dropdown", field_name: "#{f.object_name}[source_project_id]", disabled: @merge_request.persisted? }, { toggle_class: "js-compare-dropdown js-source-project" }
.dropdown-menu.dropdown-menu-selectable.dropdown-source-project
= dropdown_title("Select source project")
= dropdown_filter("Search projects")
= dropdown_content do
- is_active = f.object.source_project_id == @merge_request.source_project.id
%ul
%li
%a{ href: "#", class: "#{("is-active" if is_active)}", data: { id: @merge_request.source_project.id } }
= @merge_request.source_project_path
.merge-request-select.dropdown
= f.hidden_field :source_branch
= dropdown_toggle "Select source branch", { toggle: "dropdown", field_name: "#{f.object_name}[source_branch]" }, { toggle_class: "js-compare-dropdown js-source-branch" }
.dropdown-menu.dropdown-menu-selectable.dropdown-source-branch
= dropdown_title("Select source branch")
= dropdown_filter("Search branches")
= dropdown_content do
%ul
- @merge_request.source_branches.each do |branch|
%li
%a{ href: "#", class: "#{("is-active" if f.object.source_branch == branch)}", data: { id: branch } }
= branch
.panel-footer .panel-footer
.mr_source_commit = icon('spinner spin', class: 'js-source-loading')
%ul.list-unstyled.mr_source_commit
.col-md-6 .col-md-6
.panel.panel-default .panel.panel-default.panel-new-merge-request
.panel-heading .panel-heading
%strong Target branch Target branch
.panel-body .panel-body.clearfix
- projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project] - projects = @project.forked_from_project.nil? ? [@project] : [@project, @project.forked_from_project]
= f.select(:target_project_id, options_from_collection_for_select(projects, 'id', 'path_with_namespace', f.object.target_project_id), {}, { class: 'target_project select2 span3', disabled: @merge_request.persisted?, required: true }) .merge-request-select.dropdown
&nbsp; = f.hidden_field :target_project_id
= f.select(:target_branch, @merge_request.target_branches, { include_blank: true }, { class: 'target_branch select2 span2', required: true, data: { placeholder: "Select target branch" } }) = dropdown_toggle f.object.target_project.path_with_namespace, { toggle: "dropdown", field_name: "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted? }, { toggle_class: "js-compare-dropdown js-target-project" }
.dropdown-menu.dropdown-menu-selectable.dropdown-target-project
= dropdown_title("Select target project")
= dropdown_filter("Search projects")
= dropdown_content do
%ul
- projects.each do |project|
%li
%a{ href: "#", class: "#{("is-active" if f.object.target_project_id == project.id)}", data: { id: project.id } }
= project.path_with_namespace
.merge-request-select.dropdown
= f.hidden_field :target_branch
= dropdown_toggle f.object.target_branch, { toggle: "dropdown", field_name: "#{f.object_name}[target_branch]" }, { toggle_class: "js-compare-dropdown js-target-branch" }
.dropdown-menu.dropdown-menu-selectable.dropdown-target-branch.js-target-branch-dropdown
= dropdown_title("Select target branch")
= dropdown_filter("Search branches")
= dropdown_content do
%ul
- @merge_request.target_branches.each do |branch|
%li
%a{ href: "#", class: "#{("is-active" if f.object.target_branch == branch)}", data: { id: branch } }
= branch
.panel-footer .panel-footer
.mr_target_commit = icon('spinner spin', class: "js-target-loading")
%ul.list-unstyled.mr_target_commit
- if @merge_request.errors.any? - if @merge_request.errors.any?
.alert.alert-danger = form_errors(@merge_request)
- @merge_request.errors.full_messages.each do |msg|
%div= msg
- elsif @merge_request.source_branch.present? && @merge_request.target_branch.present? - elsif @merge_request.source_branch.present? && @merge_request.target_branch.present?
.light-well.append-bottom-default .light-well.append-bottom-default
.center .center
...@@ -45,40 +86,11 @@ ...@@ -45,40 +86,11 @@
and and
%span.label-branch #{@merge_request.target_branch} %span.label-branch #{@merge_request.target_branch}
are the same. are the same.
= f.submit 'Compare branches and continue', class: "btn btn-new mr-compare-btn"
.form-actions
= f.submit 'Compare branches and continue', class: "btn btn-new mr-compare-btn"
:javascript
var source_branch = $("#merge_request_source_branch")
, target_branch = $("#merge_request_target_branch")
, target_project = $("#merge_request_target_project_id");
$.get("#{branch_from_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {ref: source_branch.val() });
$.get("#{branch_to_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: target_project.val(),ref: target_branch.val() });
target_project.on("change", function() {
$.get("#{update_branches_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: $(this).val() });
});
source_branch.on("change", function() {
$.get("#{branch_from_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {ref: $(this).val() });
$(".mr-compare-errors").fadeOut();
$(".mr-compare-btn").enable();
});
target_branch.on("change", function() {
$.get("#{branch_to_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}", {target_project_id: target_project.val(),ref: $(this).val() });
$(".mr-compare-errors").fadeOut();
$(".mr-compare-btn").enable();
});
:javascript :javascript
$(".merge-request-form").on('submit', function () { new Compare({
if ($("#merge_request_source_branch").val() === "" || $('#merge_request_target_branch').val() === "") { targetProjectUrl: "#{update_branches_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}",
$(".mr-compare-errors").html("You must select source and target branch to proceed"); sourceBranchUrl: "#{branch_from_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}",
$(".mr-compare-errors").fadeIn(); targetBranchUrl: "#{branch_to_namespace_project_merge_requests_path(@source_project.namespace, @source_project)}"
event.preventDefault();
return;
}
}); });
= commit_to_html(@commit, @source_project, false)
:plain
$(".mr_source_commit").html("#{commit_to_html(@commit, @source_project, false)}");
$('.js-timeago').timeago()
= commit_to_html(@commit, @target_project, false)
:plain
$(".mr_target_commit").html("#{commit_to_html(@commit, @target_project, false)}");
$('.js-timeago').timeago()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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