Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into fix/import-event-error
This commit is contained in:
commit
feecb4afde
|
|
@ -193,7 +193,7 @@ Style/EmptyLineBetweenDefs:
|
|||
|
||||
# Don't use several empty lines in a row.
|
||||
Style/EmptyLines:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Keep blank lines around access modifiers.
|
||||
Style/EmptyLinesAroundAccessModifier:
|
||||
|
|
@ -284,7 +284,7 @@ Style/IfWithSemicolon:
|
|||
# Checks that conditional statements do not have an identical line at the
|
||||
# end of each branch, which can validly be moved out of the conditional.
|
||||
Style/IdenticalConditionalBranches:
|
||||
Enabled: false
|
||||
Enabled: true
|
||||
|
||||
# Checks the indentation of the first line of the right-hand-side of a
|
||||
# multi-line assignment.
|
||||
|
|
|
|||
30
CHANGELOG
30
CHANGELOG
|
|
@ -8,27 +8,50 @@ v 8.10.0 (unreleased)
|
|||
- Wrap code blocks on Activies and Todos page. !4783 (winniehell)
|
||||
- Align flash messages with left side of page content !4959 (winniehell)
|
||||
- Display last commit of deleted branch in push events !4699 (winniehell)
|
||||
- Escape file extension when parsing search results !5141 (winniehell)
|
||||
- Apply the trusted_proxies config to the rack request object for use with rack_attack
|
||||
- Add Sidekiq queue duration to transaction metrics.
|
||||
- Add a new column `artifacts_size` to table `ci_builds` !4964
|
||||
- Let Workhorse serve format-patch diffs
|
||||
- Make images fit to the size of the viewport !4810
|
||||
- Fix check for New Branch button on Issue page !4630 (winniehell)
|
||||
- Fix MR-auto-close text added to description. !4836
|
||||
- Fix issue, preventing users w/o push access to sort tags !5105 (redetection)
|
||||
- Add Spring EmojiOne updates.
|
||||
- Add syntax for multiline blockquote using `>>>` fence !3954
|
||||
- Fix viewing notification settings when a project is pending deletion
|
||||
- Fix pagination when sorting by columns with lots of ties (like priority)
|
||||
- The Markdown reference parsers now re-use query results to prevent running the same queries multiple times !5020
|
||||
- Updated project header design
|
||||
- Exclude email check from the standard health check
|
||||
- Updated layout for Projects, Groups, Users on Admin area !4424
|
||||
- Fix changing issue state columns in milestone view
|
||||
- Add notification settings dropdown for groups
|
||||
- Wildcards for protected branches. !4665
|
||||
- Allow importing from Github using Personal Access Tokens. (Eric K Idema)
|
||||
- API: Todos !3188 (Robert Schilling)
|
||||
- API: Expose shared groups for projects and shared projects for groups !5050 (Robert Schilling)
|
||||
- Add "Enabled Git access protocols" to Application Settings
|
||||
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
|
||||
- Only show New Snippet button to users that can create snippets.
|
||||
- PipelinesFinder uses git cache data
|
||||
- Throttle the update of `project.pushes_since_gc` to 1 minute.
|
||||
- Check for conflicts with existing Project's wiki path when creating a new project.
|
||||
- Show last push widget in upstream after push to fork
|
||||
- Don't instantiate a git tree on Projects show default view
|
||||
- Bump Rinku to 2.0.0
|
||||
- Remove unused front-end variable -> default_issues_tracker
|
||||
- Better caching of git calls on ProjectsController#show.
|
||||
- Avoid to retrieve MR closes_issues as much as possible.
|
||||
- Add API endpoint for a group issues !4520 (mahcsig)
|
||||
- Add Bugzilla integration !4930 (iamtjg)
|
||||
- Instrument Rinku usage
|
||||
- Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
|
||||
- RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info.
|
||||
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
|
||||
- Set import_url validation to be more strict
|
||||
- Memoize MR merged/closed events retrieval
|
||||
- Don't render discussion notes when requesting diff tab through AJAX
|
||||
- Add basic system information like memory and disk usage to the admin panel
|
||||
|
||||
v 8.9.5 (unreleased)
|
||||
|
|
@ -43,6 +66,8 @@ v 8.9.5 (unreleased)
|
|||
|
||||
v 8.9.6
|
||||
- Fix importing of events under notes for GitLab projects
|
||||
- Add min value for project limit field on user's form !3622 (jastkand)
|
||||
- Add reminder to not paste private SSH keys !4399 (Ingo Blechschmidt)
|
||||
|
||||
v 8.9.5
|
||||
- Add more debug info to import/export and memory killer. !5108
|
||||
|
|
@ -58,9 +83,6 @@ v 8.9.5
|
|||
- Admin should be able to turn shared runners into specific ones. !4961
|
||||
- Update RedCloth to 4.3.2 for CVE-2012-6684. !4929 (Takuya Noguchi)
|
||||
- Improve the request / withdraw access button. !4860
|
||||
- Fix assigning shared runners as admins. !4961
|
||||
- Show "locked" label for locked runners on runners admin. !4961
|
||||
- Fixes issues importing events in Import/Export. Import/Export version bumped to 0.1.1
|
||||
|
||||
v 8.9.4
|
||||
- Fix privilege escalation issue with OAuth external users.
|
||||
|
|
@ -90,7 +112,7 @@ v 8.9.3
|
|||
- Removed fade when filtering results. !4932
|
||||
- Fix missing avatar on system notes. !4954
|
||||
- Reduce overhead and optimize ProjectTeam#max_member_access performance. !4973
|
||||
- Use update_columns to by_pass all the dirty code on active_record. !4985
|
||||
- Use update_columns to bypass all the dirty code on active_record. !4985
|
||||
- Fix restore Rake task warning message output !4980
|
||||
|
||||
v 8.9.2
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.1.0
|
||||
3.2.0
|
||||
|
|
|
|||
115
Gemfile
115
Gemfile
|
|
@ -1,4 +1,4 @@
|
|||
source "https://rubygems.org"
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'rails', '4.2.6'
|
||||
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
|
||||
|
|
@ -11,15 +11,15 @@ gem 'responders', '~> 2.0'
|
|||
gem 'sprockets', '~> 3.6.0'
|
||||
|
||||
# Default values for AR models
|
||||
gem "default_value_for", "~> 3.0.0"
|
||||
gem 'default_value_for', '~> 3.0.0'
|
||||
|
||||
# Supported DBs
|
||||
gem "mysql2", '~> 0.3.16', group: :mysql
|
||||
gem "pg", '~> 0.18.2', group: :postgres
|
||||
gem 'mysql2', '~> 0.3.16', group: :mysql
|
||||
gem 'pg', '~> 0.18.2', group: :postgres
|
||||
|
||||
# Authentication libraries
|
||||
gem 'devise', '~> 4.0'
|
||||
gem 'doorkeeper', '~> 3.1'
|
||||
gem 'doorkeeper', '~> 4.0'
|
||||
gem 'omniauth', '~> 1.3.1'
|
||||
gem 'omniauth-auth0', '~> 1.4.1'
|
||||
gem 'omniauth-azure-oauth2', '~> 0.0.6'
|
||||
|
|
@ -28,7 +28,7 @@ gem 'omniauth-cas3', '~> 1.1.2'
|
|||
gem 'omniauth-facebook', '~> 3.0.0'
|
||||
gem 'omniauth-github', '~> 1.1.1'
|
||||
gem 'omniauth-gitlab', '~> 1.0.0'
|
||||
gem 'omniauth-google-oauth2', '~> 0.2.0'
|
||||
gem 'omniauth-google-oauth2', '~> 0.4.1'
|
||||
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
|
||||
gem 'omniauth-saml', '~> 1.6.0'
|
||||
gem 'omniauth-shibboleth', '~> 1.2.0'
|
||||
|
|
@ -48,16 +48,16 @@ gem 'attr_encrypted', '~> 3.0.0'
|
|||
gem 'u2f', '~> 0.2.1'
|
||||
|
||||
# Browser detection
|
||||
gem "browser", '~> 2.2'
|
||||
gem 'browser', '~> 2.2'
|
||||
|
||||
# Extracting information from a git repository
|
||||
# Provide access to Gitlab::Git library
|
||||
gem "gitlab_git", '~> 10.2'
|
||||
gem 'gitlab_git', '~> 10.2'
|
||||
|
||||
# LDAP Auth
|
||||
# GitLab fork with several improvements to original library. For full list of changes
|
||||
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
|
||||
gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: "omniauth-ldap"
|
||||
gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap'
|
||||
|
||||
# Git Wiki
|
||||
# Required manually in config/initializers/gollum.rb to control load order
|
||||
|
|
@ -65,7 +65,7 @@ gem 'gollum-lib', '~> 4.1.0', require: false
|
|||
gem 'gollum-rugged_adapter', '~> 0.4.2', require: false
|
||||
|
||||
# Language detection
|
||||
gem "github-linguist", "~> 4.7.0", require: "linguist"
|
||||
gem 'github-linguist', '~> 4.7.0', require: 'linguist'
|
||||
|
||||
# API
|
||||
gem 'grape', '~> 0.13.0'
|
||||
|
|
@ -73,13 +73,13 @@ gem 'grape-entity', '~> 0.4.2'
|
|||
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||
|
||||
# Pagination
|
||||
gem "kaminari", "~> 0.17.0"
|
||||
gem 'kaminari', '~> 0.17.0'
|
||||
|
||||
# HAML
|
||||
gem 'hamlit', '~> 2.5'
|
||||
|
||||
# Files attachments
|
||||
gem "carrierwave", '~> 0.10.0'
|
||||
gem 'carrierwave', '~> 0.10.0'
|
||||
|
||||
# Drag and Drop UI
|
||||
gem 'dropzonejs-rails', '~> 0.7.1'
|
||||
|
|
@ -94,20 +94,20 @@ gem 'fog-openstack', '~> 0.1'
|
|||
gem 'fog-rackspace', '~> 0.1.1'
|
||||
|
||||
# for aws storage
|
||||
gem "unf", '~> 0.1.4'
|
||||
gem 'unf', '~> 0.1.4'
|
||||
|
||||
# Authorization
|
||||
gem "six", '~> 0.2.0'
|
||||
gem 'six', '~> 0.2.0'
|
||||
|
||||
# Seed data
|
||||
gem "seed-fu", '~> 2.3.5'
|
||||
gem 'seed-fu', '~> 2.3.5'
|
||||
|
||||
# Markdown and HTML processing
|
||||
gem 'html-pipeline', '~> 1.11.0'
|
||||
gem 'task_list', '~> 1.0.2', require: 'task_list/railtie'
|
||||
gem 'github-markup', '~> 1.3.1'
|
||||
gem 'redcarpet', '~> 3.3.3'
|
||||
gem 'RedCloth', '~> 4.2.9'
|
||||
gem 'RedCloth', '~> 4.3.2'
|
||||
gem 'rdoc', '~>3.6'
|
||||
gem 'org-ruby', '~> 0.9.12'
|
||||
gem 'creole', '~> 0.5.0'
|
||||
|
|
@ -124,29 +124,29 @@ gem 'diffy', '~> 3.0.3'
|
|||
|
||||
# Application server
|
||||
group :unicorn do
|
||||
gem "unicorn", '~> 4.9.0'
|
||||
gem 'unicorn', '~> 4.9.0'
|
||||
gem 'unicorn-worker-killer', '~> 0.4.2'
|
||||
end
|
||||
|
||||
# State machine
|
||||
gem "state_machines-activerecord", '~> 0.4.0'
|
||||
gem 'state_machines-activerecord', '~> 0.4.0'
|
||||
# Run events after state machine commits
|
||||
gem 'after_commit_queue'
|
||||
gem 'after_commit_queue', '~> 1.3.0'
|
||||
|
||||
# Issue tags
|
||||
gem 'acts-as-taggable-on', '~> 3.4'
|
||||
|
||||
# Background jobs
|
||||
gem 'sinatra', '~> 1.4.4', require: nil
|
||||
gem 'sinatra', '~> 1.4.4', require: false
|
||||
gem 'sidekiq', '~> 4.0'
|
||||
gem 'sidekiq-cron', '~> 0.4.0'
|
||||
gem 'redis-namespace'
|
||||
gem 'redis-namespace', '~> 1.5.2'
|
||||
|
||||
# HTTP requests
|
||||
gem "httparty", '~> 0.13.3'
|
||||
gem 'httparty', '~> 0.13.3'
|
||||
|
||||
# Colored output to console
|
||||
gem "rainbow", '~> 2.1.0'
|
||||
gem 'rainbow', '~> 2.1.0'
|
||||
|
||||
# GitLab settings
|
||||
gem 'settingslogic', '~> 2.0.9'
|
||||
|
|
@ -156,7 +156,7 @@ gem 'settingslogic', '~> 2.0.9'
|
|||
gem 'version_sorter', '~> 2.0.0'
|
||||
|
||||
# Cache
|
||||
gem "redis-rails", '~> 4.0.0'
|
||||
gem 'redis-rails', '~> 4.0.0'
|
||||
|
||||
# Redis
|
||||
gem 'redis', '~> 3.2'
|
||||
|
|
@ -169,13 +169,13 @@ gem 'tinder', '~> 1.10.0'
|
|||
gem 'hipchat', '~> 1.5.0'
|
||||
|
||||
# Flowdock integration
|
||||
gem "gitlab-flowdock-git-hook", "~> 1.0.1"
|
||||
gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
|
||||
|
||||
# Gemnasium integration
|
||||
gem "gemnasium-gitlab-service", "~> 0.2"
|
||||
gem 'gemnasium-gitlab-service', '~> 0.2'
|
||||
|
||||
# Slack integration
|
||||
gem "slack-notifier", "~> 1.2.0"
|
||||
gem 'slack-notifier', '~> 1.2.0'
|
||||
|
||||
# Asana integration
|
||||
gem 'asana', '~> 0.4.0'
|
||||
|
|
@ -187,20 +187,20 @@ gem 'ruby-fogbugz', '~> 0.2.1'
|
|||
gem 'd3_rails', '~> 3.5.0'
|
||||
|
||||
# underscore-rails
|
||||
gem "underscore-rails", "~> 1.8.0"
|
||||
gem 'underscore-rails', '~> 1.8.0'
|
||||
|
||||
# Sanitize user input
|
||||
gem "sanitize", '~> 2.0'
|
||||
gem 'sanitize', '~> 2.0'
|
||||
gem 'babosa', '~> 1.0.2'
|
||||
|
||||
# Sanitizes SVG input
|
||||
gem "loofah", "~> 2.0.3"
|
||||
gem 'loofah', '~> 2.0.3'
|
||||
|
||||
# Working with license
|
||||
gem 'licensee', '~> 8.0.0'
|
||||
|
||||
# Protect against bruteforcing
|
||||
gem "rack-attack", '~> 4.3.1'
|
||||
gem 'rack-attack', '~> 4.3.1'
|
||||
|
||||
# Ace editor
|
||||
gem 'ace-rails-ap', '~> 4.0.2'
|
||||
|
|
@ -214,16 +214,16 @@ gem 'charlock_holmes', '~> 0.7.3'
|
|||
# Parse duration
|
||||
gem 'chronic_duration', '~> 0.10.6'
|
||||
|
||||
gem "sass-rails", '~> 5.0.0'
|
||||
gem "coffee-rails", '~> 4.1.0'
|
||||
gem "uglifier", '~> 2.7.2'
|
||||
gem 'sass-rails', '~> 5.0.0'
|
||||
gem 'coffee-rails', '~> 4.1.0'
|
||||
gem 'uglifier', '~> 2.7.2'
|
||||
gem 'turbolinks', '~> 2.5.0'
|
||||
gem 'jquery-turbolinks', '~> 2.1.0'
|
||||
|
||||
gem 'addressable', '~> 2.3.8'
|
||||
gem 'bootstrap-sass', '~> 3.3.0'
|
||||
gem 'font-awesome-rails', '~> 4.6.1'
|
||||
gem 'gitlab_emoji', '~> 0.3.0'
|
||||
gem 'gemojione', '~> 2.6'
|
||||
gem 'gon', '~> 6.0.1'
|
||||
gem 'jquery-atwho-rails', '~> 1.3.2'
|
||||
gem 'jquery-rails', '~> 4.1.0'
|
||||
|
|
@ -247,14 +247,13 @@ group :metrics do
|
|||
end
|
||||
|
||||
group :development do
|
||||
gem "foreman"
|
||||
gem 'foreman', '~> 0.78.0'
|
||||
gem 'brakeman', '~> 3.3.0', require: false
|
||||
|
||||
gem 'letter_opener_web', '~> 1.3.0'
|
||||
gem 'quiet_assets', '~> 1.0.2'
|
||||
gem 'rerun', '~> 0.11.0'
|
||||
gem 'bullet', require: false
|
||||
gem 'rblineprof', platform: :mri, require: false
|
||||
gem 'bullet', '~> 5.0.0', require: false
|
||||
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
|
||||
gem 'web-console', '~> 2.0'
|
||||
|
||||
# Better errors handler
|
||||
|
|
@ -262,23 +261,23 @@ group :development do
|
|||
gem 'binding_of_caller', '~> 0.7.2'
|
||||
|
||||
# Docs generator
|
||||
gem "sdoc", '~> 0.3.20'
|
||||
gem 'sdoc', '~> 0.3.20'
|
||||
|
||||
# thin instead webrick
|
||||
gem 'thin', '~> 1.6.1'
|
||||
gem 'thin', '~> 1.7.0'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
gem 'byebug', platform: :mri
|
||||
gem 'pry-rails'
|
||||
gem 'byebug', '~> 8.2.1', platform: :mri
|
||||
gem 'pry-rails', '~> 0.3.4'
|
||||
|
||||
gem 'awesome_print', '~> 1.2.0', require: false
|
||||
gem 'fuubar', '~> 2.0.0'
|
||||
|
||||
gem 'database_cleaner', '~> 1.4.0'
|
||||
gem 'factory_girl_rails', '~> 4.6.0'
|
||||
gem 'rspec-rails', '~> 3.4.0'
|
||||
gem 'rspec-retry'
|
||||
gem 'rspec-rails', '~> 3.5.0'
|
||||
gem 'rspec-retry', '~> 0.4.5'
|
||||
gem 'spinach-rails', '~> 0.2.1'
|
||||
gem 'spinach-rerun-reporter', '~> 0.0.2'
|
||||
|
||||
|
|
@ -304,14 +303,14 @@ group :development, :test do
|
|||
gem 'rubocop-rspec', '~> 1.5.0', require: false
|
||||
gem 'scss_lint', '~> 0.47.0', require: false
|
||||
gem 'simplecov', '~> 0.11.0', require: false
|
||||
gem 'flog', require: false
|
||||
gem 'flay', require: false
|
||||
gem 'bundler-audit', require: false
|
||||
gem 'flog', '~> 4.3.2', require: false
|
||||
gem 'flay', '~> 2.6.1', require: false
|
||||
gem 'bundler-audit', '~> 0.5.0', require: false
|
||||
|
||||
gem 'benchmark-ips', require: false
|
||||
gem 'benchmark-ips', '~> 2.3.0', require: false
|
||||
|
||||
gem "license_finder", require: false
|
||||
gem 'knapsack'
|
||||
gem 'license_finder', '~> 2.1.0', require: false
|
||||
gem 'knapsack', '~> 1.11.0'
|
||||
end
|
||||
|
||||
group :test do
|
||||
|
|
@ -319,30 +318,30 @@ group :test do
|
|||
gem 'email_spec', '~> 1.6.0'
|
||||
gem 'webmock', '~> 1.21.0'
|
||||
gem 'test_after_commit', '~> 0.4.2'
|
||||
gem 'sham_rack'
|
||||
gem 'sham_rack', '~> 1.3.6'
|
||||
end
|
||||
|
||||
group :production do
|
||||
gem "gitlab_meta", '7.0'
|
||||
gem 'gitlab_meta', '7.0'
|
||||
end
|
||||
|
||||
gem "newrelic_rpm", '~> 3.14'
|
||||
gem 'newrelic_rpm', '~> 3.14'
|
||||
|
||||
gem 'octokit', '~> 4.3.0'
|
||||
|
||||
gem "mail_room", "~> 0.8"
|
||||
gem 'mail_room', '~> 0.8'
|
||||
|
||||
gem 'email_reply_parser', '~> 0.5.8'
|
||||
|
||||
## CI
|
||||
gem 'activerecord-session_store', '~> 1.0.0'
|
||||
gem "nested_form", '~> 0.3.2'
|
||||
gem 'nested_form', '~> 0.3.2'
|
||||
|
||||
# OAuth
|
||||
gem 'oauth2', '~> 1.0.0'
|
||||
gem 'oauth2', '~> 1.2.0'
|
||||
|
||||
# Soft deletion
|
||||
gem "paranoia", "~> 2.0"
|
||||
gem 'paranoia', '~> 2.0'
|
||||
|
||||
# Health check
|
||||
gem 'health_check', '~> 1.5.1'
|
||||
|
|
|
|||
136
Gemfile.lock
136
Gemfile.lock
|
|
@ -1,7 +1,7 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
RedCloth (4.2.9)
|
||||
RedCloth (4.3.2)
|
||||
ace-rails-ap (4.0.2)
|
||||
actionmailer (4.2.6)
|
||||
actionpack (= 4.2.6)
|
||||
|
|
@ -171,8 +171,8 @@ GEM
|
|||
diff-lcs (1.2.5)
|
||||
diffy (3.0.7)
|
||||
docile (1.1.5)
|
||||
doorkeeper (3.1.0)
|
||||
railties (>= 3.2)
|
||||
doorkeeper (4.0.0)
|
||||
railties (>= 4.2)
|
||||
dropzonejs-rails (0.7.2)
|
||||
rails (> 3.1)
|
||||
email_reply_parser (0.5.8)
|
||||
|
|
@ -255,7 +255,7 @@ GEM
|
|||
ruby-progressbar (~> 1.4)
|
||||
gemnasium-gitlab-service (0.2.6)
|
||||
rugged (~> 0.21)
|
||||
gemojione (2.2.1)
|
||||
gemojione (2.6.1)
|
||||
json
|
||||
get_process_mem (0.2.0)
|
||||
gherkin-ruby (0.3.2)
|
||||
|
|
@ -274,8 +274,6 @@ GEM
|
|||
diff-lcs (~> 1.1)
|
||||
mime-types (>= 1.16, < 3)
|
||||
posix-spawn (~> 0.3)
|
||||
gitlab_emoji (0.3.1)
|
||||
gemojione (~> 2.2, >= 2.2.1)
|
||||
gitlab_git (10.2.3)
|
||||
activesupport (~> 4.0)
|
||||
charlock_holmes (~> 0.7.3)
|
||||
|
|
@ -355,7 +353,7 @@ GEM
|
|||
jquery-ui-rails (5.0.5)
|
||||
railties (>= 3.2.16)
|
||||
json (1.8.3)
|
||||
jwt (1.5.2)
|
||||
jwt (1.5.4)
|
||||
kaminari (0.17.0)
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
|
|
@ -395,7 +393,7 @@ GEM
|
|||
mini_portile2 (2.1.0)
|
||||
minitest (5.7.0)
|
||||
mousetrap-rails (1.4.6)
|
||||
multi_json (1.11.2)
|
||||
multi_json (1.12.1)
|
||||
multi_xml (0.5.5)
|
||||
multipart-post (2.0.0)
|
||||
mysql2 (0.3.20)
|
||||
|
|
@ -408,12 +406,12 @@ GEM
|
|||
pkg-config (~> 1.1.7)
|
||||
numerizer (0.1.1)
|
||||
oauth (0.4.7)
|
||||
oauth2 (1.0.0)
|
||||
oauth2 (1.2.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
jwt (~> 1.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (~> 1.2)
|
||||
rack (>= 1.2, < 3)
|
||||
octokit (4.3.0)
|
||||
sawyer (~> 0.7.0, >= 0.5.3)
|
||||
omniauth (1.3.1)
|
||||
|
|
@ -441,7 +439,7 @@ GEM
|
|||
omniauth-gitlab (1.0.1)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (~> 1.0)
|
||||
omniauth-google-oauth2 (0.2.10)
|
||||
omniauth-google-oauth2 (0.4.1)
|
||||
addressable (~> 2.3)
|
||||
jwt (~> 1.0)
|
||||
multi_json (~> 1.3)
|
||||
|
|
@ -499,8 +497,6 @@ GEM
|
|||
pry-rails (0.3.4)
|
||||
pry (>= 0.9.10)
|
||||
pyu-ruby-sasl (0.0.3.3)
|
||||
quiet_assets (1.0.3)
|
||||
railties (>= 3.1, < 5.0)
|
||||
rack (1.6.4)
|
||||
rack-accept (0.4.5)
|
||||
rack (>= 0.4)
|
||||
|
|
@ -556,7 +552,7 @@ GEM
|
|||
recaptcha (3.0.0)
|
||||
json
|
||||
redcarpet (3.3.3)
|
||||
redis (3.3.0)
|
||||
redis (3.2.2)
|
||||
redis-actionpack (4.0.1)
|
||||
actionpack (~> 4)
|
||||
redis-rack (~> 1.5.0)
|
||||
|
|
@ -580,36 +576,36 @@ GEM
|
|||
listen (~> 3.0)
|
||||
responders (2.1.1)
|
||||
railties (>= 4.2.0, < 5.1)
|
||||
rinku (1.7.3)
|
||||
rinku (2.0.0)
|
||||
rotp (2.1.2)
|
||||
rouge (1.11.0)
|
||||
rqrcode (0.7.0)
|
||||
chunky_png
|
||||
rqrcode-rails3 (0.1.7)
|
||||
rqrcode (>= 0.4.2)
|
||||
rspec (3.4.0)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-core (3.4.4)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-expectations (3.4.0)
|
||||
rspec (3.5.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-core (3.5.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-expectations (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-mocks (3.4.1)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-mocks (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-rails (3.4.2)
|
||||
actionpack (>= 3.0, < 4.3)
|
||||
activesupport (>= 3.0, < 4.3)
|
||||
railties (>= 3.0, < 4.3)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-rails (3.5.0)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-retry (0.4.5)
|
||||
rspec-core
|
||||
rspec-support (3.4.1)
|
||||
rspec-support (3.5.0)
|
||||
rubocop (0.40.0)
|
||||
parser (>= 2.3.1.0, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
|
|
@ -634,8 +630,8 @@ GEM
|
|||
sanitize (2.1.0)
|
||||
nokogiri (>= 1.4.4)
|
||||
sass (3.4.22)
|
||||
sass-rails (5.0.4)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass-rails (5.0.5)
|
||||
railties (>= 4.0.0, < 6)
|
||||
sass (~> 3.1)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
|
|
@ -649,9 +645,9 @@ GEM
|
|||
sdoc (0.3.20)
|
||||
json (>= 1.1.3)
|
||||
rdoc (~> 3.10)
|
||||
seed-fu (2.3.5)
|
||||
activerecord (>= 3.1, < 4.3)
|
||||
activesupport (>= 3.1, < 4.3)
|
||||
seed-fu (2.3.6)
|
||||
activerecord (>= 3.1)
|
||||
activesupport (>= 3.1)
|
||||
select2-rails (3.5.9.3)
|
||||
thor (~> 0.14)
|
||||
sentry-raven (1.1.0)
|
||||
|
|
@ -662,10 +658,11 @@ GEM
|
|||
rack
|
||||
shoulda-matchers (2.8.0)
|
||||
activesupport (>= 3.0.0)
|
||||
sidekiq (4.1.2)
|
||||
sidekiq (4.1.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
redis (~> 3.2, >= 3.2.1)
|
||||
sinatra (>= 1.4.7)
|
||||
sidekiq-cron (0.4.0)
|
||||
redis-namespace (>= 1.5.2)
|
||||
rufus-scheduler (>= 2.0.24)
|
||||
|
|
@ -676,8 +673,8 @@ GEM
|
|||
json (~> 1.8)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.0)
|
||||
sinatra (1.4.6)
|
||||
rack (~> 1.4)
|
||||
sinatra (1.4.7)
|
||||
rack (~> 1.5)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (>= 1.3, < 3)
|
||||
six (0.2.0)
|
||||
|
|
@ -693,17 +690,17 @@ GEM
|
|||
spinach (>= 0.4)
|
||||
spinach-rerun-reporter (0.0.2)
|
||||
spinach (~> 0.8)
|
||||
spring (1.7.1)
|
||||
spring (1.7.2)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
spring-commands-spinach (1.1.0)
|
||||
spring (>= 0.9.1)
|
||||
spring-commands-teaspoon (0.0.2)
|
||||
spring (>= 0.9.1)
|
||||
sprockets (3.6.0)
|
||||
sprockets (3.6.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (3.0.4)
|
||||
sprockets-rails (3.1.1)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
|
|
@ -727,10 +724,10 @@ GEM
|
|||
temple (0.7.7)
|
||||
test_after_commit (0.4.2)
|
||||
activerecord (>= 3.2)
|
||||
thin (1.6.4)
|
||||
thin (1.7.0)
|
||||
daemons (~> 1.0, >= 1.0.9)
|
||||
eventmachine (~> 1.0, >= 1.0.4)
|
||||
rack (~> 1.0)
|
||||
rack (>= 1, < 3)
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.5)
|
||||
|
|
@ -804,12 +801,12 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
RedCloth (~> 4.2.9)
|
||||
RedCloth (~> 4.3.2)
|
||||
ace-rails-ap (~> 4.0.2)
|
||||
activerecord-session_store (~> 1.0.0)
|
||||
acts-as-taggable-on (~> 3.4)
|
||||
addressable (~> 2.3.8)
|
||||
after_commit_queue
|
||||
after_commit_queue (~> 1.3.0)
|
||||
akismet (~> 2.0)
|
||||
allocations (~> 1.0)
|
||||
asana (~> 0.4.0)
|
||||
|
|
@ -818,15 +815,15 @@ DEPENDENCIES
|
|||
awesome_print (~> 1.2.0)
|
||||
babosa (~> 1.0.2)
|
||||
base32 (~> 0.3.0)
|
||||
benchmark-ips
|
||||
benchmark-ips (~> 2.3.0)
|
||||
better_errors (~> 1.0.1)
|
||||
binding_of_caller (~> 0.7.2)
|
||||
bootstrap-sass (~> 3.3.0)
|
||||
brakeman (~> 3.3.0)
|
||||
browser (~> 2.2)
|
||||
bullet
|
||||
bundler-audit
|
||||
byebug
|
||||
bullet (~> 5.0.0)
|
||||
bundler-audit (~> 0.5.0)
|
||||
byebug (~> 8.2.1)
|
||||
capybara (~> 2.6.2)
|
||||
capybara-screenshot (~> 1.0.0)
|
||||
carrierwave (~> 0.10.0)
|
||||
|
|
@ -841,14 +838,14 @@ DEPENDENCIES
|
|||
devise (~> 4.0)
|
||||
devise-two-factor (~> 3.0.0)
|
||||
diffy (~> 3.0.3)
|
||||
doorkeeper (~> 3.1)
|
||||
doorkeeper (~> 4.0)
|
||||
dropzonejs-rails (~> 0.7.1)
|
||||
email_reply_parser (~> 0.5.8)
|
||||
email_spec (~> 1.6.0)
|
||||
factory_girl_rails (~> 4.6.0)
|
||||
ffaker (~> 2.0.0)
|
||||
flay
|
||||
flog
|
||||
flay (~> 2.6.1)
|
||||
flog (~> 4.3.2)
|
||||
fog-aws (~> 0.9)
|
||||
fog-azure (~> 0.0)
|
||||
fog-core (~> 1.40)
|
||||
|
|
@ -857,13 +854,13 @@ DEPENDENCIES
|
|||
fog-openstack (~> 0.1)
|
||||
fog-rackspace (~> 0.1.1)
|
||||
font-awesome-rails (~> 4.6.1)
|
||||
foreman
|
||||
foreman (~> 0.78.0)
|
||||
fuubar (~> 2.0.0)
|
||||
gemnasium-gitlab-service (~> 0.2)
|
||||
gemojione (~> 2.6)
|
||||
github-linguist (~> 4.7.0)
|
||||
github-markup (~> 1.3.1)
|
||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||
gitlab_emoji (~> 0.3.0)
|
||||
gitlab_git (~> 10.2)
|
||||
gitlab_meta (= 7.0)
|
||||
gitlab_omniauth-ldap (~> 1.2.1)
|
||||
|
|
@ -884,9 +881,9 @@ DEPENDENCIES
|
|||
jquery-ui-rails (~> 5.0.0)
|
||||
jwt
|
||||
kaminari (~> 0.17.0)
|
||||
knapsack
|
||||
knapsack (~> 1.11.0)
|
||||
letter_opener_web (~> 1.3.0)
|
||||
license_finder
|
||||
license_finder (~> 2.1.0)
|
||||
licensee (~> 8.0.0)
|
||||
loofah (~> 2.0.3)
|
||||
mail_room (~> 0.8)
|
||||
|
|
@ -898,7 +895,7 @@ DEPENDENCIES
|
|||
net-ssh (~> 3.0.1)
|
||||
newrelic_rpm (~> 3.14)
|
||||
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
||||
oauth2 (~> 1.0.0)
|
||||
oauth2 (~> 1.2.0)
|
||||
octokit (~> 4.3.0)
|
||||
omniauth (~> 1.3.1)
|
||||
omniauth-auth0 (~> 1.4.1)
|
||||
|
|
@ -908,7 +905,7 @@ DEPENDENCIES
|
|||
omniauth-facebook (~> 3.0.0)
|
||||
omniauth-github (~> 1.1.1)
|
||||
omniauth-gitlab (~> 1.0.0)
|
||||
omniauth-google-oauth2 (~> 0.2.0)
|
||||
omniauth-google-oauth2 (~> 0.4.1)
|
||||
omniauth-kerberos (~> 0.3.0)
|
||||
omniauth-saml (~> 1.6.0)
|
||||
omniauth-shibboleth (~> 1.2.0)
|
||||
|
|
@ -919,28 +916,27 @@ DEPENDENCIES
|
|||
pg (~> 0.18.2)
|
||||
poltergeist (~> 1.9.0)
|
||||
premailer-rails (~> 1.9.0)
|
||||
pry-rails
|
||||
quiet_assets (~> 1.0.2)
|
||||
pry-rails (~> 0.3.4)
|
||||
rack-attack (~> 4.3.1)
|
||||
rack-cors (~> 0.4.0)
|
||||
rack-oauth2 (~> 1.2.1)
|
||||
rails (= 4.2.6)
|
||||
rails-deprecated_sanitizer (~> 1.0.3)
|
||||
rainbow (~> 2.1.0)
|
||||
rblineprof
|
||||
rblineprof (~> 0.3.6)
|
||||
rdoc (~> 3.6)
|
||||
recaptcha (~> 3.0)
|
||||
redcarpet (~> 3.3.3)
|
||||
redis (~> 3.2)
|
||||
redis-namespace
|
||||
redis-namespace (~> 1.5.2)
|
||||
redis-rails (~> 4.0.0)
|
||||
request_store (~> 1.3.0)
|
||||
rerun (~> 0.11.0)
|
||||
responders (~> 2.0)
|
||||
rouge (~> 1.11)
|
||||
rqrcode-rails3 (~> 0.1.7)
|
||||
rspec-rails (~> 3.4.0)
|
||||
rspec-retry
|
||||
rspec-rails (~> 3.5.0)
|
||||
rspec-retry (~> 0.4.5)
|
||||
rubocop (~> 0.40.0)
|
||||
rubocop-rspec (~> 1.5.0)
|
||||
ruby-fogbugz (~> 0.2.1)
|
||||
|
|
@ -952,7 +948,7 @@ DEPENDENCIES
|
|||
select2-rails (~> 3.5.9)
|
||||
sentry-raven (~> 1.1.0)
|
||||
settingslogic (~> 2.0.9)
|
||||
sham_rack
|
||||
sham_rack (~> 1.3.6)
|
||||
shoulda-matchers (~> 2.8.0)
|
||||
sidekiq (~> 4.0)
|
||||
sidekiq-cron (~> 0.4.0)
|
||||
|
|
@ -973,7 +969,7 @@ DEPENDENCIES
|
|||
teaspoon (~> 1.1.0)
|
||||
teaspoon-jasmine (~> 2.2.0)
|
||||
test_after_commit (~> 0.4.2)
|
||||
thin (~> 1.6.1)
|
||||
thin (~> 1.7.0)
|
||||
tinder (~> 1.10.0)
|
||||
turbolinks (~> 2.5.0)
|
||||
u2f (~> 0.2.1)
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 257 KiB After Width: | Height: | Size: 1002 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 673 KiB After Width: | Height: | Size: 2.4 MiB |
|
|
@ -54,7 +54,6 @@
|
|||
#= require_directory ./u2f
|
||||
#= require_directory .
|
||||
#= require fuzzaldrin-plus
|
||||
#= require cropper
|
||||
#= require u2f
|
||||
|
||||
window.slugify = (text) ->
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ class @CiBuild
|
|||
@interval: null
|
||||
@state: null
|
||||
|
||||
constructor: (@build_url, @build_status, @state) ->
|
||||
constructor: (@page_url, @build_url, @build_status, @state) ->
|
||||
clearInterval(CiBuild.interval)
|
||||
|
||||
# Init breakpoint checker
|
||||
|
|
@ -41,7 +41,7 @@ class @CiBuild
|
|||
# Only valid for runnig build when output changes during time
|
||||
#
|
||||
CiBuild.interval = setInterval =>
|
||||
if window.location.href.split("#").first() is @build_url
|
||||
if window.location.href.split("#").first() is @page_url
|
||||
@getBuildTrace()
|
||||
, 4000
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ class @CiBuild
|
|||
|
||||
getBuildTrace: ->
|
||||
$.ajax
|
||||
url: "#{@build_url}/trace.json?state=#{encodeURIComponent(@state)}"
|
||||
url: "#{@page_url}/trace.json?state=#{encodeURIComponent(@state)}"
|
||||
dataType: "json"
|
||||
success: (log) =>
|
||||
if log.state
|
||||
|
|
@ -70,7 +70,7 @@ class @CiBuild
|
|||
$('.js-build-output').html log.html
|
||||
@checkAutoscroll()
|
||||
else if log.status isnt @build_status
|
||||
Turbolinks.visit @build_url
|
||||
Turbolinks.visit @page_url
|
||||
|
||||
checkAutoscroll: ->
|
||||
$("html,body").scrollTop $("#build-trace").height() if "enabled" is $("#autoscroll-button").data("state")
|
||||
|
|
|
|||
|
|
@ -127,11 +127,10 @@ class Dispatcher
|
|||
when 'groups'
|
||||
new UsersSelect()
|
||||
when 'projects'
|
||||
new NamespaceSelect()
|
||||
new NamespaceSelects()
|
||||
when 'dashboard', 'root'
|
||||
shortcut_handler = new ShortcutsDashboardNavigation()
|
||||
when 'profiles'
|
||||
new Profile()
|
||||
new NotificationsForm()
|
||||
new NotificationsDropdown()
|
||||
when 'projects'
|
||||
|
|
|
|||
|
|
@ -70,12 +70,12 @@ class @DropzoneInput
|
|||
pasteText response.link.markdown
|
||||
return
|
||||
|
||||
error: (temp, errorMessage) ->
|
||||
error: (temp) ->
|
||||
errorAlert = $(form).find('.error-alert')
|
||||
checkIfMsgExists = errorAlert.children().length
|
||||
if checkIfMsgExists is 0
|
||||
errorAlert.append divAlert
|
||||
$(".div-dropzone-alert").append btnAlert + errorMessage
|
||||
$(".div-dropzone-alert").append "#{btnAlert}Attaching the file failed."
|
||||
return
|
||||
|
||||
totaluploadprogress: (totalUploadProgress) ->
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ window.GitLab ?= {}
|
|||
GitLab.GfmAutoComplete =
|
||||
dataLoading: false
|
||||
dataLoaded: false
|
||||
|
||||
cachedData: {}
|
||||
dataSource: ''
|
||||
|
||||
# Emoji
|
||||
|
|
@ -55,7 +55,7 @@ GitLab.GfmAutoComplete =
|
|||
@setupAtWho()
|
||||
|
||||
if @dataSource
|
||||
if !@dataLoading
|
||||
if not @dataLoading and not @cachedData
|
||||
@dataLoading = true
|
||||
|
||||
# We should wait until initializations are done
|
||||
|
|
@ -70,6 +70,8 @@ GitLab.GfmAutoComplete =
|
|||
@loadData(data)
|
||||
, 1000)
|
||||
|
||||
if @cachedData?
|
||||
@loadData(@cachedData)
|
||||
|
||||
setupAtWho: ->
|
||||
# Emoji
|
||||
|
|
@ -188,7 +190,7 @@ GitLab.GfmAutoComplete =
|
|||
callbacks:
|
||||
beforeSave: (merges) ->
|
||||
sanitizeLabelTitle = (title)->
|
||||
if /\w+\s+\w+/g.test(title)
|
||||
if /[\w\?&]+\s+[\w\?&]+/g.test(title)
|
||||
"\"#{sanitize(title)}\""
|
||||
else
|
||||
sanitize(title)
|
||||
|
|
@ -205,6 +207,7 @@ GitLab.GfmAutoComplete =
|
|||
$.getJSON(dataSource)
|
||||
|
||||
loadData: (data) ->
|
||||
@cachedData = data
|
||||
@dataLoaded = true
|
||||
|
||||
# load members
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ class GitLabDropdownFilter
|
|||
return BLUR_KEYCODES.indexOf(keyCode) >= 0
|
||||
|
||||
filter: (search_text) ->
|
||||
@options.onFilter(search_text) if @options.onFilter
|
||||
data = @options.data()
|
||||
|
||||
if data? and not @options.filterByText
|
||||
|
|
@ -195,6 +196,7 @@ class GitLabDropdown
|
|||
@filter = new GitLabDropdownFilter @filterInput,
|
||||
filterInputBlur: @filterInputBlur
|
||||
filterByText: @options.filterByText
|
||||
onFilter: @options.onFilter
|
||||
remote: @options.filterRemote
|
||||
query: @options.data
|
||||
keys: searchFields
|
||||
|
|
@ -530,7 +532,7 @@ class GitLabDropdown
|
|||
if $el.length
|
||||
e.preventDefault()
|
||||
e.stopImmediatePropagation()
|
||||
$(selector, @dropdown)[0].click()
|
||||
$el.first().trigger('click')
|
||||
|
||||
addArrowKeyEvent: ->
|
||||
ARROW_KEY_CODES = [38, 40]
|
||||
|
|
|
|||
|
|
@ -7,13 +7,16 @@ class @ImporterStatus
|
|||
$('.js-add-to-import')
|
||||
.off 'click'
|
||||
.on 'click', (e) =>
|
||||
new_namespace = null
|
||||
$btn = $(e.currentTarget)
|
||||
$tr = $btn.closest('tr')
|
||||
$target_field = $tr.find('.import-target')
|
||||
$namespace_input = $target_field.find('input')
|
||||
id = $tr.attr('id').replace('repo_', '')
|
||||
if $tr.find('.import-target input').length > 0
|
||||
new_namespace = $tr.find('.import-target input').prop('value')
|
||||
$tr.find('.import-target').empty().append("#{new_namespace} / #{$tr.find('.import-target').data('project_name')}")
|
||||
new_namespace = null
|
||||
|
||||
if $namespace_input.length > 0
|
||||
new_namespace = $namespace_input.prop('value')
|
||||
$target_field.empty().append("#{new_namespace}/#{$target_field.data('project_name')}")
|
||||
|
||||
$btn
|
||||
.disable()
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ issuable_created = false
|
|||
initTemplates: ->
|
||||
Issuable.labelRow = _.template(
|
||||
'<% _.each(labels, function(label){ %>
|
||||
<span class="label-row btn-group" role="group" aria-label="<%= _.escape(label.title) %>" style="color: <%= label.text_color %>;">
|
||||
<a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%= label.color %>;" title="<%= _.escape(label.description) %>" data-container="body">
|
||||
<%= _.escape(label.title) %>
|
||||
<span class="label-row btn-group" role="group" aria-label="<%- label.title %>" style="color: <%- label.text_color %>;">
|
||||
<a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%- label.color %>;" title="<%- label.description %>" data-container="body">
|
||||
<%- label.title %>
|
||||
</a>
|
||||
<button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%= label.color %>;" data-label="<%= _.escape(label.title) %>">
|
||||
<button type="button" class="btn btn-transparent label-remove js-label-filter-remove" style="background-color: <%- label.color %>;" data-label="<%- label.title %>">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ class @LabelsSelect
|
|||
if issueUpdateURL
|
||||
labelHTMLTemplate = _.template(
|
||||
'<% _.each(labels, function(label){ %>
|
||||
<a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%= _.escape(label.title) %>">
|
||||
<span class="label has-tooltip color-label" title="<%= _.escape(label.description) %>" style="background-color: <%= label.color %>; color: <%= label.text_color %>;">
|
||||
<%= _.escape(label.title) %>
|
||||
<a href="<%- ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%- encodeURIComponent(label.title) %>">
|
||||
<span class="label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">
|
||||
<%- label.title %>
|
||||
</span>
|
||||
</a>
|
||||
<% }); %>'
|
||||
|
|
@ -261,7 +261,7 @@ class @LabelsSelect
|
|||
$a.attr('data-label-id', label.id)
|
||||
|
||||
$a.addClass(selectedClass.join(' '))
|
||||
.html("#{colorEl} #{_.escape(label.title)}")
|
||||
.html("#{colorEl} #{label.title}")
|
||||
|
||||
# Return generated html
|
||||
$li.html($a).prop('outerHTML')
|
||||
|
|
@ -288,7 +288,7 @@ class @LabelsSelect
|
|||
fieldName: $dropdown.data('field-name')
|
||||
id: (label) ->
|
||||
if $dropdown.hasClass("js-filter-submit") and not label.isAny?
|
||||
_.escape label.title
|
||||
label.title
|
||||
else
|
||||
label.id
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
#= require cropper
|
||||
|
|
@ -5,12 +5,12 @@
|
|||
|
||||
w.gl.utils.isInGroupsPage = ->
|
||||
|
||||
return $('body').data('page').split(':')[0] is 'groups'
|
||||
return gl.utils.getPagePath() is 'groups'
|
||||
|
||||
|
||||
w.gl.utils.isInProjectPage = ->
|
||||
|
||||
return $('body').data('page').split(':')[0] is 'projects'
|
||||
return gl.utils.getPagePath() is 'projects'
|
||||
|
||||
|
||||
w.gl.utils.getProjectSlug = ->
|
||||
|
|
@ -40,6 +40,9 @@
|
|||
e.stopImmediatePropagation()
|
||||
return false
|
||||
|
||||
gl.utils.getPagePath = ->
|
||||
return $('body').data('page').split(':')[0]
|
||||
|
||||
|
||||
jQuery.timefor = (time, suffix, expiredLabel) ->
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,9 @@
|
|||
insertText = "#{startChar}#{tag}#{selected}#{if wrap then tag else ' '}"
|
||||
|
||||
if document.queryCommandSupported('insertText')
|
||||
document.execCommand 'insertText', false, insertText
|
||||
else
|
||||
inserted = document.execCommand 'insertText', false, insertText
|
||||
|
||||
unless inserted
|
||||
try
|
||||
document.execCommand("ms-beginUndoUnit")
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ class @MilestoneSelect
|
|||
|
||||
if issueUpdateURL
|
||||
milestoneLinkTemplate = _.template(
|
||||
'<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>" class="bold has-tooltip" data-container="body" title="<%= remaining %>"><%= _.escape(title) %></a>'
|
||||
'<a href="/<%- namespace %>/<%- path %>/milestones/<%- iid %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>'
|
||||
)
|
||||
|
||||
milestoneLinkNoneTemplate = '<span class="no-value">None</span>'
|
||||
|
||||
collapsedSidebarLabelTemplate = _.template(
|
||||
'<span class="has-tooltip" data-container="body" title="<%= remaining %>" data-placement="left">
|
||||
<%= _.escape(title) %>
|
||||
'<span class="has-tooltip" data-container="body" title="<%- remaining %>" data-placement="left">
|
||||
<%- title %>
|
||||
</span>'
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,56 @@
|
|||
class @NamespaceSelect
|
||||
constructor: ->
|
||||
namespaceFormatResult = (namespace) ->
|
||||
markup = "<div class='namespace-result'>"
|
||||
markup += "<span class='namespace-kind'>" + namespace.kind + "</span>"
|
||||
markup += "<span class='namespace-path'>" + namespace.path + "</span>"
|
||||
markup += "</div>"
|
||||
markup
|
||||
constructor: (opts) ->
|
||||
{
|
||||
@dropdown
|
||||
} = opts
|
||||
|
||||
formatSelection = (namespace) ->
|
||||
namespace.kind + ": " + namespace.path
|
||||
showAny = true
|
||||
fieldName = 'namespace_id'
|
||||
|
||||
$('.ajax-namespace-select').each (i, select) ->
|
||||
$(select).select2
|
||||
placeholder: "Search for namespace"
|
||||
multiple: $(select).hasClass('multiselect')
|
||||
minimumInputLength: 0
|
||||
query: (query) ->
|
||||
Api.namespaces query.term, (namespaces) ->
|
||||
data = { results: namespaces }
|
||||
query.callback(data)
|
||||
if @dropdown.attr 'data-field-name'
|
||||
fieldName = @dropdown.data 'fieldName'
|
||||
|
||||
dropdownCssClass: "ajax-namespace-dropdown"
|
||||
formatResult: namespaceFormatResult
|
||||
formatSelection: formatSelection
|
||||
if @dropdown.attr 'data-show-any'
|
||||
showAny = @dropdown.data 'showAny'
|
||||
|
||||
@dropdown.glDropdown(
|
||||
filterable: true
|
||||
selectable: true
|
||||
filterRemote: true
|
||||
search:
|
||||
fields: ['path']
|
||||
fieldName: fieldName
|
||||
toggleLabel: (selected) ->
|
||||
return if not selected.id? then selected.text else "#{selected.kind}: #{selected.path}"
|
||||
data: (term, dataCallback) ->
|
||||
Api.namespaces term, (namespaces) ->
|
||||
if showAny
|
||||
anyNamespace =
|
||||
text: 'Any namespace'
|
||||
id: null
|
||||
|
||||
namespaces.unshift(anyNamespace)
|
||||
namespaces.splice 1, 0, 'divider'
|
||||
|
||||
dataCallback(namespaces)
|
||||
text: (namespace) ->
|
||||
return if not namespace.id? then namespace.text else "#{namespace.kind}: #{namespace.path}"
|
||||
renderRow: @renderRow
|
||||
clicked: @onSelectItem
|
||||
)
|
||||
|
||||
onSelectItem: (item, el, e) =>
|
||||
e.preventDefault()
|
||||
|
||||
class @NamespaceSelects
|
||||
constructor: (opts = {}) ->
|
||||
{
|
||||
@$dropdowns = $('.js-namespace-select')
|
||||
} = opts
|
||||
|
||||
@$dropdowns.each (i, dropdown) ->
|
||||
$dropdown = $(dropdown)
|
||||
|
||||
new NamespaceSelect(
|
||||
dropdown: $dropdown
|
||||
)
|
||||
|
|
|
|||
|
|
@ -100,13 +100,40 @@ class @Notes
|
|||
$('.note .js-task-list-container').taskList('disable')
|
||||
$(document).off 'tasklist:changed', '.note .js-task-list-container'
|
||||
|
||||
keydownNoteText: (e) ->
|
||||
$this = $(this)
|
||||
if $this.val() is '' and e.which is 38 and not isMetaKey e
|
||||
myLastNote = $("li.note[data-author-id='#{gon.current_user_id}'][data-editable]:last")
|
||||
if myLastNote.length
|
||||
myLastNoteEditBtn = myLastNote.find('.js-note-edit')
|
||||
myLastNoteEditBtn.trigger('click', [true, myLastNote])
|
||||
keydownNoteText: (e) =>
|
||||
return if isMetaKey e
|
||||
|
||||
$textarea = $(e.target)
|
||||
|
||||
# Edit previous note when UP arrow is hit
|
||||
switch e.which
|
||||
when 38
|
||||
return unless $textarea.val() is ''
|
||||
|
||||
myLastNote = $("li.note[data-author-id='#{gon.current_user_id}'][data-editable]:last")
|
||||
if myLastNote.length
|
||||
myLastNoteEditBtn = myLastNote.find('.js-note-edit')
|
||||
myLastNoteEditBtn.trigger('click', [true, myLastNote])
|
||||
|
||||
# Cancel creating diff note or editing any note when ESCAPE is hit
|
||||
when 27
|
||||
discussionNoteForm = $textarea.closest('.js-discussion-note-form')
|
||||
if discussionNoteForm.length
|
||||
if $textarea.val() isnt ''
|
||||
return unless confirm('Are you sure you want to cancel creating this comment?')
|
||||
|
||||
@removeDiscussionNoteForm(discussionNoteForm)
|
||||
return
|
||||
|
||||
editNote = $textarea.closest('.note')
|
||||
if editNote.length
|
||||
originalText = $textarea.closest('form').data('original-note')
|
||||
newText = $textarea.val()
|
||||
if originalText isnt newText
|
||||
return unless confirm('Are you sure you want to cancel editing this comment?')
|
||||
|
||||
@removeNoteEditForm(editNote)
|
||||
|
||||
|
||||
isMetaKey = (e) ->
|
||||
(e.metaKey or e.ctrlKey or e.altKey or e.shiftKey)
|
||||
|
|
@ -213,12 +240,16 @@ class @Notes
|
|||
|
||||
@note_ids.push(note.id)
|
||||
form = $("#new-discussion-note-form-#{note.discussion_id}")
|
||||
if note.original_discussion_id? and form.length is 0
|
||||
form = $("#new-discussion-note-form-#{note.original_discussion_id}")
|
||||
row = form.closest("tr")
|
||||
note_html = $(note.html)
|
||||
note_html.syntaxHighlight()
|
||||
|
||||
# is this the first note of discussion?
|
||||
discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']")
|
||||
if note.original_discussion_id? and discussionContainer.length is 0
|
||||
discussionContainer = $(".notes[data-discussion-id='" + note.original_discussion_id + "']")
|
||||
if discussionContainer.length is 0
|
||||
# insert the note and the reply button after the temp row
|
||||
row.after note.discussion_html
|
||||
|
|
@ -291,6 +322,7 @@ class @Notes
|
|||
form.addClass "js-main-target-form"
|
||||
|
||||
form.find("#note_line_code").remove()
|
||||
form.find("#note_position").remove()
|
||||
form.find("#note_type").remove()
|
||||
|
||||
###
|
||||
|
|
@ -308,10 +340,12 @@ class @Notes
|
|||
|
||||
new Autosave textarea, [
|
||||
"Note"
|
||||
form.find("#note_commit_id").val()
|
||||
form.find("#note_line_code").val()
|
||||
form.find("#note_noteable_type").val()
|
||||
form.find("#note_noteable_id").val()
|
||||
form.find("#note_commit_id").val()
|
||||
form.find("#note_type").val()
|
||||
form.find("#note_line_code").val()
|
||||
form.find("#note_position").val()
|
||||
]
|
||||
|
||||
###
|
||||
|
|
@ -401,9 +435,12 @@ class @Notes
|
|||
|
||||
Hides edit form and restores the original note text to the editor textarea.
|
||||
###
|
||||
cancelEdit: (e) ->
|
||||
cancelEdit: (e) =>
|
||||
e.preventDefault()
|
||||
note = $(this).closest(".note")
|
||||
note = $(e.target).closest('.note')
|
||||
@removeNoteEditForm(note)
|
||||
|
||||
removeNoteEditForm: (note) ->
|
||||
form = note.find(".current-note-edit-form")
|
||||
note.removeClass "is-editting"
|
||||
form.removeClass("current-note-edit-form")
|
||||
|
|
@ -482,10 +519,12 @@ class @Notes
|
|||
setupDiscussionNoteForm: (dataHolder, form) =>
|
||||
# setup note target
|
||||
form.attr 'id', "new-discussion-note-form-#{dataHolder.data("discussionId")}"
|
||||
form.attr "data-line-code", dataHolder.data("lineCode")
|
||||
form.find("#note_type").val dataHolder.data("noteType")
|
||||
form.find("#line_type").val dataHolder.data("lineType")
|
||||
form.find("#note_commit_id").val dataHolder.data("commitId")
|
||||
form.find("#note_line_code").val dataHolder.data("lineCode")
|
||||
form.find("#note_position").val dataHolder.attr("data-position")
|
||||
form.find("#note_noteable_type").val dataHolder.data("noteableType")
|
||||
form.find("#note_noteable_id").val dataHolder.data("noteableId")
|
||||
form.find('.js-note-discard')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
#
|
||||
#= require_tree .
|
||||
|
|
@ -78,3 +78,6 @@ $ ->
|
|||
|
||||
if comment && comment.length > 1 && $title.val() == ''
|
||||
$title.val(comment[1]).change()
|
||||
|
||||
if gl.utils.getPagePath() == 'profiles'
|
||||
new Profile()
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
class @ProtectedBranchSelect
|
||||
constructor: (currentProject) ->
|
||||
$('.dropdown-footer').hide();
|
||||
@dropdown = $('.js-protected-branch-select').glDropdown(
|
||||
data: @getProtectedBranches
|
||||
filterable: true
|
||||
remote: false
|
||||
search:
|
||||
fields: ['title']
|
||||
selectable: true
|
||||
toggleLabel: (selected) -> if (selected and 'id' of selected) then selected.title else 'Protected Branch'
|
||||
fieldName: 'protected_branch[name]'
|
||||
text: (protected_branch) -> _.escape(protected_branch.title)
|
||||
id: (protected_branch) -> _.escape(protected_branch.id)
|
||||
onFilter: @toggleCreateNewButton
|
||||
clicked: () -> $('.protect-branch-btn').attr('disabled', false)
|
||||
)
|
||||
|
||||
$('.create-new-protected-branch').on 'click', (event) =>
|
||||
# Refresh the dropdown's data, which ends up calling `getProtectedBranches`
|
||||
@dropdown.data('glDropdown').remote.execute()
|
||||
@dropdown.data('glDropdown').selectRowAtIndex(event, 0)
|
||||
|
||||
getProtectedBranches: (term, callback) =>
|
||||
if @selectedBranch
|
||||
callback(gon.open_branches.concat(@selectedBranch))
|
||||
else
|
||||
callback(gon.open_branches)
|
||||
|
||||
toggleCreateNewButton: (branchName) =>
|
||||
@selectedBranch = { title: branchName, id: branchName, text: branchName }
|
||||
|
||||
if branchName is ''
|
||||
$('.protected-branch-select-footer-list').addClass('hidden')
|
||||
$('.dropdown-footer').hide();
|
||||
else
|
||||
$('.create-new-protected-branch').text("Create Protected Branch: #{branchName}")
|
||||
$('.protected-branch-select-footer-list').removeClass('hidden')
|
||||
$('.dropdown-footer').show();
|
||||
|
||||
|
|
@ -11,7 +11,8 @@ $ ->
|
|||
dataType: "json"
|
||||
data:
|
||||
id: id
|
||||
developers_can_push: checked
|
||||
protected_branch:
|
||||
developers_can_push: checked
|
||||
|
||||
success: ->
|
||||
row = $(e.target)
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ class @UsersSelect
|
|||
|
||||
collapsedAssigneeTemplate = _.template(
|
||||
'<% if( avatar ) { %>
|
||||
<a class="author_link" href="/u/<%= username %>">
|
||||
<img width="24" class="avatar avatar-inline s24" alt="" src="<%= avatar %>">
|
||||
<a class="author_link" href="/u/<%- username %>">
|
||||
<img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>">
|
||||
<span class="author">Toni Boehm</span>
|
||||
</a>
|
||||
<% } else { %>
|
||||
|
|
@ -72,13 +72,13 @@ class @UsersSelect
|
|||
|
||||
assigneeTemplate = _.template(
|
||||
'<% if (username) { %>
|
||||
<a class="author_link bold" href="/u/<%= username %>">
|
||||
<a class="author_link bold" href="/u/<%- username %>">
|
||||
<% if( avatar ) { %>
|
||||
<img width="32" class="avatar avatar-inline s32" alt="" src="<%= avatar %>">
|
||||
<img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>">
|
||||
<% } %>
|
||||
<span class="author"><%= name %></span>
|
||||
<span class="author"><%- name %></span>
|
||||
<span class="username">
|
||||
@<%= username %>
|
||||
@<%- username %>
|
||||
</span>
|
||||
</a>
|
||||
<% } else { %>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
.blank-state-welcome {
|
||||
text-align: center;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.blank-state-text {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.blank-state {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
|
|
@ -6,7 +15,15 @@
|
|||
|
||||
.blank-state-no-icon {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.blank-state-icon {
|
||||
padding-bottom: 20px;
|
||||
|
||||
path {
|
||||
fill: $gray-darkest;
|
||||
}
|
||||
}
|
||||
|
||||
.blank-state-title {
|
||||
|
|
@ -21,3 +38,7 @@
|
|||
margin-bottom: $gl-padding;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.blank-state-welcome-title {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -281,3 +281,21 @@
|
|||
color: $gl-icon-color;
|
||||
}
|
||||
}
|
||||
|
||||
.clone-dropdown-btn a {
|
||||
color: $dropdown-link-color;
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-static {
|
||||
background-color: $background-color !important;
|
||||
border: 1px solid lightgrey;
|
||||
cursor: default;
|
||||
&:active {
|
||||
-moz-box-shadow: inset 0 0 0 white;
|
||||
-webkit-box-shadow: inset 0 0 0 white;
|
||||
box-shadow: inset 0 0 0 white;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,12 @@
|
|||
}
|
||||
|
||||
.open {
|
||||
.dropdown-menu {
|
||||
.dropdown-menu,
|
||||
.dropdown-menu-nav {
|
||||
display: block;
|
||||
@media (max-width: $screen-xs-max) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-toggle {
|
||||
|
|
@ -64,9 +68,14 @@
|
|||
color: $dropdown-toggle-hover-icon-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.large {
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
.dropdown-menu,
|
||||
.dropdown-menu-nav {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
|
|
@ -77,7 +86,7 @@
|
|||
margin-bottom: 0;
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
padding: 10px 0;
|
||||
padding: 8px 0;
|
||||
background-color: $dropdown-bg;
|
||||
border: 1px solid $dropdown-border-color;
|
||||
border-radius: $border-radius-base;
|
||||
|
|
@ -101,12 +110,12 @@
|
|||
li {
|
||||
text-align: left;
|
||||
list-style: none;
|
||||
padding: 0 10px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
margin: 8px 10px;
|
||||
margin: 8px;
|
||||
padding: 0;
|
||||
background-color: $dropdown-divider-color;
|
||||
}
|
||||
|
|
@ -122,7 +131,7 @@
|
|||
a {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: 5px 10px;
|
||||
padding: 5px 8px;
|
||||
color: $dropdown-link-color;
|
||||
line-height: initial;
|
||||
text-overflow: ellipsis;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
}
|
||||
|
||||
a:not(.btn) {
|
||||
color: $gl-dark-link-color;
|
||||
color: $gl-text-color;
|
||||
}
|
||||
|
||||
.left-options {
|
||||
|
|
|
|||
|
|
@ -20,17 +20,6 @@
|
|||
|
||||
.sidebar-wrapper {
|
||||
background: $color-darker;
|
||||
|
||||
.sidebar-user {
|
||||
background: $color-darker;
|
||||
color: $color-light;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-dark;
|
||||
color: $white-light;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-sidebar li {
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ header {
|
|||
margin: ($header-height - 28) / 2 0;
|
||||
margin-left: 10px;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
min-width: 28px;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
|
||||
|
|
@ -241,14 +241,23 @@ header {
|
|||
.navbar-collapse {
|
||||
padding-left: 5px;
|
||||
|
||||
li {
|
||||
.nav > li {
|
||||
display: table-cell;
|
||||
width: 1%;
|
||||
|
||||
a {
|
||||
margin-left: 8px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-user {
|
||||
.dropdown-menu-nav {
|
||||
width: 140px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-user-avatar {
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,6 +137,15 @@ ul.content-list {
|
|||
padding-top: 1px;
|
||||
float: right;
|
||||
|
||||
> .control-text {
|
||||
margin-right: $gl-padding-top;
|
||||
line-height: 40px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> .btn,
|
||||
> .btn-group {
|
||||
margin-right: $gl-padding-top;
|
||||
|
|
@ -166,6 +175,12 @@ ul.content-list {
|
|||
|
||||
.panel > .content-list > li {
|
||||
padding: $gl-padding-top $gl-padding;
|
||||
|
||||
&.commit {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
padding-left: 46px + $gl-padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul.controls {
|
||||
|
|
|
|||
|
|
@ -77,10 +77,10 @@
|
|||
|
||||
&.sub-nav {
|
||||
text-align: center;
|
||||
background-color: $background-color;
|
||||
background-color: $dark-background-color;
|
||||
|
||||
.container-fluid {
|
||||
background-color: $background-color;
|
||||
background-color: $dark-background-color;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +134,11 @@
|
|||
margin-bottom: 0;
|
||||
border-bottom: none;
|
||||
|
||||
&.wide {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
li a {
|
||||
padding: 16px 10px 11px;
|
||||
}
|
||||
|
|
@ -164,6 +169,7 @@
|
|||
> .btn {
|
||||
margin-right: $gl-padding-top;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,12 @@
|
|||
padding-bottom: 25px;
|
||||
transition: padding $sidebar-transition-duration;
|
||||
|
||||
&.page-sidebar-pinned {
|
||||
.sidebar-wrapper {
|
||||
@include box-shadow(none);
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
|
@ -11,6 +17,7 @@
|
|||
height: 100%;
|
||||
overflow: hidden;
|
||||
transition: width $sidebar-transition-duration;
|
||||
@include box-shadow(2px 0 16px 0 #bbb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -40,32 +47,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
.sidebar-user {
|
||||
padding: 15px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: $sidebar_width;
|
||||
overflow: hidden;
|
||||
font-size: 16px;
|
||||
line-height: 36px;
|
||||
transition: width $sidebar-transition-duration, padding $sidebar-transition-duration;
|
||||
|
||||
@media (min-width: $sidebar-breakpoint) {
|
||||
bottom: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-sidebar {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
bottom: 65px;
|
||||
bottom: 0;
|
||||
width: $sidebar_width;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
|
||||
@media (min-width: $sidebar-breakpoint) {
|
||||
bottom: 115px;
|
||||
bottom: 50px;
|
||||
}
|
||||
|
||||
&.navbar-collapse {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@ $sidebar-breakpoint: 1024px;
|
|||
/*
|
||||
* UI elements
|
||||
*/
|
||||
$border-color: #e5e5e5;
|
||||
$focus-border-color: #3aabf0;
|
||||
$table-border-color: #f0f0f0;
|
||||
$background-color: #fafafa;
|
||||
$border-color: #e5e5e5;
|
||||
$focus-border-color: #3aabf0;
|
||||
$table-border-color: #f0f0f0;
|
||||
$background-color: #fafafa;
|
||||
$dark-background-color: #f7f7f7;
|
||||
|
||||
/*
|
||||
* Text
|
||||
|
|
@ -153,9 +154,6 @@ $warning-message-bg: #fbf2d9;
|
|||
$warning-message-color: #9e8e60;
|
||||
$warning-message-border: #f0e2bb;
|
||||
|
||||
/* header */
|
||||
$light-grey-header: #faf9f9;
|
||||
|
||||
/* tanuki logo colors */
|
||||
$tanuki-red: #e24329;
|
||||
$tanuki-orange: #fc6d26;
|
||||
|
|
|
|||
|
|
@ -71,3 +71,36 @@
|
|||
@extend .broadcast-message;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
// Users List
|
||||
|
||||
.users-list {
|
||||
.user-row {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.user-details {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.controls {
|
||||
> .btn, > .dropdown {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
.btn-block {
|
||||
margin-bottom: 0;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -434,13 +434,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.discussion {
|
||||
.diff-content {
|
||||
.diff-line-num {
|
||||
&:before {
|
||||
content: attr(data-linenumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,39 @@
|
|||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
&.group-admin {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
|
||||
.group-avatar, .group-details, .group-controls {
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.group-details {
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.group-controls {
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.ldap-group-links {
|
||||
.form-actions {
|
||||
margin-bottom: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.groups-cover-block {
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ form.edit-issue {
|
|||
.merge-request,
|
||||
.issue {
|
||||
&.today {
|
||||
background: #efe;
|
||||
border-color: #cec;
|
||||
background: #f8feef;
|
||||
border-color: #e1e8d5;
|
||||
}
|
||||
|
||||
&.closed {
|
||||
|
|
|
|||
|
|
@ -167,7 +167,8 @@
|
|||
|
||||
.commit {
|
||||
margin: 0;
|
||||
padding: 2px 0;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
list-style: none;
|
||||
&:hover {
|
||||
background: none;
|
||||
|
|
|
|||
|
|
@ -64,86 +64,49 @@
|
|||
}
|
||||
|
||||
.project-home-panel {
|
||||
background: $white-light;
|
||||
text-align: left;
|
||||
padding: 24px 0;
|
||||
padding-top: 24px;
|
||||
padding-bottom: 24px;
|
||||
|
||||
.container-fluid {
|
||||
position: relative;
|
||||
|
||||
@media (min-width: $screen-lg-min) {
|
||||
.row {
|
||||
display: flex;
|
||||
-ms-flex-align: center;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
}
|
||||
}
|
||||
@media (min-width: $screen-sm-min) {
|
||||
border-bottom: 1px solid $border-color;
|
||||
}
|
||||
|
||||
.cover-controls {
|
||||
.project-settings-dropdown {
|
||||
margin-left: 10px;
|
||||
display: inline-block;
|
||||
|
||||
.dropdown-menu {
|
||||
left: auto;
|
||||
width: auto;
|
||||
right: 0;
|
||||
max-width: 240px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cover-title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.project-image-container {
|
||||
@include make-sm-column(1);
|
||||
max-width: 86px;
|
||||
min-width: 86px;
|
||||
padding-right: 0;
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
padding-left: 0;
|
||||
margin: 0 0 10px;
|
||||
max-width: none;
|
||||
min-width: none;
|
||||
|
||||
.avatar.s70 {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project-info {
|
||||
@include make-sm-column(10);
|
||||
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.project-home-desc {
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.identicon {
|
||||
float: left;
|
||||
@include border-radius(50%);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
.project-avatar {
|
||||
float: none;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
&.identicon {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.project-title {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
|
||||
.fa {
|
||||
margin-left: 2px;
|
||||
font-size: 12px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.project-home-desc {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 15px;
|
||||
max-width: 480px;
|
||||
|
||||
> p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.notifications-btn {
|
||||
|
||||
.fa-bell,
|
||||
.fa-spinner {
|
||||
margin-right: 6px;
|
||||
|
|
@ -153,127 +116,106 @@
|
|||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.project-repo-buttons {
|
||||
font-size: 0;
|
||||
.project-repo-buttons {
|
||||
font-size: 0;
|
||||
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
padding: 3px 10px;
|
||||
text-transform: none;
|
||||
background-color: $background-color;
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
padding: 3px 10px;
|
||||
|
||||
.fa {
|
||||
color: $layout-link-gray;
|
||||
}
|
||||
|
||||
.fa-caret-down {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.fa {
|
||||
color: $layout-link-gray;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-left: 10px;
|
||||
.fa-caret-down {
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.count-buttons {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 16px;
|
||||
.project-repo-btn-group,
|
||||
.notification-dropdown {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.count-buttons {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.project-clone-holder {
|
||||
display: inline-block;
|
||||
|
||||
input {
|
||||
height: 29px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-clone-holder {
|
||||
display: inline-block;
|
||||
margin-top: 16px;
|
||||
.count-with-arrow {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin-left: 4px;
|
||||
|
||||
input {
|
||||
height: 29px;
|
||||
}
|
||||
}
|
||||
|
||||
.count-with-arrow {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin-left: 4px;
|
||||
|
||||
.arrow {
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -6px;
|
||||
border-width: 7px 5px 7px 0;
|
||||
border-right-color: #dce0e5;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
top: 50%;
|
||||
left: 1px;
|
||||
margin-top: -9px;
|
||||
border-width: 10px 7px 10px 0;
|
||||
border-right-color: #fff;
|
||||
}
|
||||
}
|
||||
.count {
|
||||
@include btn-gray;
|
||||
.arrow {
|
||||
&:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
background: white;
|
||||
border-radius: 2px;
|
||||
border-width: 1px;
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
line-height: 13px;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
letter-spacing: .4px;
|
||||
padding: 7px 14px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
touch-action: manipulation;
|
||||
cursor: pointer;
|
||||
background-image: none;
|
||||
white-space: nowrap;
|
||||
margin: 0 10px 0 4px;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -6px;
|
||||
border-width: 7px 5px 7px 0;
|
||||
border-right-color: #dce0e5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #fff;
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
top: 50%;
|
||||
left: 1px;
|
||||
margin-top: -9px;
|
||||
border-width: 10px 7px 10px 0;
|
||||
border-right-color: #fff;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.count {
|
||||
@include btn-gray;
|
||||
display: inline-block;
|
||||
background: white;
|
||||
border-radius: 2px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
line-height: 13px;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
letter-spacing: .4px;
|
||||
padding: 7px 14px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
touch-action: manipulation;
|
||||
background-image: none;
|
||||
white-space: nowrap;
|
||||
margin: 0 10px 0 4px;
|
||||
|
||||
.project-right-buttons {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
bottom: 0;
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: $screen-md-max) {
|
||||
text-align: center;
|
||||
|
||||
.project-info,
|
||||
.project-image-container {
|
||||
width: 100%;
|
||||
&:hover {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -421,36 +363,42 @@ a.deploy-project-label {
|
|||
}
|
||||
|
||||
.project-stats {
|
||||
margin-top: $gl-padding;
|
||||
margin-bottom: 0;
|
||||
padding: 0;
|
||||
background-color: $white-light;
|
||||
font-size: 0;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
ul.nav {
|
||||
display: inline-block;
|
||||
.nav {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.nav li {
|
||||
.nav > li {
|
||||
display: inline-block;
|
||||
margin: 16px 0;
|
||||
margin-right: 16px;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: $gl-padding;
|
||||
}
|
||||
|
||||
&.project-repo-buttons-right {
|
||||
margin-top: 10px;
|
||||
|
||||
@media (min-width: $screen-md-min) {
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav > li > a {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
padding: 5px 10px;
|
||||
font-size: 15px;
|
||||
line-height: 29px;
|
||||
color: $notes-light-color;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
a {
|
||||
float: left;
|
||||
font-size: 17px;
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: darken($notes-light-color, 15%);
|
||||
}
|
||||
}
|
||||
|
||||
li.missing {
|
||||
|
|
@ -458,6 +406,8 @@ a.deploy-project-label {
|
|||
border-radius: $border-radius-default;
|
||||
|
||||
a {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
color: $notes-light-color;
|
||||
display: block;
|
||||
}
|
||||
|
|
@ -466,10 +416,6 @@ a.deploy-project-label {
|
|||
background-color: $gray-normal;
|
||||
}
|
||||
}
|
||||
|
||||
&.row-content-block.second-block {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
pre.light-well {
|
||||
|
|
@ -529,10 +475,6 @@ pre.light-well {
|
|||
a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
> span {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -557,8 +499,32 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.project-last-commit {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
margin-top: $gl-padding;
|
||||
}
|
||||
|
||||
&.container-fluid {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
background-color: $background-color;
|
||||
border: 1px solid $border-color;
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
border-right-width: 1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&.container-limited {
|
||||
@media (min-width: 1281px) {
|
||||
border-radius: $border-radius-base;
|
||||
}
|
||||
}
|
||||
|
||||
.ci-status {
|
||||
margin-right: 16px;
|
||||
margin-right: $gl-padding;
|
||||
}
|
||||
|
||||
.commit-row-message {
|
||||
|
|
@ -566,19 +532,12 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.commit_short_id {
|
||||
margin: 0 5px;
|
||||
margin-right: 5px;
|
||||
color: $gl-link-color;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.commit-author-link {
|
||||
margin-left: 7px;
|
||||
text-decoration: none;
|
||||
.avatar {
|
||||
float: none;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.commit-author-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
@ -601,15 +560,10 @@ pre.light-well {
|
|||
}
|
||||
|
||||
.git-clone-holder {
|
||||
width: 498px;
|
||||
width: 380px;
|
||||
|
||||
.btn-clipboard {
|
||||
border: 1px solid $border-color;
|
||||
padding: 6px $gl-padding;
|
||||
}
|
||||
|
||||
.project-home-dropdown + & {
|
||||
margin-right: 45px;
|
||||
}
|
||||
|
||||
.clone-options {
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@
|
|||
margin-top: 5px;
|
||||
|
||||
@media (min-width: $screen-sm-min) {
|
||||
width: 160px;
|
||||
width: 180px;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
:version_check_enabled,
|
||||
:admin_notification_email,
|
||||
:user_oauth_applications,
|
||||
:user_default_external,
|
||||
:shared_runners_enabled,
|
||||
:shared_runners_text,
|
||||
:max_artifacts_size,
|
||||
|
|
@ -110,6 +111,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
:send_user_confirmation_email,
|
||||
:container_registry_token_expire_delay,
|
||||
:repository_storage,
|
||||
:enabled_git_access_protocol,
|
||||
restricted_visibility_levels: [],
|
||||
import_sources: [],
|
||||
disabled_oauth_sign_in_sources: []
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ class Admin::GroupsController < Admin::ApplicationController
|
|||
|
||||
def show
|
||||
@members = @group.members.order("access_level DESC").page(params[:members_page])
|
||||
@requesters = @group.requesters
|
||||
@projects = @group.projects.page(params[:projects_page])
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ class Admin::HooksController < Admin::ApplicationController
|
|||
redirect_to admin_hooks_path
|
||||
end
|
||||
|
||||
|
||||
def test
|
||||
@hook = SystemHook.find(params[:hook_id])
|
||||
data = {
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
def index
|
||||
@projects = Project.all
|
||||
@projects = @projects.in_namespace(params[:namespace_id]) if params[:namespace_id].present?
|
||||
@projects = @projects.where("projects.visibility_level IN (?)", params[:visibility_levels]) if params[:visibility_levels].present?
|
||||
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
|
||||
@projects = @projects.with_push if params[:with_push].present?
|
||||
@projects = @projects.abandoned if params[:abandoned].present?
|
||||
@projects = @projects.where(last_repository_check_failed: true) if params[:last_repository_check_failed].present?
|
||||
@projects = @projects.non_archived unless params[:with_archived].present?
|
||||
@projects = @projects.non_archived unless params[:archived].present?
|
||||
@projects = @projects.personal(current_user) if params[:personal].present?
|
||||
@projects = @projects.search(params[:name]) if params[:name].present?
|
||||
@projects = @projects.sort(@sort = params[:sort])
|
||||
@projects = @projects.includes(:namespace).order("namespaces.path, projects.name ASC").page(params[:page])
|
||||
|
|
@ -20,7 +21,8 @@ class Admin::ProjectsController < Admin::ApplicationController
|
|||
@group_members = @group.members.order("access_level DESC").page(params[:group_members_page])
|
||||
end
|
||||
|
||||
@project_members = @project.project_members.page(params[:project_members_page])
|
||||
@project_members = @project.members.page(params[:project_members_page])
|
||||
@requesters = @project.requesters
|
||||
end
|
||||
|
||||
def transfer
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module MembershipActions
|
|||
end
|
||||
|
||||
def approve_access_request
|
||||
@member = membershipable.members.request.find(params[:id])
|
||||
@member = membershipable.requesters.find(params[:id])
|
||||
|
||||
return render_403 unless can?(current_user, action_member_permission(:update, @member), @member)
|
||||
|
||||
|
|
@ -20,7 +20,8 @@ module MembershipActions
|
|||
end
|
||||
|
||||
def leave
|
||||
@member = membershipable.members.find_by(user_id: current_user)
|
||||
@member = membershipable.members.find_by(user_id: current_user) ||
|
||||
membershipable.requesters.find_by(user_id: current_user)
|
||||
Members::DestroyService.new(@member, current_user).execute
|
||||
|
||||
source_type = @member.real_source_type.humanize(capitalize: false)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class ConfirmationsController < Devise::ConfirmationsController
|
||||
|
||||
def almost_there
|
||||
flash[:notice] = nil
|
||||
render layout: "devise_empty"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
def index
|
||||
@project = @group.projects.find(params[:project_id]) if params[:project_id]
|
||||
@members = @group.group_members
|
||||
@members = @members.non_pending unless can?(current_user, :admin_group, @group)
|
||||
@members = @members.non_invite unless can?(current_user, :admin_group, @group)
|
||||
|
||||
if params[:search].present?
|
||||
users = @group.users.search(params[:search]).to_a
|
||||
|
|
@ -15,6 +15,7 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
@members = @members.order('access_level DESC').page(params[:page]).per(50)
|
||||
@requesters = @group.requesters if can?(current_user, :admin_group, @group)
|
||||
|
||||
@group_member = @group.group_members.new
|
||||
end
|
||||
|
|
@ -34,7 +35,8 @@ class Groups::GroupMembersController < Groups::ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
@group_member = @group.group_members.find(params[:id])
|
||||
@group_member = @group.members.find_by(id: params[:id]) ||
|
||||
@group.requesters.find_by(id: params[:id])
|
||||
|
||||
Members::DestroyService.new(@group_member, current_user).execute
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class Import::BaseController < ApplicationController
|
||||
|
||||
private
|
||||
|
||||
def get_or_create_namespace
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ class Import::FogbugzController < Import::BaseController
|
|||
rescue_from Fogbugz::AuthenticationException, with: :fogbugz_unauthorized
|
||||
|
||||
def new
|
||||
|
||||
end
|
||||
|
||||
def callback
|
||||
|
|
@ -22,7 +21,6 @@ class Import::FogbugzController < Import::BaseController
|
|||
end
|
||||
|
||||
def new_user_map
|
||||
|
||||
end
|
||||
|
||||
def create_user_map
|
||||
|
|
|
|||
|
|
@ -27,10 +27,7 @@ class Import::GitlabProjectsController < Import::BaseController
|
|||
notice: "Project '#{@project.name}' is being imported."
|
||||
)
|
||||
else
|
||||
redirect_to(
|
||||
new_import_gitlab_project_path,
|
||||
alert: "Project could not be imported: #{@project.errors.full_messages.join(', ')}"
|
||||
)
|
||||
redirect_back_or_default(options: { alert: "Project could not be imported: #{@project.errors.full_messages.join(', ')}" })
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -44,5 +44,4 @@ class Import::GitoriousController < Import::BaseController
|
|||
def verify_gitorious_import_enabled
|
||||
render_404 unless gitorious_import_enabled?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ class Import::GoogleCodeController < Import::BaseController
|
|||
before_action :user_map, only: [:new_user_map, :create_user_map]
|
||||
|
||||
def new
|
||||
|
||||
end
|
||||
|
||||
def callback
|
||||
|
|
@ -34,7 +33,6 @@ class Import::GoogleCodeController < Import::BaseController
|
|||
end
|
||||
|
||||
def new_user_map
|
||||
|
||||
end
|
||||
|
||||
def create_user_map
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ class InvitesController < ApplicationController
|
|||
respond_to :html
|
||||
|
||||
def show
|
||||
|
||||
end
|
||||
|
||||
def accept
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
|
||||
diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
|
||||
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines)
|
||||
@diff_lines = Gitlab::Diff::Highlight.new(diff_lines).highlight
|
||||
@diff_lines = Gitlab::Diff::Highlight.new(diff_lines, repository: @repository).highlight
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ class Projects::CommitController < Projects::ApplicationController
|
|||
opts[:ignore_whitespace_change] = true if params[:format] == 'diff'
|
||||
|
||||
@diffs = commit.diffs(opts)
|
||||
@diff_refs = [commit.parent || commit, commit]
|
||||
@notes_count = commit.notes.count
|
||||
|
||||
@statuses = CommitStatus.where(pipeline: pipelines)
|
||||
|
|
|
|||
|
|
@ -14,14 +14,22 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
|
||||
def show
|
||||
compare = CompareService.new.
|
||||
execute(@project, @head_ref, @project, @base_ref, diff_options)
|
||||
execute(@project, @head_ref, @project, @start_ref, diff_options)
|
||||
|
||||
if compare
|
||||
@commits = Commit.decorate(compare.commits, @project)
|
||||
|
||||
@start_commit = @project.commit(@start_ref)
|
||||
@commit = @project.commit(@head_ref)
|
||||
@base_commit = @project.merge_base_commit(@base_ref, @head_ref)
|
||||
@base_commit = @project.merge_base_commit(@start_ref, @head_ref)
|
||||
|
||||
@diffs = compare.diffs(diff_options)
|
||||
@diff_refs = [@base_commit, @commit]
|
||||
@diff_refs = Gitlab::Diff::DiffRefs.new(
|
||||
base_sha: @base_commit.try(:sha),
|
||||
start_sha: @start_commit.try(:sha),
|
||||
head_sha: @commit.try(:sha)
|
||||
)
|
||||
|
||||
@diff_notes_disabled = true
|
||||
@grouped_diff_notes = {}
|
||||
end
|
||||
|
|
@ -35,12 +43,12 @@ class Projects::CompareController < Projects::ApplicationController
|
|||
private
|
||||
|
||||
def assign_ref_vars
|
||||
@base_ref = Addressable::URI.unescape(params[:from])
|
||||
@start_ref = Addressable::URI.unescape(params[:from])
|
||||
@ref = @head_ref = Addressable::URI.unescape(params[:to])
|
||||
end
|
||||
|
||||
def merge_request
|
||||
@merge_request ||= @project.merge_requests.opened.
|
||||
find_by(source_project: @project, source_branch: @head_ref, target_branch: @base_ref)
|
||||
find_by(source_project: @project, source_branch: @head_ref, target_branch: @start_ref)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
# This file should be identical in GitLab Community Edition and Enterprise Edition
|
||||
|
||||
class Projects::GitHttpController < Projects::ApplicationController
|
||||
include ActionController::HttpAuthentication::Basic
|
||||
include KerberosSpnegoHelper
|
||||
|
||||
attr_reader :user
|
||||
|
||||
# Git clients will not know what authenticity token to send along
|
||||
|
|
@ -14,6 +19,8 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
render_ok
|
||||
elsif receive_pack? && receive_pack_allowed?
|
||||
render_ok
|
||||
elsif http_blocked?
|
||||
render_not_allowed
|
||||
else
|
||||
render_not_found
|
||||
end
|
||||
|
|
@ -40,9 +47,12 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
private
|
||||
|
||||
def authenticate_user
|
||||
return if project && project.public? && upload_pack?
|
||||
if project && project.public? && upload_pack?
|
||||
return # Allow access
|
||||
end
|
||||
|
||||
authenticate_or_request_with_http_basic do |login, password|
|
||||
if allow_basic_auth? && basic_auth_provided?
|
||||
login, password = user_name_and_password(request)
|
||||
auth_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip)
|
||||
|
||||
if auth_result.type == :ci && upload_pack?
|
||||
|
|
@ -53,8 +63,31 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
@user = auth_result.user
|
||||
end
|
||||
|
||||
ci? || user
|
||||
if ci? || user
|
||||
return # Allow access
|
||||
end
|
||||
elsif allow_kerberos_spnego_auth? && spnego_provided?
|
||||
@user = find_kerberos_user
|
||||
|
||||
if user
|
||||
send_final_spnego_response
|
||||
return # Allow access
|
||||
end
|
||||
end
|
||||
|
||||
send_challenges
|
||||
render plain: "HTTP Basic: Access denied\n", status: 401
|
||||
end
|
||||
|
||||
def basic_auth_provided?
|
||||
has_basic_credentials?(request)
|
||||
end
|
||||
|
||||
def send_challenges
|
||||
challenges = []
|
||||
challenges << 'Basic realm="GitLab"' if allow_basic_auth?
|
||||
challenges << spnego_challenge if allow_kerberos_spnego_auth?
|
||||
headers['Www-Authenticate'] = challenges.join("\n") if challenges.any?
|
||||
end
|
||||
|
||||
def ensure_project_found!
|
||||
|
|
@ -120,7 +153,11 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def render_not_found
|
||||
render text: 'Not Found', status: :not_found
|
||||
render plain: 'Not Found', status: :not_found
|
||||
end
|
||||
|
||||
def render_not_allowed
|
||||
render plain: download_access.message, status: :forbidden
|
||||
end
|
||||
|
||||
def ci?
|
||||
|
|
@ -131,12 +168,28 @@ class Projects::GitHttpController < Projects::ApplicationController
|
|||
return false unless Gitlab.config.gitlab_shell.upload_pack
|
||||
|
||||
if user
|
||||
Gitlab::GitAccess.new(user, project).download_access_check.allowed?
|
||||
download_access.allowed?
|
||||
else
|
||||
ci? || project.public?
|
||||
end
|
||||
end
|
||||
|
||||
def access
|
||||
return @access if defined?(@access)
|
||||
|
||||
@access = Gitlab::GitAccess.new(user, project, 'http')
|
||||
end
|
||||
|
||||
def download_access
|
||||
return @download_access if defined?(@download_access)
|
||||
|
||||
@download_access = access.check('git-upload-pack')
|
||||
end
|
||||
|
||||
def http_blocked?
|
||||
!access.protocol_allowed?
|
||||
end
|
||||
|
||||
def receive_pack_allowed?
|
||||
return false unless Gitlab.config.gitlab_shell.receive_pack
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,6 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
render json: @issue.to_json(include: [:milestone, :labels])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
:edit, :update, :show, :diffs, :commits, :builds, :merge, :merge_check,
|
||||
:ci_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip
|
||||
]
|
||||
before_action :closes_issues, only: [:edit, :update, :show, :diffs, :commits, :builds]
|
||||
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds]
|
||||
before_action :define_show_vars, only: [:show, :diffs, :commits, :builds]
|
||||
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
|
||||
|
|
@ -53,19 +52,19 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@note_counts = Note.where(commit_id: @merge_request.commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json { render json: @merge_request }
|
||||
format.patch do
|
||||
headers.store(*Gitlab::Workhorse.send_git_patch(@project.repository,
|
||||
@merge_request.diff_base_commit.id,
|
||||
@merge_request.last_commit.id))
|
||||
headers['Content-Disposition'] = 'inline'
|
||||
head :ok
|
||||
|
||||
format.json do
|
||||
render json: @merge_request
|
||||
end
|
||||
|
||||
format.patch do
|
||||
return render_404 unless @merge_request.diff_refs
|
||||
|
||||
send_git_patch @project.repository, @merge_request.diff_refs
|
||||
end
|
||||
|
||||
format.diff do
|
||||
return render_404 unless @merge_request.diff_refs
|
||||
|
||||
|
|
@ -77,18 +76,17 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
def diffs
|
||||
apply_diff_view_cookie!
|
||||
|
||||
@commit = @merge_request.last_commit
|
||||
@base_commit = @merge_request.diff_base_commit
|
||||
@merge_request_diff = @merge_request.merge_request_diff
|
||||
|
||||
# MRs created before 8.4 don't have a diff_base_commit,
|
||||
# but we need it for the "View file @ ..." link by deleted files
|
||||
@base_commit ||= @merge_request.first_commit.parent || @merge_request.first_commit
|
||||
@commit = @merge_request.diff_head_commit
|
||||
@base_commit = @merge_request.diff_base_commit || @merge_request.likely_diff_base_commit
|
||||
|
||||
@comments_target = {
|
||||
noteable_type: 'MergeRequest',
|
||||
noteable_id: @merge_request.id
|
||||
}
|
||||
|
||||
@use_legacy_diff_notes = !@merge_request.support_new_diff_notes?
|
||||
@grouped_diff_notes = @merge_request.notes.grouped_diff_notes
|
||||
|
||||
Banzai::NoteRenderer.render(
|
||||
|
|
@ -109,7 +107,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
def commits
|
||||
respond_to do |format|
|
||||
format.html { render 'show' }
|
||||
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_commits') } }
|
||||
format.json do
|
||||
# Get commits from repository
|
||||
# or from cache if already merged
|
||||
@commits = @merge_request.commits
|
||||
@note_counts = Note.where(commit_id: @commits.map(&:id)).
|
||||
group(:commit_id).count
|
||||
|
||||
render json: { html: view_to_html_string('projects/merge_requests/show/_commits') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -134,7 +140,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
@target_project = merge_request.target_project
|
||||
@source_project = merge_request.source_project
|
||||
@commits = @merge_request.compare_commits.reverse
|
||||
@commit = @merge_request.last_commit
|
||||
@commit = @merge_request.diff_head_commit
|
||||
@base_commit = @merge_request.diff_base_commit
|
||||
@diffs = @merge_request.compare.diffs(diff_options) if @merge_request.compare
|
||||
@diff_notes_disabled = true
|
||||
|
|
@ -212,7 +218,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
return
|
||||
end
|
||||
|
||||
if params[:sha] != @merge_request.source_sha
|
||||
if params[:sha] != @merge_request.diff_head_sha
|
||||
@status = :sha_mismatch
|
||||
return
|
||||
end
|
||||
|
|
@ -274,16 +280,16 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
status ||= "preparing"
|
||||
else
|
||||
ci_service = @merge_request.source_project.ci_service
|
||||
status = ci_service.commit_status(merge_request.last_commit.sha, merge_request.source_branch) if ci_service
|
||||
status = ci_service.commit_status(merge_request.diff_head_sha, merge_request.source_branch) if ci_service
|
||||
|
||||
if ci_service.respond_to?(:commit_coverage)
|
||||
coverage = ci_service.commit_coverage(merge_request.last_commit.sha, merge_request.source_branch)
|
||||
coverage = ci_service.commit_coverage(merge_request.diff_head_sha, merge_request.source_branch)
|
||||
end
|
||||
end
|
||||
|
||||
response = {
|
||||
title: merge_request.title,
|
||||
sha: merge_request.last_commit_short_sha,
|
||||
sha: merge_request.diff_head_commit.short_id,
|
||||
status: status,
|
||||
coverage: coverage
|
||||
}
|
||||
|
|
@ -308,10 +314,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
alias_method :issuable, :merge_request
|
||||
alias_method :awardable, :merge_request
|
||||
|
||||
def closes_issues
|
||||
@closes_issues ||= @merge_request.closes_issues
|
||||
end
|
||||
|
||||
def authorize_update_merge_request!
|
||||
return render_404 unless can?(current_user, :update_merge_request, @merge_request)
|
||||
end
|
||||
|
|
@ -340,30 +342,8 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def define_show_vars
|
||||
# Build a note object for comment form
|
||||
@note = @project.notes.new(noteable: @merge_request)
|
||||
|
||||
@discussions = @merge_request.mr_and_commit_notes.
|
||||
inc_author_project_award_emoji.
|
||||
fresh.
|
||||
discussions
|
||||
|
||||
@notes = Banzai::NoteRenderer.render(
|
||||
@discussions.flatten,
|
||||
@project,
|
||||
current_user,
|
||||
@path,
|
||||
@project_wiki,
|
||||
@ref
|
||||
)
|
||||
|
||||
@noteable = @merge_request
|
||||
|
||||
# Get commits from repository
|
||||
# or from cache if already merged
|
||||
@commits = @merge_request.commits
|
||||
|
||||
@merge_request_diff = @merge_request.merge_request_diff
|
||||
@commits_count = @merge_request.commits.count
|
||||
|
||||
@pipeline = @merge_request.pipeline
|
||||
@statuses = @pipeline.statuses if @pipeline
|
||||
|
|
@ -372,12 +352,36 @@ class Projects::MergeRequestsController < Projects::ApplicationController
|
|||
@merge_request.unlock_mr
|
||||
@merge_request.close
|
||||
end
|
||||
|
||||
if request.format == :html || action_name == 'show'
|
||||
define_show_html_vars
|
||||
end
|
||||
end
|
||||
|
||||
# Discussion tab data is only required on html requests
|
||||
def define_show_html_vars
|
||||
# Build a note object for comment form
|
||||
@note = @project.notes.new(noteable: @noteable)
|
||||
|
||||
@discussions = @noteable.mr_and_commit_notes.
|
||||
inc_author_project_award_emoji.
|
||||
fresh.
|
||||
discussions
|
||||
|
||||
# This is not executed lazily
|
||||
@notes = Banzai::NoteRenderer.render(
|
||||
@discussions.flatten,
|
||||
@project,
|
||||
current_user,
|
||||
@path,
|
||||
@project_wiki,
|
||||
@ref
|
||||
)
|
||||
end
|
||||
|
||||
def define_widget_vars
|
||||
@pipeline = @merge_request.pipeline
|
||||
@pipelines = [@pipeline].compact
|
||||
closes_issues
|
||||
end
|
||||
|
||||
def invalid_mr
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ class Projects::NetworkController < Projects::ApplicationController
|
|||
before_action :authorize_download_code!
|
||||
|
||||
def show
|
||||
|
||||
@url = namespace_project_network_path(@project.namespace, @project, @ref, @options.merge(format: :json))
|
||||
@commit_url = namespace_project_commit_path(@project.namespace, @project, 'ae45ca32').gsub("ae45ca32", "%s")
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
elsif note.valid?
|
||||
Banzai::NoteRenderer.render([note], @project, current_user)
|
||||
|
||||
{
|
||||
attrs = {
|
||||
valid: true,
|
||||
id: note.id,
|
||||
discussion_id: note.discussion_id,
|
||||
|
|
@ -138,6 +138,23 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
discussion_html: note_to_discussion_html(note),
|
||||
discussion_with_diff_html: note_to_discussion_with_diff_html(note)
|
||||
}
|
||||
|
||||
# The discussion_id is used to add the comment to the correct discussion
|
||||
# element on the merge request page. Among other things, the discussion_id
|
||||
# contains the sha of head commit of the merge request.
|
||||
# When new commits are pushed into the merge request after the initial
|
||||
# load of the merge request page, the discussion elements will still have
|
||||
# the old discussion_ids, with the old head commit sha. The new comment,
|
||||
# however, will have the new discussion_id with the new commit sha.
|
||||
# To ensure that these new comments will still end up in the correct
|
||||
# discussion element, we also send the original discussion_id, with the
|
||||
# old commit sha, along, and fall back on this value when no discussion
|
||||
# element with the new discussion_id could be found.
|
||||
if note.new_diff_note? && note.position != note.original_position
|
||||
attrs[:original_discussion_id] = note.original_discussion_id
|
||||
end
|
||||
|
||||
attrs
|
||||
else
|
||||
{
|
||||
valid: false,
|
||||
|
|
@ -154,7 +171,7 @@ class Projects::NotesController < Projects::ApplicationController
|
|||
def note_params
|
||||
params.require(:note).permit(
|
||||
:note, :noteable, :noteable_id, :noteable_type, :project_id,
|
||||
:attachment, :line_code, :commit_id, :type
|
||||
:attachment, :line_code, :commit_id, :type, :position
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
|
||||
def index
|
||||
@project_members = @project.project_members
|
||||
@project_members = @project_members.non_pending unless can?(current_user, :admin_project, @project)
|
||||
@project_members = @project_members.non_invite unless can?(current_user, :admin_project, @project)
|
||||
|
||||
if params[:search].present?
|
||||
users = @project.users.search(params[:search]).to_a
|
||||
|
|
@ -19,7 +19,7 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
|
||||
if @group
|
||||
@group_members = @group.group_members
|
||||
@group_members = @group_members.non_pending unless can?(current_user, :admin_group, @group)
|
||||
@group_members = @group_members.non_invite unless can?(current_user, :admin_group, @group)
|
||||
|
||||
if params[:search].present?
|
||||
users = @group.users.search(params[:search]).to_a
|
||||
|
|
@ -29,6 +29,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
@group_members = @group_members.order('access_level DESC')
|
||||
end
|
||||
|
||||
@requesters = @project.requesters if can?(current_user, :admin_project, @project)
|
||||
|
||||
@project_member = @project.project_members.new
|
||||
@project_group_links = @project.project_group_links
|
||||
end
|
||||
|
|
@ -48,7 +50,8 @@ class Projects::ProjectMembersController < Projects::ApplicationController
|
|||
end
|
||||
|
||||
def destroy
|
||||
@project_member = @project.project_members.find(params[:id])
|
||||
@project_member = @project.members.find_by(id: params[:id]) ||
|
||||
@project.requesters.find_by(id: params[:id])
|
||||
|
||||
Members::DestroyService.new(@project_member, current_user).execute
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
|
|||
# Authorize
|
||||
before_action :require_non_empty_project
|
||||
before_action :authorize_admin_project!
|
||||
before_action :load_protected_branch, only: [:show, :update, :destroy]
|
||||
|
||||
layout "project_settings"
|
||||
|
||||
def index
|
||||
@branches = @project.protected_branches.to_a
|
||||
@protected_branches = @project.protected_branches.order(:name).page(params[:page])
|
||||
@protected_branch = @project.protected_branches.new
|
||||
gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name, title: br.name } } })
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
@ -16,26 +18,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
|
|||
@project)
|
||||
end
|
||||
|
||||
def show
|
||||
@matching_branches = @protected_branch.matching(@project.repository.branches)
|
||||
end
|
||||
|
||||
def update
|
||||
protected_branch = @project.protected_branches.find(params[:id])
|
||||
|
||||
if protected_branch &&
|
||||
protected_branch.update_attributes(
|
||||
developers_can_push: params[:developers_can_push]
|
||||
)
|
||||
|
||||
if @protected_branch && @protected_branch.update_attributes(protected_branch_params)
|
||||
respond_to do |format|
|
||||
format.json { render json: protected_branch, status: :ok }
|
||||
format.json { render json: @protected_branch, status: :ok }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.json { render json: protected_branch.errors, status: :unprocessable_entity }
|
||||
format.json { render json: @protected_branch.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@project.protected_branches.find(params[:id]).destroy
|
||||
@protected_branch.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to namespace_project_protected_branches_path }
|
||||
|
|
@ -45,6 +45,10 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def load_protected_branch
|
||||
@protected_branch = @project.protected_branches.find(params[:id])
|
||||
end
|
||||
|
||||
def protected_branch_params
|
||||
params.require(:protected_branch).permit(:name, :developers_can_push)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class Projects::SnippetsController < Projects::ApplicationController
|
|||
|
||||
def show
|
||||
@note = @project.notes.new(noteable: @snippet)
|
||||
@notes = @snippet.notes.fresh
|
||||
@notes = Banzai::NoteRenderer.render(@snippet.notes.fresh, @project, current_user)
|
||||
@noteable = @snippet
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -124,5 +124,4 @@ class Projects::WikisController < Projects::ApplicationController
|
|||
def wiki_params
|
||||
params[:wiki].slice(:title, :content, :format, :message)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ class ProjectsController < Projects::ApplicationController
|
|||
notice: "Project '#{@project.name}' was successfully updated."
|
||||
)
|
||||
end
|
||||
format.js
|
||||
else
|
||||
format.html { render 'edit' }
|
||||
format.js
|
||||
end
|
||||
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class TodosFinder
|
|||
def execute
|
||||
items = current_user.todos
|
||||
items = by_action_id(items)
|
||||
items = by_action(items)
|
||||
items = by_author(items)
|
||||
items = by_project(items)
|
||||
items = by_state(items)
|
||||
|
|
@ -43,6 +44,18 @@ class TodosFinder
|
|||
params[:action_id]
|
||||
end
|
||||
|
||||
def to_action_id
|
||||
Todo::ACTION_NAMES.key(action.to_sym)
|
||||
end
|
||||
|
||||
def action?
|
||||
action.present? && to_action_id
|
||||
end
|
||||
|
||||
def action
|
||||
params[:action]
|
||||
end
|
||||
|
||||
def author?
|
||||
params[:author_id].present?
|
||||
end
|
||||
|
|
@ -96,6 +109,14 @@ class TodosFinder
|
|||
params[:type]
|
||||
end
|
||||
|
||||
def by_action(items)
|
||||
if action?
|
||||
items = items.where(action: to_action_id)
|
||||
end
|
||||
|
||||
items
|
||||
end
|
||||
|
||||
def by_action_id(items)
|
||||
if action_id?
|
||||
items = items.where(action: action_id)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ module AppearancesHelper
|
|||
end
|
||||
end
|
||||
|
||||
def navbar_icon(icon_name)
|
||||
render "shared/icons/#{icon_name}.svg"
|
||||
def navbar_icon(icon_name, size: 16)
|
||||
render "shared/icons/#{icon_name}.svg", size: size
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -306,4 +306,15 @@ module ApplicationHelper
|
|||
def truncate_first_line(message, length = 50)
|
||||
truncate(message.each_line.first.chomp, length: length) if message
|
||||
end
|
||||
|
||||
# While similarly named to Rails's `link_to_if`, this method behaves quite differently.
|
||||
# If `condition` is truthy, a link will be returned with the result of the block
|
||||
# as its body. If `condition` is falsy, only the result of the block will be returned.
|
||||
def conditional_link_to(condition, options, html_options = {}, &block)
|
||||
if condition
|
||||
link_to options, html_options, &block
|
||||
else
|
||||
capture(&block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -31,6 +31,28 @@ module ApplicationSettingsHelper
|
|||
current_application_settings.akismet_enabled?
|
||||
end
|
||||
|
||||
def allowed_protocols_present?
|
||||
current_application_settings.enabled_git_access_protocol.present?
|
||||
end
|
||||
|
||||
def enabled_protocol
|
||||
case current_application_settings.enabled_git_access_protocol
|
||||
when 'http'
|
||||
gitlab_config.protocol
|
||||
when 'ssh'
|
||||
'ssh'
|
||||
end
|
||||
end
|
||||
|
||||
def enabled_project_button(project, protocol)
|
||||
case protocol
|
||||
when 'ssh'
|
||||
ssh_clone_button(project, 'bottom', append_link: false)
|
||||
else
|
||||
http_clone_button(project, 'bottom', append_link: false)
|
||||
end
|
||||
end
|
||||
|
||||
# Return a group of checkboxes that use Bootstrap's button plugin for a
|
||||
# toggle button effect.
|
||||
def restricted_level_checkboxes(help_block_id)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module BranchesHelper
|
|||
def can_push_branch?(project, branch_name)
|
||||
return false unless project.repository.branch_exists?(branch_name)
|
||||
|
||||
::Gitlab::GitAccess.new(current_user, project).can_push_to_branch?(branch_name)
|
||||
::Gitlab::GitAccess.new(current_user, project, 'web').can_push_to_branch?(branch_name)
|
||||
end
|
||||
|
||||
def project_branches
|
||||
|
|
|
|||
|
|
@ -40,33 +40,33 @@ module ButtonHelper
|
|||
type: :button
|
||||
end
|
||||
|
||||
def http_clone_button(project)
|
||||
def http_clone_button(project, placement = 'right', append_link: true)
|
||||
klass = 'http-selector'
|
||||
klass << ' has-tooltip' if current_user.try(:require_password?)
|
||||
|
||||
protocol = gitlab_config.protocol.upcase
|
||||
|
||||
content_tag :a, protocol,
|
||||
content_tag (append_link ? :a : :span), protocol,
|
||||
class: klass,
|
||||
href: project.http_url_to_repo,
|
||||
href: (project.http_url_to_repo if append_link),
|
||||
data: {
|
||||
html: true,
|
||||
placement: 'right',
|
||||
placement: placement,
|
||||
container: 'body',
|
||||
title: "Set a password on your account<br>to pull or push via #{protocol}"
|
||||
}
|
||||
end
|
||||
|
||||
def ssh_clone_button(project)
|
||||
def ssh_clone_button(project, placement = 'right', append_link: true)
|
||||
klass = 'ssh-selector'
|
||||
klass << ' has-tooltip' if current_user.try(:require_ssh_key?)
|
||||
|
||||
content_tag :a, 'SSH',
|
||||
content_tag (append_link ? :a : :span), 'SSH',
|
||||
class: klass,
|
||||
href: project.ssh_url_to_repo,
|
||||
href: (project.ssh_url_to_repo if append_link),
|
||||
data: {
|
||||
html: true,
|
||||
placement: 'right',
|
||||
placement: placement,
|
||||
container: 'body',
|
||||
title: 'Add an SSH key to your profile<br>to pull or push via SSH.'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,8 @@ module DiffHelper
|
|||
options
|
||||
end
|
||||
|
||||
def safe_diff_files(diffs, diff_refs)
|
||||
diffs.decorate! { |diff| Gitlab::Diff::File.new(diff, diff_refs) }
|
||||
end
|
||||
|
||||
def generate_line_code(file_path, line)
|
||||
Gitlab::Diff::LineCode.generate(file_path, line.new_pos, line.old_pos)
|
||||
def safe_diff_files(diffs, diff_refs: nil, repository: nil)
|
||||
diffs.decorate! { |diff| Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
|
||||
end
|
||||
|
||||
def unfold_bottom_class(bottom)
|
||||
|
|
@ -93,6 +89,8 @@ module DiffHelper
|
|||
end
|
||||
|
||||
def commit_for_diff(diff_file)
|
||||
return diff_file.content_commit if diff_file.content_commit
|
||||
|
||||
if diff_file.deleted_file
|
||||
@base_commit || @commit.parent || @commit
|
||||
else
|
||||
|
|
@ -100,10 +98,11 @@ module DiffHelper
|
|||
end
|
||||
end
|
||||
|
||||
def diff_file_html_data(project, diff_commit, diff_file)
|
||||
def diff_file_html_data(project, diff_file)
|
||||
commit = commit_for_diff(diff_file)
|
||||
{
|
||||
blob_diff_path: namespace_project_blob_diff_path(project.namespace, project,
|
||||
tree_join(diff_commit.id, diff_file.file_path))
|
||||
tree_join(commit.id, diff_file.file_path))
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ module DropdownsHelper
|
|||
end
|
||||
end
|
||||
|
||||
def dropdown_toggle(toggle_text, data_attr, options)
|
||||
def dropdown_toggle(toggle_text, data_attr, options = {})
|
||||
content_tag(:button, class: "dropdown-menu-toggle #{options[:toggle_class] if options.has_key?(:toggle_class)}", id: (options[:id] if options.has_key?(:id)), type: "button", data: data_attr) do
|
||||
output = content_tag(:span, toggle_text, class: "dropdown-toggle-text")
|
||||
output << icon('chevron-down')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module EmailsHelper
|
||||
|
||||
# Google Actions
|
||||
# https://developers.google.com/gmail/markup/reference/go-to-action
|
||||
def email_action(url)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module IssuablesHelper
|
||||
|
||||
def sidebar_gutter_toggle_icon
|
||||
sidebar_gutter_collapsed? ? icon('angle-double-left') : icon('angle-double-right')
|
||||
end
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ module IssuesHelper
|
|||
end
|
||||
|
||||
def emoji_icon(name, unicode = nil, aliases = [], sprite: true)
|
||||
unicode ||= Emoji.emoji_filename(name) rescue ""
|
||||
unicode ||= Gitlab::Emoji.emoji_filename(name) rescue ""
|
||||
|
||||
data = {
|
||||
aliases: aliases.join(" "),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
module KerberosSpnegoHelper
|
||||
def allow_basic_auth?
|
||||
true # different behavior in GitLab Enterprise Edition
|
||||
end
|
||||
|
||||
def allow_kerberos_spnego_auth?
|
||||
false # different behavior in GitLab Enterprise Edition
|
||||
end
|
||||
end
|
||||
|
|
@ -27,7 +27,7 @@ module MergeRequestsHelper
|
|||
end
|
||||
|
||||
def ci_build_details_path(merge_request)
|
||||
build_url = merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch)
|
||||
build_url = merge_request.source_project.ci_service.build_page(merge_request.diff_head_sha, merge_request.source_branch)
|
||||
return nil unless build_url
|
||||
|
||||
parsed_url = URI.parse(build_url)
|
||||
|
|
@ -55,6 +55,10 @@ module MergeRequestsHelper
|
|||
end.sort.to_sentence
|
||||
end
|
||||
|
||||
def mr_closes_issues
|
||||
@mr_closes_issues ||= @merge_request.closes_issues
|
||||
end
|
||||
|
||||
def mr_change_branches_path(merge_request)
|
||||
new_namespace_project_merge_request_path(
|
||||
@project.namespace, @project,
|
||||
|
|
|
|||
|
|
@ -24,23 +24,55 @@ module NotesHelper
|
|||
}.to_json
|
||||
end
|
||||
|
||||
def link_to_new_diff_note(line_code, line_type = nil)
|
||||
discussion_id = LegacyDiffNote.build_discussion_id(
|
||||
@comments_target[:noteable_type],
|
||||
@comments_target[:noteable_id] || @comments_target[:commit_id],
|
||||
line_code
|
||||
)
|
||||
def link_to_new_diff_note(line_code, position, line_type = nil)
|
||||
use_legacy_diff_note = @use_legacy_diff_notes
|
||||
# If the controller doesn't force the use of legacy diff notes, we
|
||||
# determine this on a line-by-line basis by seeing if there already exist
|
||||
# active legacy diff notes at this line, in which case newly created notes
|
||||
# will use the legacy technology as well.
|
||||
# We do this because the discussion_id values of legacy and "new" diff
|
||||
# notes, which are used to group notes on the merge request discussion tab,
|
||||
# are incompatible.
|
||||
# If we didn't, diff notes that would show for the same line on the changes
|
||||
# tab, would show in different discussions on the discussion tab.
|
||||
use_legacy_diff_note ||= begin
|
||||
line_diff_notes = @grouped_diff_notes[line_code]
|
||||
line_diff_notes && line_diff_notes.any?(&:legacy_diff_note?)
|
||||
end
|
||||
|
||||
data = {
|
||||
noteable_type: @comments_target[:noteable_type],
|
||||
noteable_id: @comments_target[:noteable_id],
|
||||
commit_id: @comments_target[:commit_id],
|
||||
line_type: line_type,
|
||||
line_code: line_code,
|
||||
note_type: LegacyDiffNote.name,
|
||||
discussion_id: discussion_id
|
||||
line_code: line_code
|
||||
}
|
||||
|
||||
if use_legacy_diff_note
|
||||
discussion_id = LegacyDiffNote.build_discussion_id(
|
||||
@comments_target[:noteable_type],
|
||||
@comments_target[:noteable_id] || @comments_target[:commit_id],
|
||||
line_code
|
||||
)
|
||||
|
||||
data.merge!(
|
||||
note_type: LegacyDiffNote.name,
|
||||
discussion_id: discussion_id
|
||||
)
|
||||
else
|
||||
discussion_id = DiffNote.build_discussion_id(
|
||||
@comments_target[:noteable_type],
|
||||
@comments_target[:noteable_id] || @comments_target[:commit_id],
|
||||
position
|
||||
)
|
||||
|
||||
data.merge!(
|
||||
position: position.to_json,
|
||||
note_type: DiffNote.name,
|
||||
discussion_id: discussion_id
|
||||
)
|
||||
end
|
||||
|
||||
button_tag(class: 'btn add-diff-note js-add-diff-note-button',
|
||||
data: data,
|
||||
title: 'Add a comment to this line') do
|
||||
|
|
@ -60,14 +92,15 @@ module NotesHelper
|
|||
}
|
||||
|
||||
if note.diff_note?
|
||||
data.merge!(
|
||||
line_code: note.line_code,
|
||||
note_type: LegacyDiffNote.name
|
||||
)
|
||||
data[:note_type] = note.type
|
||||
|
||||
data.merge!(note.diff_attributes)
|
||||
end
|
||||
|
||||
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
|
||||
data: data, title: 'Add a reply'
|
||||
content_tag(:div, class: "discussion-reply-holder") do
|
||||
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
|
||||
data: data, title: 'Add a reply'
|
||||
end
|
||||
end
|
||||
|
||||
def note_max_access_for_user(note)
|
||||
|
|
@ -79,4 +112,14 @@ module NotesHelper
|
|||
full_key = { project: note.project, user_id: note.author_id }
|
||||
@max_access_by_user_id[full_key]
|
||||
end
|
||||
|
||||
def diff_note_path(note)
|
||||
return unless note.diff_note?
|
||||
|
||||
if note.for_merge_request? && note.active?
|
||||
diffs_namespace_project_merge_request_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code)
|
||||
elsif note.for_commit?
|
||||
namespace_project_commit_path(note.project.namespace, note.project, note.noteable, anchor: note.line_code)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -206,10 +206,14 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def default_clone_protocol
|
||||
if !current_user || current_user.require_ssh_key?
|
||||
gitlab_config.protocol
|
||||
if allowed_protocols_present?
|
||||
enabled_protocol
|
||||
else
|
||||
"ssh"
|
||||
if !current_user || current_user.require_ssh_key?
|
||||
gitlab_config.protocol
|
||||
else
|
||||
'ssh'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -289,7 +293,11 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def last_push_event
|
||||
if current_user
|
||||
return unless current_user
|
||||
|
||||
if fork = current_user.fork_of(@project)
|
||||
current_user.recent_push(fork.id)
|
||||
else
|
||||
current_user.recent_push(@project.id)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module SearchHelper
|
||||
|
||||
def search_autocomplete_opts(term)
|
||||
return unless current_user
|
||||
|
||||
|
|
|
|||
|
|
@ -23,4 +23,11 @@ module TimeHelper
|
|||
def date_from_to(from, to)
|
||||
"#{from.to_s(:short)} - #{to.to_s(:short)}"
|
||||
end
|
||||
|
||||
def duration_in_numbers(finished_at, started_at)
|
||||
diff_in_seconds = finished_at.to_i - started_at.to_i
|
||||
time_format = diff_in_seconds < 1.hour ? "%M:%S" : "%H:%M:%S"
|
||||
|
||||
Time.at(diff_in_seconds).utc.strftime(time_format)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Helpers to send Git blobs, diffs or archives through Workhorse.
|
||||
# Helpers to send Git blobs, diffs, patches or archives through Workhorse.
|
||||
# Workhorse will also serve files when using `send_file`.
|
||||
module WorkhorseHelper
|
||||
# Send a Git blob through Workhorse
|
||||
|
|
@ -16,6 +16,13 @@ module WorkhorseHelper
|
|||
head :ok
|
||||
end
|
||||
|
||||
# Send a Git patch through Workhorse
|
||||
def send_git_patch(repository, diff_refs)
|
||||
headers.store(*Gitlab::Workhorse.send_git_patch(repository, diff_refs))
|
||||
headers['Content-Disposition'] = 'inline'
|
||||
head :ok
|
||||
end
|
||||
|
||||
# Archive a Git repository and send it through Workhorse
|
||||
def send_git_archive(repository, ref:, format:)
|
||||
headers.store(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ module Emails
|
|||
# used in notify layout
|
||||
@target_url = @message.target_url
|
||||
@project = Project.find(project_id)
|
||||
@diff_notes_disabled = true
|
||||
|
||||
|
||||
add_project_headers
|
||||
headers['X-GitLab-Author'] = @message.author_username
|
||||
|
||||
|
|
|
|||
|
|
@ -157,10 +157,11 @@ class Ability
|
|||
# Push abilities on the users team role
|
||||
rules.push(*project_team_rules(project.team, user))
|
||||
|
||||
if project.owner == user ||
|
||||
(project.group && project.group.has_owner?(user)) ||
|
||||
user.admin?
|
||||
owner = user.admin? ||
|
||||
project.owner == user ||
|
||||
(project.group && project.group.has_owner?(user))
|
||||
|
||||
if owner
|
||||
rules.push(*project_owner_rules)
|
||||
end
|
||||
|
||||
|
|
@ -169,6 +170,10 @@ class Ability
|
|||
|
||||
# Allow to read builds for internal projects
|
||||
rules << :read_build if project.public_builds?
|
||||
|
||||
unless owner || project.team.member?(user) || project_group_member?(project, user)
|
||||
rules << :request_access
|
||||
end
|
||||
end
|
||||
|
||||
if project.archived?
|
||||
|
|
@ -345,8 +350,11 @@ class Ability
|
|||
rules = []
|
||||
rules << :read_group if can_read_group?(user, group)
|
||||
|
||||
owner = user.admin? || group.has_owner?(user)
|
||||
master = owner || group.has_master?(user)
|
||||
|
||||
# Only group masters and group owners can create new projects
|
||||
if group.has_master?(user) || group.has_owner?(user) || user.admin?
|
||||
if master
|
||||
rules += [
|
||||
:create_projects,
|
||||
:admin_milestones
|
||||
|
|
@ -354,7 +362,7 @@ class Ability
|
|||
end
|
||||
|
||||
# Only group owner and administrators can admin group
|
||||
if group.has_owner?(user) || user.admin?
|
||||
if owner
|
||||
rules += [
|
||||
:admin_group,
|
||||
:admin_namespace,
|
||||
|
|
@ -363,6 +371,10 @@ class Ability
|
|||
]
|
||||
end
|
||||
|
||||
if group.public? || (group.internal? && !user.external?)
|
||||
rules << :request_access unless group.users.include?(user)
|
||||
end
|
||||
|
||||
rules.flatten
|
||||
end
|
||||
|
||||
|
|
@ -564,5 +576,13 @@ class Ability
|
|||
|
||||
rules
|
||||
end
|
||||
|
||||
def project_group_member?(project, user)
|
||||
project.group &&
|
||||
(
|
||||
project.group.members.exists?(user_id: user.id) ||
|
||||
project.group.requesters.exists?(user_id: user.id)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
presence: true,
|
||||
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
|
||||
|
||||
validates :enabled_git_access_protocol,
|
||||
inclusion: { in: %w(ssh http), allow_blank: true, allow_nil: true }
|
||||
|
||||
validates_each :restricted_visibility_levels do |record, attr, value|
|
||||
unless value.nil?
|
||||
value.each do |level|
|
||||
|
|
@ -139,6 +142,7 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
send_user_confirmation_email: false,
|
||||
container_registry_token_expire_delay: 5,
|
||||
repository_storage: 'default',
|
||||
user_default_external: false,
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class AwardEmoji < ActiveRecord::Base
|
|||
belongs_to :user
|
||||
|
||||
validates :awardable, :user, presence: true
|
||||
validates :name, presence: true, inclusion: { in: Emoji.emojis_names }
|
||||
validates :name, presence: true, inclusion: { in: Gitlab::Emoji.emojis_names }
|
||||
validates :name, uniqueness: { scope: [:user, :awardable_type, :awardable_id] }
|
||||
|
||||
participant :user
|
||||
|
|
|
|||
|
|
@ -13,21 +13,19 @@ module Ci
|
|||
scope :ignore_failures, ->() { where(allow_failure: false) }
|
||||
scope :with_artifacts, ->() { where.not(artifacts_file: nil) }
|
||||
scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
|
||||
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
|
||||
|
||||
mount_uploader :artifacts_file, ArtifactUploader
|
||||
mount_uploader :artifacts_metadata, ArtifactUploader
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
before_save :update_artifacts_size, if: :artifacts_file_changed?
|
||||
before_destroy { project }
|
||||
|
||||
after_create :execute_hooks
|
||||
|
||||
class << self
|
||||
def last_month
|
||||
where('created_at > ?', Date.today - 1.month)
|
||||
end
|
||||
|
||||
def first_pending
|
||||
pending.unstarted.order('created_at ASC').first
|
||||
end
|
||||
|
|
@ -329,7 +327,12 @@ module Ci
|
|||
end
|
||||
|
||||
def artifacts_metadata_entry(path, **options)
|
||||
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry
|
||||
metadata = Gitlab::Ci::Build::Artifacts::Metadata.new(
|
||||
artifacts_metadata.path,
|
||||
path,
|
||||
**options)
|
||||
|
||||
metadata.to_entry
|
||||
end
|
||||
|
||||
def erase_artifacts!
|
||||
|
|
@ -375,6 +378,14 @@ module Ci
|
|||
|
||||
private
|
||||
|
||||
def update_artifacts_size
|
||||
self.artifacts_size = if artifacts_file.exists?
|
||||
artifacts_file.size
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def erase_trace!
|
||||
self.trace = nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ module Ci
|
|||
|
||||
# Invalidate object and save if when touched
|
||||
after_touch :update_state
|
||||
after_save :keep_around_commits
|
||||
|
||||
def self.truncate_sha(sha)
|
||||
sha[0...8]
|
||||
|
|
@ -212,5 +213,10 @@ module Ci
|
|||
self.duration = statuses.latest.duration
|
||||
save
|
||||
end
|
||||
|
||||
def keep_around_commits
|
||||
project.repository.keep_around(self.sha)
|
||||
project.repository.keep_around(self.before_sha)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module Ci
|
||||
class TriggerRequest < ActiveRecord::Base
|
||||
extend Ci::Model
|
||||
|
||||
|
||||
belongs_to :trigger, class_name: 'Ci::Trigger'
|
||||
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
|
||||
has_many :builds, class_name: 'Ci::Build'
|
||||
|
|
|
|||
|
|
@ -214,6 +214,13 @@ class Commit
|
|||
@raw.short_id(7)
|
||||
end
|
||||
|
||||
def diff_refs
|
||||
Gitlab::Diff::DiffRefs.new(
|
||||
base_sha: self.parent_id || self.sha,
|
||||
head_sha: self.sha
|
||||
)
|
||||
end
|
||||
|
||||
def pipelines
|
||||
@pipeline ||= project.pipelines.where(sha: sha)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class CommitRange
|
|||
attr_reader :commit_from, :notation, :commit_to
|
||||
attr_reader :ref_from, :ref_to
|
||||
|
||||
# Optional Project model
|
||||
# The Project model
|
||||
attr_accessor :project
|
||||
|
||||
# The beginning and ending refs can be named or SHAs, and
|
||||
|
|
@ -56,7 +56,7 @@ class CommitRange
|
|||
# Initialize a CommitRange
|
||||
#
|
||||
# range_string - The String commit range.
|
||||
# project - An optional Project model.
|
||||
# project - The Project model.
|
||||
#
|
||||
# Raises ArgumentError if `range_string` does not match `PATTERN`.
|
||||
def initialize(range_string, project)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ module Issuable
|
|||
scope :references_project, -> { references(:project) }
|
||||
scope :non_archived, -> { join_project.where(projects: { archived: false }) }
|
||||
|
||||
|
||||
delegate :name,
|
||||
:email,
|
||||
to: :author,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ module Mentionable
|
|||
|
||||
def all_references(current_user = nil, text = nil, extractor: nil)
|
||||
extractor ||= Gitlab::ReferenceExtractor.
|
||||
new(project, current_user || author)
|
||||
new(project, current_user)
|
||||
|
||||
if text
|
||||
extractor.analyze(text, author: author)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue