Upstream version 8.9.0+debian~rc4
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJXYuRgAAoJEM4fnGdFEsIqgwgP/R7xR2HQ8CpGbaeMi33JM/qU eN1/u5X7aue7CwqCw3WGBW2PubHZRxJmbxwPE4GasWPnnvtAg5+RU7whJbbeeEwV kwQdP1VfddSolARD+4sBi6mQtkFn03n0GZm7Hel9m2pssevwN4DSAf4b7i/eoa5l 35WTQdPGYbU3LCIYvdg7yPYvroFK2lz+aIsA/1Al4qvjrZy/hZbc0Xgb7U4nmJMI tlybL9eYQIB+gxAkozxEUWZXhEyo2u4/WwDSosm47N1s9Hv/2H7ks2dzKVhD3phS fbTf5fmeDF82yAtrpWYMO8xDEpkXQB/BtRFDBEFkkSERZ8jR6Yml/f8BzTWzSgiV AItfbPaHldj5RDZ+gpOmE0cQ4Uol/XvvXxH6ZQdcQuqG2ZfgWwvqONTLuBV0MRyu 74Unc6Ul4+649oq2hSe5+lcLhUBYEsIxcdre69Qy9GKJ85m61+DQcV4VvgFOvrdv cAwImWtLW/Tm2RzdvpicJlYO4szrSKYyub5avrCSwpgLBmxGVAkWnJtm8YOuwcBX cHcodr1gnfWjya+g67BAhWyhRWBZD9r3hvKULkSOyc1ls7870su9MkUSLNZboBrA sly/J6ochXrnijysIEHqjLphLWAh4E8JKahIJIHPvgU8ZQFkhIx+I6tFlqPu4y8M f8Aeky6lOfEosNPYNtmp =O7yH -----END PGP SIGNATURE----- Merge tag 'upstream/8.9.0+debian_rc4' Upstream version 8.9.0+debian~rc4 # gpg: Signature made Thursday 16 June 2016 11:09:44 PM IST using RSA key ID 4512C22A # gpg: Good signature from "Praveen Arimbrathodiyil (piratepin) <praveen@debian.org>" # gpg: aka "Pirate Praveen (pirates.org.in) <praveen@onenetbeyond.org>" # gpg: aka "Pirate Praveen (piratesin) <me@j4v4m4n.in>" # gpg: aka "Pirate Praveen (PP) <praveen@privacyrequired.com>" # gpg: aka "Praveen Arimbrathodiyil (j4v4m4n) <pravi.a@gmail.com>"
This commit is contained in:
commit
d987b6228e
1485 changed files with 26862 additions and 9882 deletions
3
.github/ISSUE_TEMPLATE.md
vendored
Normal file
3
.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
We’re closing our issue tracker on GitHub so we can focus on the GitLab.com project and respond to issues more quickly.
|
||||||
|
|
||||||
|
We encourage you to open an issue on the [GitLab.com issue tracker](https://gitlab.com/gitlab-org/gitlab-ce/issues). You can log into GitLab.com using your GitHub account.
|
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Thank you for taking the time to contribute back to GitLab!
|
||||||
|
|
||||||
|
Please open a merge request [on GitLab.com](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests), we look forward to reviewing your contribution! You can log into GitLab.com using your GitHub account.
|
78
.gitignore
vendored
78
.gitignore
vendored
|
@ -4,46 +4,46 @@
|
||||||
.bundle
|
.bundle
|
||||||
.chef
|
.chef
|
||||||
.directory
|
.directory
|
||||||
.envrc
|
/.envrc
|
||||||
.gitlab_shell_secret
|
/.gitlab_shell_secret
|
||||||
.idea
|
.idea
|
||||||
.rbenv-version
|
/.rbenv-version
|
||||||
.rbx/
|
.rbx/
|
||||||
.ruby-gemset
|
/.ruby-gemset
|
||||||
.ruby-version
|
/.ruby-version
|
||||||
.rvmrc
|
/.rvmrc
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
.secret
|
/.secret
|
||||||
.vagrant
|
/.vagrant
|
||||||
.byebug_history
|
/.byebug_history
|
||||||
Vagrantfile
|
/Vagrantfile
|
||||||
backups/*
|
/backups/*
|
||||||
config/aws.yml
|
/config/aws.yml
|
||||||
config/database.yml
|
/config/database.yml
|
||||||
config/gitlab.yml
|
/config/gitlab.yml
|
||||||
config/gitlab_ci.yml
|
/config/gitlab_ci.yml
|
||||||
config/initializers/rack_attack.rb
|
/config/initializers/rack_attack.rb
|
||||||
config/initializers/smtp_settings.rb
|
/config/initializers/smtp_settings.rb
|
||||||
config/initializers/relative_url.rb
|
/config/initializers/relative_url.rb
|
||||||
config/resque.yml
|
/config/resque.yml
|
||||||
config/unicorn.rb
|
/config/unicorn.rb
|
||||||
config/secrets.yml
|
/config/secrets.yml
|
||||||
config/sidekiq.yml
|
/config/sidekiq.yml
|
||||||
coverage/*
|
/coverage/*
|
||||||
db/*.sqlite3
|
/db/*.sqlite3
|
||||||
db/*.sqlite3-journal
|
/db/*.sqlite3-journal
|
||||||
db/data.yml
|
/db/data.yml
|
||||||
doc/code/*
|
/doc/code/*
|
||||||
dump.rdb
|
/dump.rdb
|
||||||
log/*.log*
|
/log/*.log*
|
||||||
nohup.out
|
/nohup.out
|
||||||
public/assets/
|
/public/assets/
|
||||||
public/uploads.*
|
/public/uploads.*
|
||||||
public/uploads/
|
/public/uploads/
|
||||||
shared/artifacts/
|
/shared/artifacts/
|
||||||
rails_best_practices_output.html
|
/rails_best_practices_output.html
|
||||||
/tags
|
/tags
|
||||||
tmp/
|
/tmp/*
|
||||||
vendor/bundle/*
|
/vendor/bundle/*
|
||||||
builds/*
|
/builds/*
|
||||||
shared/*
|
/shared/*
|
||||||
|
|
367
.gitlab-ci.yml
367
.gitlab-ci.yml
|
@ -2,111 +2,199 @@ image: "ruby:2.1"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- mysql:latest
|
- mysql:latest
|
||||||
- redis:latest
|
- redis:alpine
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
key: "ruby21"
|
key: "ruby21"
|
||||||
paths:
|
paths:
|
||||||
- vendor
|
- vendor/apt
|
||||||
|
- vendor/ruby
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
|
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
|
||||||
# retry tests only in CI environment
|
# retry tests only in CI environment
|
||||||
RSPEC_RETRY_RETRY_COUNT: "3"
|
RSPEC_RETRY_RETRY_COUNT: "3"
|
||||||
|
RAILS_ENV: "test"
|
||||||
|
SIMPLECOV: "true"
|
||||||
|
USE_DB: "true"
|
||||||
|
USE_BUNDLE_INSTALL: "true"
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- source ./scripts/prepare_build.sh
|
- source ./scripts/prepare_build.sh
|
||||||
- ruby -v
|
|
||||||
- which ruby
|
|
||||||
- retry gem install bundler --no-ri --no-rdoc
|
|
||||||
- cp config/gitlab.yml.example config/gitlab.yml
|
- cp config/gitlab.yml.example config/gitlab.yml
|
||||||
- touch log/application.log
|
- bundle --version
|
||||||
- touch log/test.log
|
- '[ "$USE_BUNDLE_INSTALL" != "true" ] || retry bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"'
|
||||||
- retry bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"
|
- retry gem install knapsack
|
||||||
- RAILS_ENV=test bundle exec rake db:drop db:create db:schema:load db:migrate
|
- '[ "$USE_DB" != "true" ] || bundle exec rake db:drop db:create db:schema:load db:migrate'
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
|
- prepare
|
||||||
- test
|
- test
|
||||||
- notifications
|
- post-test
|
||||||
|
|
||||||
spec:feature:
|
# Prepare and merge knapsack tests
|
||||||
|
|
||||||
|
.knapsack-state: &knapsack-state
|
||||||
|
services: []
|
||||||
|
variables:
|
||||||
|
USE_DB: "false"
|
||||||
|
USE_BUNDLE_INSTALL: "false"
|
||||||
|
cache:
|
||||||
|
key: "knapsack"
|
||||||
|
paths:
|
||||||
|
- knapsack/
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- knapsack/
|
||||||
|
|
||||||
|
knapsack:
|
||||||
|
<<: *knapsack-state
|
||||||
|
stage: prepare
|
||||||
|
script:
|
||||||
|
- mkdir -p knapsack/
|
||||||
|
- '[[ -f knapsack/rspec_report.json ]] || echo "{}" > knapsack/rspec_report.json'
|
||||||
|
- '[[ -f knapsack/spinach_report.json ]] || echo "{}" > knapsack/spinach_report.json'
|
||||||
|
|
||||||
|
update-knapsack:
|
||||||
|
<<: *knapsack-state
|
||||||
|
stage: post-test
|
||||||
|
script:
|
||||||
|
- scripts/merge-reports knapsack/rspec_report.json knapsack/rspec_node_*.json
|
||||||
|
- scripts/merge-reports knapsack/spinach_report.json knapsack/spinach_node_*.json
|
||||||
|
- rm -f knapsack/*_node_*.json
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
|
||||||
|
# Execute all testing suites
|
||||||
|
|
||||||
|
.rspec-knapsack: &rspec-knapsack
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
- bundle exec rake assets:precompile 2>/dev/null
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
|
- JOB_NAME=( $CI_BUILD_NAME )
|
||||||
|
- export CI_NODE_INDEX=${JOB_NAME[1]}
|
||||||
|
- export CI_NODE_TOTAL=${JOB_NAME[2]}
|
||||||
|
- export KNAPSACK_REPORT_PATH=knapsack/rspec_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
|
||||||
|
- export KNAPSACK_GENERATE_REPORT=true
|
||||||
|
- cp knapsack/rspec_report.json ${KNAPSACK_REPORT_PATH}
|
||||||
|
- knapsack rspec
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- knapsack/
|
||||||
|
|
||||||
spec:api:
|
.spinach-knapsack: &spinach-knapsack
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api
|
- bundle exec rake assets:precompile 2>/dev/null
|
||||||
|
- JOB_NAME=( $CI_BUILD_NAME )
|
||||||
|
- export CI_NODE_INDEX=${JOB_NAME[1]}
|
||||||
|
- export CI_NODE_TOTAL=${JOB_NAME[2]}
|
||||||
|
- export KNAPSACK_REPORT_PATH=knapsack/spinach_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
|
||||||
|
- export KNAPSACK_GENERATE_REPORT=true
|
||||||
|
- cp knapsack/spinach_report.json ${KNAPSACK_REPORT_PATH}
|
||||||
|
- knapsack spinach "-r rerun" || retry '[ ! -e tmp/spinach-rerun.txt ] || bundle exec spinach -r rerun $(cat tmp/spinach-rerun.txt)'
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- knapsack/
|
||||||
|
|
||||||
spec:models:
|
rspec 0 20: *rspec-knapsack
|
||||||
|
rspec 1 20: *rspec-knapsack
|
||||||
|
rspec 2 20: *rspec-knapsack
|
||||||
|
rspec 3 20: *rspec-knapsack
|
||||||
|
rspec 4 20: *rspec-knapsack
|
||||||
|
rspec 5 20: *rspec-knapsack
|
||||||
|
rspec 6 20: *rspec-knapsack
|
||||||
|
rspec 7 20: *rspec-knapsack
|
||||||
|
rspec 8 20: *rspec-knapsack
|
||||||
|
rspec 9 20: *rspec-knapsack
|
||||||
|
rspec 10 20: *rspec-knapsack
|
||||||
|
rspec 11 20: *rspec-knapsack
|
||||||
|
rspec 12 20: *rspec-knapsack
|
||||||
|
rspec 13 20: *rspec-knapsack
|
||||||
|
rspec 14 20: *rspec-knapsack
|
||||||
|
rspec 15 20: *rspec-knapsack
|
||||||
|
rspec 16 20: *rspec-knapsack
|
||||||
|
rspec 17 20: *rspec-knapsack
|
||||||
|
rspec 18 20: *rspec-knapsack
|
||||||
|
rspec 19 20: *rspec-knapsack
|
||||||
|
|
||||||
|
spinach 0 10: *spinach-knapsack
|
||||||
|
spinach 1 10: *spinach-knapsack
|
||||||
|
spinach 2 10: *spinach-knapsack
|
||||||
|
spinach 3 10: *spinach-knapsack
|
||||||
|
spinach 4 10: *spinach-knapsack
|
||||||
|
spinach 5 10: *spinach-knapsack
|
||||||
|
spinach 6 10: *spinach-knapsack
|
||||||
|
spinach 7 10: *spinach-knapsack
|
||||||
|
spinach 8 10: *spinach-knapsack
|
||||||
|
spinach 9 10: *spinach-knapsack
|
||||||
|
|
||||||
|
# Execute all testing suites against Ruby 2.2
|
||||||
|
|
||||||
|
.ruby-22: &ruby-22
|
||||||
|
image: "ruby:2.2"
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
cache:
|
||||||
|
key: "ruby22"
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
|
||||||
|
.rspec-knapsack-ruby22: &rspec-knapsack-ruby22
|
||||||
|
<<: *rspec-knapsack
|
||||||
|
<<: *ruby-22
|
||||||
|
|
||||||
|
.spinach-knapsack-ruby22: &spinach-knapsack-ruby22
|
||||||
|
<<: *spinach-knapsack
|
||||||
|
<<: *ruby-22
|
||||||
|
|
||||||
|
rspec 0 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 1 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 2 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 3 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 4 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 5 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 6 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 7 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 8 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 9 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 10 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 11 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 12 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 13 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 14 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 15 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 16 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 17 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 18 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
rspec 19 20 ruby22: *rspec-knapsack-ruby22
|
||||||
|
|
||||||
|
spinach 0 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 1 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 2 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 3 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 4 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 5 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 6 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 7 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 8 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
spinach 9 10 ruby22: *spinach-knapsack-ruby22
|
||||||
|
|
||||||
|
# Other generic tests
|
||||||
|
|
||||||
|
.exec: &exec
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models
|
- bundle exec $CI_BUILD_NAME
|
||||||
|
|
||||||
spec:lib:
|
teaspoon: *exec
|
||||||
stage: test
|
rubocop: *exec
|
||||||
script:
|
rake scss_lint: *exec
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib
|
rake brakeman: *exec
|
||||||
|
rake flog: *exec
|
||||||
spec:services:
|
rake flay: *exec
|
||||||
stage: test
|
rake db:migrate:reset: *exec
|
||||||
script:
|
license_finder: *exec
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services
|
|
||||||
|
|
||||||
spec:other:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other
|
|
||||||
|
|
||||||
spinach:project:half:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half
|
|
||||||
|
|
||||||
spinach:project:rest:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest
|
|
||||||
|
|
||||||
spinach:other:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other
|
|
||||||
|
|
||||||
teaspoon:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec teaspoon
|
|
||||||
|
|
||||||
rubocop:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- bundle exec rubocop
|
|
||||||
|
|
||||||
scss-lint:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- bundle exec rake scss_lint
|
|
||||||
|
|
||||||
brakeman:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- bundle exec rake brakeman
|
|
||||||
|
|
||||||
flog:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- bundle exec rake flog
|
|
||||||
|
|
||||||
flay:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- bundle exec rake flay
|
|
||||||
|
|
||||||
bundler:audit:
|
bundler:audit:
|
||||||
stage: test
|
stage: test
|
||||||
|
@ -115,127 +203,10 @@ bundler:audit:
|
||||||
script:
|
script:
|
||||||
- "bundle exec bundle-audit check --update --ignore OSVDB-115941"
|
- "bundle exec bundle-audit check --update --ignore OSVDB-115941"
|
||||||
|
|
||||||
db-migrate-reset:
|
# Notify slack in the end
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake db:migrate:reset
|
|
||||||
|
|
||||||
# Ruby 2.2 jobs
|
|
||||||
|
|
||||||
spec:feature:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:feature
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spec:api:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:api
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spec:models:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:models
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spec:lib:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:lib
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spec:services:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:services
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spec:other:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spec:other
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spinach:project:half:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:half
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spinach:project:rest:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:project:rest
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
spinach:other:ruby22:
|
|
||||||
stage: test
|
|
||||||
image: ruby:2.2
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- RAILS_ENV=test bundle exec rake assets:precompile 2>/dev/null
|
|
||||||
- RAILS_ENV=test SIMPLECOV=true bundle exec rake spinach:other
|
|
||||||
cache:
|
|
||||||
key: "ruby22"
|
|
||||||
paths:
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
notify:slack:
|
notify:slack:
|
||||||
stage: notifications
|
stage: post-test
|
||||||
script:
|
script:
|
||||||
- ./scripts/notify_slack.sh "#builds" "Build on \`$CI_BUILD_REF_NAME\` failed! Commit \`$(git log -1 --oneline)\` See <https://gitlab.com/gitlab-org/$(basename "$PWD")/commit/"$CI_BUILD_REF"/builds>"
|
- ./scripts/notify_slack.sh "#builds" "Build on \`$CI_BUILD_REF_NAME\` failed! Commit \`$(git log -1 --oneline)\` See <https://gitlab.com/gitlab-org/$(basename "$PWD")/commit/"$CI_BUILD_REF"/builds>"
|
||||||
when: on_failure
|
when: on_failure
|
||||||
|
|
272
.rubocop.yml
272
.rubocop.yml
|
@ -1,3 +1,5 @@
|
||||||
|
require: rubocop-rspec
|
||||||
|
|
||||||
AllCops:
|
AllCops:
|
||||||
TargetRubyVersion: 2.1
|
TargetRubyVersion: 2.1
|
||||||
# Cop names are not displayed in offense messages by default. Change behavior
|
# Cop names are not displayed in offense messages by default. Change behavior
|
||||||
|
@ -11,7 +13,8 @@ AllCops:
|
||||||
# Exclude some GitLab files
|
# Exclude some GitLab files
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'vendor/**/*'
|
- 'vendor/**/*'
|
||||||
- 'db/**/*'
|
- 'db/*'
|
||||||
|
- 'db/fixtures/**/*'
|
||||||
- 'tmp/**/*'
|
- 'tmp/**/*'
|
||||||
- 'bin/**/*'
|
- 'bin/**/*'
|
||||||
- 'lib/backup/**/*'
|
- 'lib/backup/**/*'
|
||||||
|
@ -57,7 +60,7 @@ Style/AndOr:
|
||||||
|
|
||||||
# Use `Array#join` instead of `Array#*`.
|
# Use `Array#join` instead of `Array#*`.
|
||||||
Style/ArrayJoin:
|
Style/ArrayJoin:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use only ascii symbols in comments.
|
# Use only ascii symbols in comments.
|
||||||
Style/AsciiComments:
|
Style/AsciiComments:
|
||||||
|
@ -69,7 +72,7 @@ Style/AsciiIdentifiers:
|
||||||
|
|
||||||
# Checks for uses of Module#attr.
|
# Checks for uses of Module#attr.
|
||||||
Style/Attr:
|
Style/Attr:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Avoid the use of BEGIN blocks.
|
# Avoid the use of BEGIN blocks.
|
||||||
Style/BeginBlock:
|
Style/BeginBlock:
|
||||||
|
@ -81,7 +84,7 @@ Style/BarePercentLiterals:
|
||||||
|
|
||||||
# Do not use block comments.
|
# Do not use block comments.
|
||||||
Style/BlockComments:
|
Style/BlockComments:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Put end statement of multiline block on its own line.
|
# Put end statement of multiline block on its own line.
|
||||||
Style/BlockEndNewline:
|
Style/BlockEndNewline:
|
||||||
|
@ -122,7 +125,7 @@ Style/ClassCheck:
|
||||||
|
|
||||||
# Use self when defining module/class methods.
|
# Use self when defining module/class methods.
|
||||||
Style/ClassMethods:
|
Style/ClassMethods:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Avoid the use of class variables.
|
# Avoid the use of class variables.
|
||||||
Style/ClassVars:
|
Style/ClassVars:
|
||||||
|
@ -152,7 +155,7 @@ Style/ConstantName:
|
||||||
|
|
||||||
# Use def with parentheses when there are arguments.
|
# Use def with parentheses when there are arguments.
|
||||||
Style/DefWithParentheses:
|
Style/DefWithParentheses:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for use of deprecated Hash methods.
|
# Checks for use of deprecated Hash methods.
|
||||||
Style/DeprecatedHashMethods:
|
Style/DeprecatedHashMethods:
|
||||||
|
@ -192,7 +195,7 @@ Style/EmptyLines:
|
||||||
|
|
||||||
# Keep blank lines around access modifiers.
|
# Keep blank lines around access modifiers.
|
||||||
Style/EmptyLinesAroundAccessModifier:
|
Style/EmptyLinesAroundAccessModifier:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Keeps track of empty lines around block bodies.
|
# Keeps track of empty lines around block bodies.
|
||||||
Style/EmptyLinesAroundBlockBody:
|
Style/EmptyLinesAroundBlockBody:
|
||||||
|
@ -216,15 +219,15 @@ Style/EmptyLiteral:
|
||||||
|
|
||||||
# Avoid the use of END blocks.
|
# Avoid the use of END blocks.
|
||||||
Style/EndBlock:
|
Style/EndBlock:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use Unix-style line endings.
|
# Use Unix-style line endings.
|
||||||
Style/EndOfLine:
|
Style/EndOfLine:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Favor the use of Fixnum#even? && Fixnum#odd?
|
# Favor the use of Fixnum#even? && Fixnum#odd?
|
||||||
Style/EvenOdd:
|
Style/EvenOdd:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Do not use unnecessary spacing.
|
# Do not use unnecessary spacing.
|
||||||
Style/ExtraSpacing:
|
Style/ExtraSpacing:
|
||||||
|
@ -232,15 +235,20 @@ Style/ExtraSpacing:
|
||||||
|
|
||||||
# Use snake_case for source file names.
|
# Use snake_case for source file names.
|
||||||
Style/FileName:
|
Style/FileName:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks for a line break before the first parameter in a multi-line method
|
||||||
|
# parameter definition.
|
||||||
|
Style/FirstMethodParameterLineBreak:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# Checks for flip flops.
|
# Checks for flip flops.
|
||||||
Style/FlipFlop:
|
Style/FlipFlop:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks use of for or each in multiline loops.
|
# Checks use of for or each in multiline loops.
|
||||||
Style/For:
|
Style/For:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Enforce the use of Kernel#sprintf, Kernel#format or String#%.
|
# Enforce the use of Kernel#sprintf, Kernel#format or String#%.
|
||||||
Style/FormatString:
|
Style/FormatString:
|
||||||
|
@ -248,7 +256,7 @@ Style/FormatString:
|
||||||
|
|
||||||
# Do not introduce global variables.
|
# Do not introduce global variables.
|
||||||
Style/GlobalVars:
|
Style/GlobalVars:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Check for conditionals that can be replaced with guard clauses.
|
# Check for conditionals that can be replaced with guard clauses.
|
||||||
Style/GuardClause:
|
Style/GuardClause:
|
||||||
|
@ -269,7 +277,7 @@ Style/IfUnlessModifier:
|
||||||
|
|
||||||
# Do not use if x; .... Use the ternary operator instead.
|
# Do not use if x; .... Use the ternary operator instead.
|
||||||
Style/IfWithSemicolon:
|
Style/IfWithSemicolon:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks that conditional statements do not have an identical line at the
|
# 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.
|
# end of each branch, which can validly be moved out of the conditional.
|
||||||
|
@ -279,7 +287,7 @@ Style/IdenticalConditionalBranches:
|
||||||
# Checks the indentation of the first line of the right-hand-side of a
|
# Checks the indentation of the first line of the right-hand-side of a
|
||||||
# multi-line assignment.
|
# multi-line assignment.
|
||||||
Style/IndentAssignment:
|
Style/IndentAssignment:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Keep indentation straight.
|
# Keep indentation straight.
|
||||||
Style/IndentationConsistency:
|
Style/IndentationConsistency:
|
||||||
|
@ -299,7 +307,7 @@ Style/IndentHash:
|
||||||
|
|
||||||
# Use Kernel#loop for infinite loops.
|
# Use Kernel#loop for infinite loops.
|
||||||
Style/InfiniteLoop:
|
Style/InfiniteLoop:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use the new lambda literal syntax for single-line blocks.
|
# Use the new lambda literal syntax for single-line blocks.
|
||||||
Style/Lambda:
|
Style/Lambda:
|
||||||
|
@ -307,11 +315,11 @@ Style/Lambda:
|
||||||
|
|
||||||
# Use lambda.call(...) instead of lambda.(...).
|
# Use lambda.call(...) instead of lambda.(...).
|
||||||
Style/LambdaCall:
|
Style/LambdaCall:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Comments should start with a space.
|
# Comments should start with a space.
|
||||||
Style/LeadingCommentSpace:
|
Style/LeadingCommentSpace:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use \ instead of + or << to concatenate two string literals at line end.
|
# Use \ instead of + or << to concatenate two string literals at line end.
|
||||||
Style/LineEndConcatenation:
|
Style/LineEndConcatenation:
|
||||||
|
@ -323,33 +331,56 @@ Style/MethodCallParentheses:
|
||||||
|
|
||||||
# Checks if the method definitions have or don't have parentheses.
|
# Checks if the method definitions have or don't have parentheses.
|
||||||
Style/MethodDefParentheses:
|
Style/MethodDefParentheses:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use the configured style when naming methods.
|
# Use the configured style when naming methods.
|
||||||
Style/MethodName:
|
Style/MethodName:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for usage of `extend self` in modules.
|
# Checks for usage of `extend self` in modules.
|
||||||
Style/ModuleFunction:
|
Style/ModuleFunction:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# Checks that the closing brace in an array literal is either on the same line
|
||||||
|
# as the last array element, or a new line.
|
||||||
|
Style/MultilineArrayBraceLayout:
|
||||||
|
Enabled: false
|
||||||
|
EnforcedStyle: symmetrical
|
||||||
|
|
||||||
# Avoid multi-line chains of blocks.
|
# Avoid multi-line chains of blocks.
|
||||||
Style/MultilineBlockChain:
|
Style/MultilineBlockChain:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Ensures newlines after multiline block do statements.
|
# Ensures newlines after multiline block do statements.
|
||||||
Style/MultilineBlockLayout:
|
Style/MultilineBlockLayout:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks that the closing brace in a hash literal is either on the same line as
|
||||||
|
# the last hash element, or a new line.
|
||||||
|
Style/MultilineHashBraceLayout:
|
||||||
|
Enabled: false
|
||||||
|
EnforcedStyle: symmetrical
|
||||||
|
|
||||||
# Do not use then for multi-line if/unless.
|
# Do not use then for multi-line if/unless.
|
||||||
Style/MultilineIfThen:
|
Style/MultilineIfThen:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks that the closing brace in a method call is either on the same line as
|
||||||
|
# the last method argument, or a new line.
|
||||||
|
Style/MultilineMethodCallBraceLayout:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
EnforcedStyle: symmetrical
|
||||||
|
|
||||||
# Checks indentation of method calls with the dot operator that span more than
|
# Checks indentation of method calls with the dot operator that span more than
|
||||||
# one line.
|
# one line.
|
||||||
Style/MultilineMethodCallIndentation:
|
Style/MultilineMethodCallIndentation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# Checks that the closing brace in a method definition is symmetrical with
|
||||||
|
# respect to the opening brace and the method parameters.
|
||||||
|
Style/MultilineMethodDefinitionBraceLayout:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Checks indentation of binary operations that span more than one line.
|
# Checks indentation of binary operations that span more than one line.
|
||||||
Style/MultilineOperationIndentation:
|
Style/MultilineOperationIndentation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
@ -364,7 +395,7 @@ Style/MutableConstant:
|
||||||
|
|
||||||
# Favor unless over if for negative conditions (or control flow or).
|
# Favor unless over if for negative conditions (or control flow or).
|
||||||
Style/NegatedIf:
|
Style/NegatedIf:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Favor until over while for negative conditions.
|
# Favor until over while for negative conditions.
|
||||||
Style/NegatedWhile:
|
Style/NegatedWhile:
|
||||||
|
@ -372,7 +403,7 @@ Style/NegatedWhile:
|
||||||
|
|
||||||
# Avoid using nested modifiers.
|
# Avoid using nested modifiers.
|
||||||
Style/NestedModifier:
|
Style/NestedModifier:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Parenthesize method calls which are nested inside the argument list of
|
# Parenthesize method calls which are nested inside the argument list of
|
||||||
# another parenthesized method call.
|
# another parenthesized method call.
|
||||||
|
@ -409,7 +440,7 @@ Style/OneLineConditional:
|
||||||
|
|
||||||
# When defining binary operators, name the argument other.
|
# When defining binary operators, name the argument other.
|
||||||
Style/OpMethod:
|
Style/OpMethod:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Check for simple usages of parallel assignment. It will only warn when
|
# Check for simple usages of parallel assignment. It will only warn when
|
||||||
# the number of variables matches on both sides of the assignment.
|
# the number of variables matches on both sides of the assignment.
|
||||||
|
@ -456,10 +487,9 @@ Style/RedundantException:
|
||||||
Style/RedundantFreeze:
|
Style/RedundantFreeze:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# TODO: Enable RedundantParentheses Cop.
|
|
||||||
# Checks for parentheses that seem not to serve any purpose.
|
# Checks for parentheses that seem not to serve any purpose.
|
||||||
Style/RedundantParentheses:
|
Style/RedundantParentheses:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Don't use return where it's not required.
|
# Don't use return where it's not required.
|
||||||
Style/RedundantReturn:
|
Style/RedundantReturn:
|
||||||
|
@ -485,11 +515,12 @@ Style/SelfAssignment:
|
||||||
|
|
||||||
# Don't use semicolons to terminate expressions.
|
# Don't use semicolons to terminate expressions.
|
||||||
Style/Semicolon:
|
Style/Semicolon:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for proper usage of fail and raise.
|
# Checks for proper usage of fail and raise.
|
||||||
Style/SignalException:
|
Style/SignalException:
|
||||||
Enabled: false
|
EnforcedStyle: only_raise
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# Enforces the names of some block params.
|
# Enforces the names of some block params.
|
||||||
Style/SingleLineBlockParams:
|
Style/SingleLineBlockParams:
|
||||||
|
@ -510,25 +541,24 @@ Style/SpaceAfterComma:
|
||||||
# Do not put a space between a method name and the opening parenthesis in a
|
# Do not put a space between a method name and the opening parenthesis in a
|
||||||
# method definition.
|
# method definition.
|
||||||
Style/SpaceAfterMethodName:
|
Style/SpaceAfterMethodName:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Tracks redundant space after the ! operator.
|
# Tracks redundant space after the ! operator.
|
||||||
Style/SpaceAfterNot:
|
Style/SpaceAfterNot:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use spaces after semicolons.
|
# Use spaces after semicolons.
|
||||||
Style/SpaceAfterSemicolon:
|
Style/SpaceAfterSemicolon:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks that the equals signs in parameter default assignments have or don't
|
# Checks that the equals signs in parameter default assignments have or don't
|
||||||
# have surrounding space depending on configuration.
|
# have surrounding space depending on configuration.
|
||||||
Style/SpaceAroundEqualsInParameterDefault:
|
Style/SpaceAroundEqualsInParameterDefault:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# TODO: Enable SpaceAroundKeyword Cop.
|
|
||||||
# Use a space around keywords if appropriate.
|
# Use a space around keywords if appropriate.
|
||||||
Style/SpaceAroundKeyword:
|
Style/SpaceAroundKeyword:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use a single space around operators.
|
# Use a single space around operators.
|
||||||
Style/SpaceAroundOperators:
|
Style/SpaceAroundOperators:
|
||||||
|
@ -540,11 +570,11 @@ Style/SpaceBeforeBlockBraces:
|
||||||
|
|
||||||
# No spaces before commas.
|
# No spaces before commas.
|
||||||
Style/SpaceBeforeComma:
|
Style/SpaceBeforeComma:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for missing space between code and a comment on the same line.
|
# Checks for missing space between code and a comment on the same line.
|
||||||
Style/SpaceBeforeComment:
|
Style/SpaceBeforeComment:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks that exactly one space is used between a method name and the first
|
# Checks that exactly one space is used between a method name and the first
|
||||||
# argument for method calls without parentheses.
|
# argument for method calls without parentheses.
|
||||||
|
@ -553,7 +583,7 @@ Style/SpaceBeforeFirstArg:
|
||||||
|
|
||||||
# No spaces before semicolons.
|
# No spaces before semicolons.
|
||||||
Style/SpaceBeforeSemicolon:
|
Style/SpaceBeforeSemicolon:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks that block braces have or don't have surrounding space.
|
# Checks that block braces have or don't have surrounding space.
|
||||||
# For blocks taking parameters, checks that the left brace has or doesn't
|
# For blocks taking parameters, checks that the left brace has or doesn't
|
||||||
|
@ -575,11 +605,12 @@ Style/SpaceInsideParens:
|
||||||
|
|
||||||
# No spaces inside range literals.
|
# No spaces inside range literals.
|
||||||
Style/SpaceInsideRangeLiteral:
|
Style/SpaceInsideRangeLiteral:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for padding/surrounding spaces inside string interpolation.
|
# Checks for padding/surrounding spaces inside string interpolation.
|
||||||
Style/SpaceInsideStringInterpolation:
|
Style/SpaceInsideStringInterpolation:
|
||||||
Enabled: false
|
EnforcedStyle: no_space
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# Avoid Perl-style global variables.
|
# Avoid Perl-style global variables.
|
||||||
Style/SpecialGlobalVars:
|
Style/SpecialGlobalVars:
|
||||||
|
@ -587,7 +618,8 @@ Style/SpecialGlobalVars:
|
||||||
|
|
||||||
# Check for the usage of parentheses around stabby lambda arguments.
|
# Check for the usage of parentheses around stabby lambda arguments.
|
||||||
Style/StabbyLambdaParentheses:
|
Style/StabbyLambdaParentheses:
|
||||||
Enabled: false
|
EnforcedStyle: require_parentheses
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# Checks if uses of quotes match the configured preference.
|
# Checks if uses of quotes match the configured preference.
|
||||||
Style/StringLiterals:
|
Style/StringLiterals:
|
||||||
|
@ -600,7 +632,9 @@ Style/StringLiteralsInInterpolation:
|
||||||
|
|
||||||
# Checks if configured preferred methods are used over non-preferred.
|
# Checks if configured preferred methods are used over non-preferred.
|
||||||
Style/StringMethods:
|
Style/StringMethods:
|
||||||
Enabled: false
|
PreferredMethods:
|
||||||
|
intern: to_sym
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# Use %i or %I for arrays of symbols.
|
# Use %i or %I for arrays of symbols.
|
||||||
Style/SymbolArray:
|
Style/SymbolArray:
|
||||||
|
@ -658,23 +692,24 @@ Style/UnneededPercentQ:
|
||||||
|
|
||||||
# Don't interpolate global, instance and class variables directly in strings.
|
# Don't interpolate global, instance and class variables directly in strings.
|
||||||
Style/VariableInterpolation:
|
Style/VariableInterpolation:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use the configured style when naming variables.
|
# Use the configured style when naming variables.
|
||||||
Style/VariableName:
|
Style/VariableName:
|
||||||
Enabled: false
|
EnforcedStyle: snake_case
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# Use when x then ... for one-line cases.
|
# Use when x then ... for one-line cases.
|
||||||
Style/WhenThen:
|
Style/WhenThen:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for redundant do after while or until.
|
# Checks for redundant do after while or until.
|
||||||
Style/WhileUntilDo:
|
Style/WhileUntilDo:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Favor modifier while/until usage when you have a single-line body.
|
# Favor modifier while/until usage when you have a single-line body.
|
||||||
Style/WhileUntilModifier:
|
Style/WhileUntilModifier:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use %w or %W for arrays of words.
|
# Use %w or %W for arrays of words.
|
||||||
Style/WordArray:
|
Style/WordArray:
|
||||||
|
@ -737,7 +772,7 @@ Metrics/PerceivedComplexity:
|
||||||
# Checks for ambiguous operators in the first argument of a method invocation
|
# Checks for ambiguous operators in the first argument of a method invocation
|
||||||
# without parentheses.
|
# without parentheses.
|
||||||
Lint/AmbiguousOperator:
|
Lint/AmbiguousOperator:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for ambiguous regexp literals in the first argument of a method
|
# Checks for ambiguous regexp literals in the first argument of a method
|
||||||
# invocation without parentheses.
|
# invocation without parentheses.
|
||||||
|
@ -750,24 +785,24 @@ Lint/AssignmentInCondition:
|
||||||
|
|
||||||
# Align block ends correctly.
|
# Align block ends correctly.
|
||||||
Lint/BlockAlignment:
|
Lint/BlockAlignment:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Default values in optional keyword arguments and optional ordinal arguments
|
# Default values in optional keyword arguments and optional ordinal arguments
|
||||||
# should not refer back to the name of the argument.
|
# should not refer back to the name of the argument.
|
||||||
Lint/CircularArgumentReference:
|
Lint/CircularArgumentReference:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for condition placed in a confusing position relative to the keyword.
|
# Checks for condition placed in a confusing position relative to the keyword.
|
||||||
Lint/ConditionPosition:
|
Lint/ConditionPosition:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Check for debugger calls.
|
# Check for debugger calls.
|
||||||
Lint/Debugger:
|
Lint/Debugger:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Align ends corresponding to defs correctly.
|
# Align ends corresponding to defs correctly.
|
||||||
Lint/DefEndAlignment:
|
Lint/DefEndAlignment:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Check for deprecated class method calls.
|
# Check for deprecated class method calls.
|
||||||
Lint/DeprecatedClassMethods:
|
Lint/DeprecatedClassMethods:
|
||||||
|
@ -783,15 +818,15 @@ Lint/DuplicatedKey:
|
||||||
|
|
||||||
# Check for immutable argument given to each_with_object.
|
# Check for immutable argument given to each_with_object.
|
||||||
Lint/EachWithObjectArgument:
|
Lint/EachWithObjectArgument:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Check for odd code arrangement in an else block.
|
# Check for odd code arrangement in an else block.
|
||||||
Lint/ElseLayout:
|
Lint/ElseLayout:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for empty ensure block.
|
# Checks for empty ensure block.
|
||||||
Lint/EmptyEnsure:
|
Lint/EmptyEnsure:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for empty string interpolation.
|
# Checks for empty string interpolation.
|
||||||
Lint/EmptyInterpolation:
|
Lint/EmptyInterpolation:
|
||||||
|
@ -799,37 +834,36 @@ Lint/EmptyInterpolation:
|
||||||
|
|
||||||
# Align ends correctly.
|
# Align ends correctly.
|
||||||
Lint/EndAlignment:
|
Lint/EndAlignment:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# END blocks should not be placed inside method definitions.
|
# END blocks should not be placed inside method definitions.
|
||||||
Lint/EndInMethod:
|
Lint/EndInMethod:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Do not use return in an ensure block.
|
# Do not use return in an ensure block.
|
||||||
Lint/EnsureReturn:
|
Lint/EnsureReturn:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# The use of eval represents a serious security risk.
|
# The use of eval represents a serious security risk.
|
||||||
Lint/Eval:
|
Lint/Eval:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Catches floating-point literals too large or small for Ruby to represent.
|
# Catches floating-point literals too large or small for Ruby to represent.
|
||||||
Lint/FloatOutOfRange:
|
Lint/FloatOutOfRange:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# The number of parameters to format/sprint must match the fields.
|
# The number of parameters to format/sprint must match the fields.
|
||||||
Lint/FormatParameterMismatch:
|
Lint/FormatParameterMismatch:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Don't suppress exception.
|
# Don't suppress exception.
|
||||||
Lint/HandleExceptions:
|
Lint/HandleExceptions:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# TODO: Enable ImplicitStringConcatenation Cop.
|
|
||||||
# Checks for adjacent string literals on the same line, which could better be
|
# Checks for adjacent string literals on the same line, which could better be
|
||||||
# represented as a single string literal.
|
# represented as a single string literal.
|
||||||
Lint/ImplicitStringConcatenation:
|
Lint/ImplicitStringConcatenation:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# TODO: Enable IneffectiveAccessModifier Cop.
|
# TODO: Enable IneffectiveAccessModifier Cop.
|
||||||
# Checks for attempts to use `private` or `protected` to set the visibility
|
# Checks for attempts to use `private` or `protected` to set the visibility
|
||||||
|
@ -840,15 +874,15 @@ Lint/IneffectiveAccessModifier:
|
||||||
# Checks for invalid character literals with a non-escaped whitespace
|
# Checks for invalid character literals with a non-escaped whitespace
|
||||||
# character.
|
# character.
|
||||||
Lint/InvalidCharacterLiteral:
|
Lint/InvalidCharacterLiteral:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks of literals used in conditions.
|
# Checks of literals used in conditions.
|
||||||
Lint/LiteralInCondition:
|
Lint/LiteralInCondition:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for literals used in interpolation.
|
# Checks for literals used in interpolation.
|
||||||
Lint/LiteralInInterpolation:
|
Lint/LiteralInInterpolation:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use Kernel#loop with break rather than begin/end/until or begin/end/while
|
# Use Kernel#loop with break rather than begin/end/until or begin/end/while
|
||||||
# for post-loop tests.
|
# for post-loop tests.
|
||||||
|
@ -857,11 +891,11 @@ Lint/Loop:
|
||||||
|
|
||||||
# Do not use nested method definitions.
|
# Do not use nested method definitions.
|
||||||
Lint/NestedMethodDefinition:
|
Lint/NestedMethodDefinition:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Do not omit the accumulator when calling `next` in a `reduce`/`inject` block.
|
# Do not omit the accumulator when calling `next` in a `reduce`/`inject` block.
|
||||||
Lint/NextWithoutAccumulator:
|
Lint/NextWithoutAccumulator:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for method calls with a space before the opening parenthesis.
|
# Checks for method calls with a space before the opening parenthesis.
|
||||||
Lint/ParenthesesAsGroupedExpression:
|
Lint/ParenthesesAsGroupedExpression:
|
||||||
|
@ -870,11 +904,11 @@ Lint/ParenthesesAsGroupedExpression:
|
||||||
# Checks for `rand(1)` calls. Such calls always return `0` and most likely
|
# Checks for `rand(1)` calls. Such calls always return `0` and most likely
|
||||||
# a mistake.
|
# a mistake.
|
||||||
Lint/RandOne:
|
Lint/RandOne:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use parentheses in the method call to avoid confusion about precedence.
|
# Use parentheses in the method call to avoid confusion about precedence.
|
||||||
Lint/RequireParentheses:
|
Lint/RequireParentheses:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Avoid rescuing the Exception class.
|
# Avoid rescuing the Exception class.
|
||||||
Lint/RescueException:
|
Lint/RescueException:
|
||||||
|
@ -909,7 +943,7 @@ Lint/UnusedMethodArgument:
|
||||||
|
|
||||||
# Unreachable code.
|
# Unreachable code.
|
||||||
Lint/UnreachableCode:
|
Lint/UnreachableCode:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for useless access modifiers.
|
# Checks for useless access modifiers.
|
||||||
Lint/UselessAccessModifier:
|
Lint/UselessAccessModifier:
|
||||||
|
@ -921,19 +955,19 @@ Lint/UselessAssignment:
|
||||||
|
|
||||||
# Checks for comparison of something with itself.
|
# Checks for comparison of something with itself.
|
||||||
Lint/UselessComparison:
|
Lint/UselessComparison:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for useless `else` in `begin..end` without `rescue`.
|
# Checks for useless `else` in `begin..end` without `rescue`.
|
||||||
Lint/UselessElseWithoutRescue:
|
Lint/UselessElseWithoutRescue:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for useless setter call to a local variable.
|
# Checks for useless setter call to a local variable.
|
||||||
Lint/UselessSetterCall:
|
Lint/UselessSetterCall:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Possible use of operator/literal/variable in void context.
|
# Possible use of operator/literal/variable in void context.
|
||||||
Lint/Void:
|
Lint/Void:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
|
|
||||||
##################### Performance ############################
|
##################### Performance ############################
|
||||||
|
@ -942,11 +976,10 @@ Lint/Void:
|
||||||
Performance/Casecmp:
|
Performance/Casecmp:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# TODO: Enable DoubleStartEndWith Cop.
|
|
||||||
# Use `str.{start,end}_with?(x, ..., y, ...)` instead of
|
# Use `str.{start,end}_with?(x, ..., y, ...)` instead of
|
||||||
# `str.{start,end}_with?(x, ...) || str.{start,end}_with?(y, ...)`.
|
# `str.{start,end}_with?(x, ...) || str.{start,end}_with?(y, ...)`.
|
||||||
Performance/DoubleStartEndWith:
|
Performance/DoubleStartEndWith:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# TODO: Enable EndWith Cop.
|
# TODO: Enable EndWith Cop.
|
||||||
# Use `end_with?` instead of a regex match anchored to the end of a string.
|
# Use `end_with?` instead of a regex match anchored to the end of a string.
|
||||||
|
@ -957,10 +990,9 @@ Performance/EndWith:
|
||||||
Performance/LstripRstrip:
|
Performance/LstripRstrip:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# TODO: Enable RangeInclude Cop.
|
|
||||||
# Use `Range#cover?` instead of `Range#include?`.
|
# Use `Range#cover?` instead of `Range#include?`.
|
||||||
Performance/RangeInclude:
|
Performance/RangeInclude:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# TODO: Enable RedundantBlockCall Cop.
|
# TODO: Enable RedundantBlockCall Cop.
|
||||||
# Use `yield` instead of `block.call`.
|
# Use `yield` instead of `block.call`.
|
||||||
|
@ -980,16 +1012,14 @@ Performance/RedundantMerge:
|
||||||
MaxKeyValuePairs: 2
|
MaxKeyValuePairs: 2
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# TODO: Enable RedundantSortBy Cop.
|
|
||||||
# Use `sort` instead of `sort_by { |x| x }`.
|
# Use `sort` instead of `sort_by { |x| x }`.
|
||||||
Performance/RedundantSortBy:
|
Performance/RedundantSortBy:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# TODO: Enable StartWith Cop.
|
|
||||||
# Use `start_with?` instead of a regex match anchored to the beginning of a
|
# Use `start_with?` instead of a regex match anchored to the beginning of a
|
||||||
# string.
|
# string.
|
||||||
Performance/StartWith:
|
Performance/StartWith:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Use `tr` instead of `gsub` when you are replacing the same number of
|
# Use `tr` instead of `gsub` when you are replacing the same number of
|
||||||
# characters. Use `delete` instead of `gsub` when you are deleting
|
# characters. Use `delete` instead of `gsub` when you are deleting
|
||||||
|
@ -997,10 +1027,9 @@ Performance/StartWith:
|
||||||
Performance/StringReplacement:
|
Performance/StringReplacement:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# TODO: Enable TimesMap Cop.
|
|
||||||
# Checks for `.times.map` calls.
|
# Checks for `.times.map` calls.
|
||||||
Performance/TimesMap:
|
Performance/TimesMap:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
|
|
||||||
##################### Rails ##################################
|
##################### Rails ##################################
|
||||||
|
@ -1025,11 +1054,11 @@ Rails/Delegate:
|
||||||
|
|
||||||
# Prefer `find_by` over `where.first`.
|
# Prefer `find_by` over `where.first`.
|
||||||
Rails/FindBy:
|
Rails/FindBy:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Prefer `all.find_each` over `all.find`.
|
# Prefer `all.find_each` over `all.find`.
|
||||||
Rails/FindEach:
|
Rails/FindEach:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Prefer has_many :through to has_and_belongs_to_many.
|
# Prefer has_many :through to has_and_belongs_to_many.
|
||||||
Rails/HasAndBelongsToMany:
|
Rails/HasAndBelongsToMany:
|
||||||
|
@ -1041,7 +1070,7 @@ Rails/Output:
|
||||||
|
|
||||||
# Checks for incorrect grammar when using methods like `3.day.ago`.
|
# Checks for incorrect grammar when using methods like `3.day.ago`.
|
||||||
Rails/PluralizationGrammar:
|
Rails/PluralizationGrammar:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`.
|
# Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`.
|
||||||
Rails/ReadWriteAttribute:
|
Rails/ReadWriteAttribute:
|
||||||
|
@ -1049,7 +1078,7 @@ Rails/ReadWriteAttribute:
|
||||||
|
|
||||||
# Checks the arguments of ActiveRecord scopes.
|
# Checks the arguments of ActiveRecord scopes.
|
||||||
Rails/ScopeArgs:
|
Rails/ScopeArgs:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# Checks the correct usage of time zone aware methods.
|
# Checks the correct usage of time zone aware methods.
|
||||||
# http://danilenko.org/2012/7/6/rails_timezones
|
# http://danilenko.org/2012/7/6/rails_timezones
|
||||||
|
@ -1059,3 +1088,68 @@ Rails/TimeZone:
|
||||||
# Use validates :attribute, hash of validations.
|
# Use validates :attribute, hash of validations.
|
||||||
Rails/Validation:
|
Rails/Validation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
Rails/UniqBeforePluck:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
##################### RSpec ##################################
|
||||||
|
|
||||||
|
# Check that instances are not being stubbed globally.
|
||||||
|
RSpec/AnyInstance:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Check that the first argument to the top level describe is the tested class or
|
||||||
|
# module.
|
||||||
|
RSpec/DescribeClass:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Use `described_class` for tested class / module.
|
||||||
|
RSpec/DescribeMethod:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Checks that the second argument to top level describe is the tested method
|
||||||
|
# name.
|
||||||
|
RSpec/DescribedClass:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Checks for long example.
|
||||||
|
RSpec/ExampleLength:
|
||||||
|
Enabled: false
|
||||||
|
Max: 5
|
||||||
|
|
||||||
|
# Do not use should when describing your tests.
|
||||||
|
RSpec/ExampleWording:
|
||||||
|
Enabled: false
|
||||||
|
CustomTransform:
|
||||||
|
be: is
|
||||||
|
have: has
|
||||||
|
not: does not
|
||||||
|
IgnoredWords: []
|
||||||
|
|
||||||
|
# Checks the file and folder naming of the spec file.
|
||||||
|
RSpec/FilePath:
|
||||||
|
Enabled: false
|
||||||
|
CustomTransform:
|
||||||
|
RuboCop: rubocop
|
||||||
|
RSpec: rspec
|
||||||
|
|
||||||
|
# Checks if there are focused specs.
|
||||||
|
RSpec/Focus:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks for the usage of instance variables.
|
||||||
|
RSpec/InstanceVariable:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Checks for multiple top-level describes.
|
||||||
|
RSpec/MultipleDescribes:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Enforces the usage of the same method on all negative message expectations.
|
||||||
|
RSpec/NotToNot:
|
||||||
|
EnforcedStyle: not_to
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Prefer using verifying doubles over normal doubles.
|
||||||
|
RSpec/VerifiedDoubles:
|
||||||
|
Enabled: false
|
||||||
|
|
0
.vagrant_enabled
Normal file
0
.vagrant_enabled
Normal file
142
CHANGELOG
142
CHANGELOG
|
@ -1,8 +1,138 @@
|
||||||
Please view this file on the master branch, on stable branches it's out of date.
|
Please view this file on the master branch, on stable branches it's out of date.
|
||||||
|
|
||||||
|
v 8.9.0 (unreleased)
|
||||||
|
- Fix Error 500 when using closes_issues API with an external issue tracker
|
||||||
|
- Add more information into RSS feed for issues (Alexander Matyushentsev)
|
||||||
|
- Bulk assign/unassign labels to issues.
|
||||||
|
- Ability to prioritize labels !4009 / !3205 (Thijs Wouters)
|
||||||
|
- Fix endless redirections when accessing user OAuth applications when they are disabled
|
||||||
|
- Allow enabling wiki page events from Webhook management UI
|
||||||
|
- Bump rouge to 1.11.0
|
||||||
|
- Fix issue with arrow keys not working in search autocomplete dropdown
|
||||||
|
- Fix an issue where note polling stopped working if a window was in the
|
||||||
|
background during a refresh.
|
||||||
|
- Make EmailsOnPushWorker use Sidekiq mailers queue
|
||||||
|
- Fix wiki page events' webhook to point to the wiki repository
|
||||||
|
- Don't show tags for revert and cherry-pick operations
|
||||||
|
- Fix issue todo not remove when leave project !4150 (Long Nguyen)
|
||||||
|
- Allow customisable text on the 'nearly there' page after a user signs up
|
||||||
|
- Bump recaptcha gem to 3.0.0 to remove deprecated stoken support
|
||||||
|
- Fix SVG sanitizer to allow more elements
|
||||||
|
- Allow forking projects with restricted visibility level
|
||||||
|
- Added descriptions to notification settings dropdown
|
||||||
|
- Improve note validation to prevent errors when creating invalid note via API
|
||||||
|
- Reduce number of fog gem dependencies
|
||||||
|
- Remove project notification settings associated with deleted projects
|
||||||
|
- Fix 404 page when viewing TODOs that contain milestones or labels in different projects
|
||||||
|
- Add a metric for the number of new Redis connections created by a transaction
|
||||||
|
- Fix Error 500 when viewing a blob with binary characters after the 1024-byte mark
|
||||||
|
- Redesign navigation for project pages
|
||||||
|
- Fix groups API to list only user's accessible projects
|
||||||
|
- Add Environments and Deployments
|
||||||
|
- Redesign account and email confirmation emails
|
||||||
|
- Don't fail builds for projects that are deleted
|
||||||
|
- Support Docker Registry manifest v1
|
||||||
|
- `git clone https://host/namespace/project` now works, in addition to using the `.git` suffix
|
||||||
|
- Bump nokogiri to 1.6.8
|
||||||
|
- Use gitlab-shell v3.0.0
|
||||||
|
- Upgrade to jQuery 2
|
||||||
|
- Use Knapsack to evenly distribute tests across multiple nodes
|
||||||
|
- Add `sha` parameter to MR merge API, to ensure only reviewed changes are merged
|
||||||
|
- Don't allow MRs to be merged when commits were added since the last review / page load
|
||||||
|
- Add DB index on users.state
|
||||||
|
- Add rake task 'gitlab:db:configure' for conditionally seeding or migrating the database
|
||||||
|
- Changed the Slack build message to use the singular duration if necessary (Aran Koning)
|
||||||
|
- Links from a wiki page to other wiki pages should be rewritten as expected
|
||||||
|
- Add option to project to only allow merge requests to be merged if the build succeeds (Rui Santos)
|
||||||
|
- Fix issues filter when ordering by milestone
|
||||||
|
- Added artifacts:when to .gitlab-ci.yml - this requires GitLab Runner 1.3
|
||||||
|
- Bamboo Service: Fix missing credentials & URL handling when base URL contains a path (Benjamin Schmid)
|
||||||
|
- TeamCity Service: Fix URL handling when base URL contains a path
|
||||||
|
- Todos will display target state if issuable target is 'Closed' or 'Merged'
|
||||||
|
- Fix bug when sorting issues by milestone due date and filtering by two or more labels
|
||||||
|
- Add support for using Yubikeys (U2F) for two-factor authentication
|
||||||
|
- Link to blank group icon doesn't throw a 404 anymore
|
||||||
|
- Remove 'main language' feature
|
||||||
|
- Pipelines can be canceled only when there are running builds
|
||||||
|
- Use downcased path to container repository as this is expected path by Docker
|
||||||
|
- Projects pending deletion will render a 404 page
|
||||||
|
- Measure queue duration between gitlab-workhorse and Rails
|
||||||
|
- Make Omniauth providers specs to not modify global configuration
|
||||||
|
- Make authentication service for Container Registry to be compatible with < Docker 1.11
|
||||||
|
- Add Application Setting to configure Container Registry token expire delay (default 5min)
|
||||||
|
- Cache assigned issue and merge request counts in sidebar nav
|
||||||
|
- Use Knapsack only in CI environment
|
||||||
|
- Cache project build count in sidebar nav
|
||||||
|
- Add milestone expire date to the right sidebar
|
||||||
|
- Manually mark a issue or merge request as a todo
|
||||||
|
- Fix markdown_spec to use before instead of before(:all) to properly cleanup database after testing
|
||||||
|
- Reduce number of queries needed to render issue labels in the sidebar
|
||||||
|
- Improve error handling importing projects
|
||||||
|
- Remove duplicated notification settings
|
||||||
|
- Put project Files and Commits tabs under Code tab
|
||||||
|
- Decouple global notification level from user model
|
||||||
|
- Replace Colorize with Rainbow for coloring console output in Rake tasks.
|
||||||
|
- Add workhorse controller and API helpers
|
||||||
|
- An indicator is now displayed at the top of the comment field for confidential issues.
|
||||||
|
- RepositoryCheck::SingleRepositoryWorker public and private methods are now instrumented
|
||||||
|
- Improve issuables APIs performance when accessing notes !4471
|
||||||
|
- External links now open in a new tab
|
||||||
|
- Prevent default actions of disabled buttons and links
|
||||||
|
- Markdown editor now correctly resets the input value on edit cancellation !4175
|
||||||
|
- Toggling a task list item in a issue/mr description does not creates a Todo for mentions
|
||||||
|
- Improved UX of date pickers on issue & milestone forms
|
||||||
|
- Cache on the database if a project has an active external issue tracker.
|
||||||
|
- Put project Labels and Milestones pages links under Issues and Merge Requests tabs as subnav
|
||||||
|
- All classes in the Banzai::ReferenceParser namespace are now instrumented
|
||||||
|
- Remove deprecated issues_tracker and issues_tracker_id from project model
|
||||||
|
- Allow users to create confidential issues in private projects
|
||||||
|
- Measure CPU time for instrumented methods
|
||||||
|
- Instrument private methods and private instance methods by default instead just public methods
|
||||||
|
- Only show notes through JSON on confidential issues that the user has access to
|
||||||
|
- Updated the allocations Gem to version 1.0.5
|
||||||
|
- The background sampler now ignores classes without names
|
||||||
|
- Update design for `Close` buttons
|
||||||
|
- New custom icons for navigation
|
||||||
|
- Horizontally scrolling navigation on project, group, and profile settings pages
|
||||||
|
- Hide global side navigation by default
|
||||||
|
- Fix project Star/Unstar project button tooltip
|
||||||
|
- Remove tanuki logo from side navigation; center on top nav
|
||||||
|
- Include user relationships when retrieving award_emoji
|
||||||
|
- Various associations are now eager loaded when parsing issue references to reduce the number of queries executed
|
||||||
|
|
||||||
|
v 8.8.5 (unreleased)
|
||||||
|
- Ensure branch cleanup regardless of whether the GitHub import process succeeds
|
||||||
|
- Fix todos page throwing errors when you have a project pending deletion
|
||||||
|
- Reduce number of SQL queries when rendering user references
|
||||||
|
- Import GitHub repositories respecting the API rate limit
|
||||||
|
- Fix importer for GitHub comments on diff
|
||||||
|
- Disable Webhooks before proceeding with the GitHub import
|
||||||
|
- Fix incremental trace upload API when using multi-byte UTF-8 chars in trace
|
||||||
|
|
||||||
|
v 8.8.4
|
||||||
|
- Fix LDAP-based login for users with 2FA enabled. !4493
|
||||||
|
|
||||||
|
v 8.8.3
|
||||||
|
- Fix 404 page when viewing TODOs that contain milestones or labels in different projects. !4312
|
||||||
|
- Fixed JS error when trying to remove discussion form. !4303
|
||||||
|
- Fixed issue with button color when no CI enabled. !4287
|
||||||
|
- Fixed potential issue with 2 CI status polling events happening. !3869
|
||||||
|
- Improve design of Pipeline view. !4230
|
||||||
|
- Fix gitlab importer failing to import new projects due to missing credentials. !4301
|
||||||
|
- Fix import URL migration not rescuing with the correct Error. !4321
|
||||||
|
- Fix health check access token changing due to old application settings being used. !4332
|
||||||
|
- Make authentication service for Container Registry to be compatible with Docker versions before 1.11. !4363
|
||||||
|
- Add Application Setting to configure Container Registry token expire delay (default 5 min). !4364
|
||||||
|
- Pass the "Remember me" value to the 2FA token form. !4369
|
||||||
|
- Fix incorrect links on pipeline page when merge request created from fork. !4376
|
||||||
|
- Use downcased path to container repository as this is expected path by Docker. !4420
|
||||||
|
- Fix wiki project clone address error (chujinjin). !4429
|
||||||
|
- Fix serious performance bug with rendering Markdown with InlineDiffFilter. !4392
|
||||||
|
- Fix missing number on generated ordered list element. !4437
|
||||||
|
- Prevent disclosure of notes on confidential issues in search results.
|
||||||
|
|
||||||
v 8.8.2
|
v 8.8.2
|
||||||
- Added remove due date button. !4209
|
- Added remove due date button. !4209
|
||||||
- Fix access to Pipelines by Anonymous user. !4233
|
|
||||||
- Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242
|
- Fix Error 500 when accessing application settings due to nil disabled OAuth sign-in sources. !4242
|
||||||
- Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245
|
- Fix Error 500 in CI charts by gracefully handling commits with no durations. !4245
|
||||||
- Fix table UI on CI builds page. !4249
|
- Fix table UI on CI builds page. !4249
|
||||||
|
@ -14,7 +144,7 @@ v 8.8.2
|
||||||
|
|
||||||
v 8.8.1
|
v 8.8.1
|
||||||
- Add documentation for the "Health Check" feature
|
- Add documentation for the "Health Check" feature
|
||||||
- Allow anonymous users to access a public project's pipelines
|
- Allow anonymous users to access a public project's pipelines !4233
|
||||||
- Fix MySQL compatibility in zero downtime migrations helpers
|
- Fix MySQL compatibility in zero downtime migrations helpers
|
||||||
- Fix the CI login to Container Registry (the gitlab-ci-token user)
|
- Fix the CI login to Container Registry (the gitlab-ci-token user)
|
||||||
|
|
||||||
|
@ -31,6 +161,7 @@ v 8.8.0
|
||||||
- Added inline diff styling for `change_title` system notes. (Adam Butler)
|
- Added inline diff styling for `change_title` system notes. (Adam Butler)
|
||||||
- Project#open_branches has been cleaned up and no longer loads entire records into memory.
|
- Project#open_branches has been cleaned up and no longer loads entire records into memory.
|
||||||
- Escape HTML in commit titles in system note messages
|
- Escape HTML in commit titles in system note messages
|
||||||
|
- Improve design of Pipeline View
|
||||||
- Fix scope used when accessing container registry
|
- Fix scope used when accessing container registry
|
||||||
- Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios
|
- Fix creation of Ci::Commit object which can lead to pending, failed in some scenarios
|
||||||
- Improve multiple branch push performance by memoizing permission checking
|
- Improve multiple branch push performance by memoizing permission checking
|
||||||
|
@ -90,11 +221,18 @@ v 8.8.0
|
||||||
- Improve Issue formatting for the Slack Service (Jeroen van Baarsen)
|
- Improve Issue formatting for the Slack Service (Jeroen van Baarsen)
|
||||||
- Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine)
|
- Fixed advice on invalid permissions on upload path !2948 (Ludovic Perrine)
|
||||||
- Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs)
|
- Allows MR authors to have the source branch removed when merging the MR. !2801 (Jeroen Jacobs)
|
||||||
|
- When creating a .gitignore file a dropdown with templates will be provided
|
||||||
|
- Shows the issue/MR list search/filter form and corrects the mobile styling for guest users. #17562
|
||||||
|
|
||||||
|
v 8.7.7
|
||||||
|
- Fix import by `Any Git URL` broken if the URL contains a space
|
||||||
|
|
||||||
v 8.7.6
|
v 8.7.6
|
||||||
- Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko)
|
- Fix links on wiki pages for relative url setups. !4131 (Artem Sidorenko)
|
||||||
- Fix import from GitLab.com to a private instance failure. !4181
|
- Fix import from GitLab.com to a private instance failure. !4181
|
||||||
- Fix external imports not finding the import data. !4106
|
- Fix external imports not finding the import data. !4106
|
||||||
|
- Fix notification delay when changing status of an issue
|
||||||
|
- Bump Workhorse to 0.7.5 so it can serve raw diffs
|
||||||
|
|
||||||
v 8.7.5
|
v 8.7.5
|
||||||
- Fix relative links in wiki pages. !4050
|
- Fix relative links in wiki pages. !4050
|
||||||
|
|
|
@ -96,7 +96,7 @@ The designs are made using Antetype (`.atype` files). You can use the
|
||||||
[free Antetype viewer (Mac OSX only)] or grab an exported PNG from the design
|
[free Antetype viewer (Mac OSX only)] or grab an exported PNG from the design
|
||||||
(the PNG is 1:1).
|
(the PNG is 1:1).
|
||||||
|
|
||||||
The current designs can be found in the [`gitlab1.atype` file].
|
The current designs can be found in the [`gitlab8.atype` file].
|
||||||
|
|
||||||
### UI development kit
|
### UI development kit
|
||||||
|
|
||||||
|
@ -308,16 +308,14 @@ tests are least likely to receive timely feedback. The workflow to make a merge
|
||||||
request is as follows:
|
request is as follows:
|
||||||
|
|
||||||
1. Fork the project into your personal space on GitLab.com
|
1. Fork the project into your personal space on GitLab.com
|
||||||
1. Create a feature branch
|
1. Create a feature branch, branch away from `master`.
|
||||||
1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code
|
1. Write [tests](https://gitlab.com/gitlab-org/gitlab-development-kit#running-the-tests) and code
|
||||||
1. Add your changes to the [CHANGELOG](CHANGELOG)
|
1. Add your changes to the [CHANGELOG](CHANGELOG)
|
||||||
1. If you are changing the README, some documentation or other things which
|
1. If you are writing documentation, make sure to read the [documentation styleguide][doc-styleguide]
|
||||||
have no effect on the tests, add `[ci skip]` somewhere in the commit message
|
|
||||||
and make sure to read the [documentation styleguide][doc-styleguide]
|
|
||||||
1. If you have multiple commits please combine them into one commit by
|
1. If you have multiple commits please combine them into one commit by
|
||||||
[squashing them][git-squash]
|
[squashing them][git-squash]
|
||||||
1. Push the commit(s) to your fork
|
1. Push the commit(s) to your fork
|
||||||
1. Submit a merge request (MR) to the master branch
|
1. Submit a merge request (MR) to the `master` branch
|
||||||
1. The MR title should describe the change you want to make
|
1. The MR title should describe the change you want to make
|
||||||
1. The MR description should give a motive for your change and the method you
|
1. The MR description should give a motive for your change and the method you
|
||||||
used to achieve it, see the [merge request description format]
|
used to achieve it, see the [merge request description format]
|
||||||
|
@ -407,6 +405,7 @@ description area. Copy-paste it to retain the markdown format.
|
||||||
entire line to follow it. This prevents linting tools from generating warnings.
|
entire line to follow it. This prevents linting tools from generating warnings.
|
||||||
- Don't touch neighbouring lines. As an exception, automatic mass
|
- Don't touch neighbouring lines. As an exception, automatic mass
|
||||||
refactoring modifications may leave style non-compliant.
|
refactoring modifications may leave style non-compliant.
|
||||||
|
1. If the merge request adds any new libraries (gems, JavaScript libraries, etc.), they should conform to our [Licensing guidelines][license-finder-doc]. See the instructions in that document for help if your MR fails the "license-finder" test with a "Dependencies that need approval" error.
|
||||||
|
|
||||||
## Changes for Stable Releases
|
## Changes for Stable Releases
|
||||||
|
|
||||||
|
@ -532,4 +531,5 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
|
||||||
[scss-styleguide]: doc/development/scss_styleguide.md "SCSS styleguide"
|
[scss-styleguide]: doc/development/scss_styleguide.md "SCSS styleguide"
|
||||||
[gitlab-design]: https://gitlab.com/gitlab-org/gitlab-design
|
[gitlab-design]: https://gitlab.com/gitlab-org/gitlab-design
|
||||||
[free Antetype viewer (Mac OSX only)]: https://itunes.apple.com/us/app/antetype-viewer/id824152298?mt=12
|
[free Antetype viewer (Mac OSX only)]: https://itunes.apple.com/us/app/antetype-viewer/id824152298?mt=12
|
||||||
[`gitlab1.atype` file]: https://gitlab.com/gitlab-org/gitlab-design/tree/master/gitlab1.atype/
|
[`gitlab8.atype` file]: https://gitlab.com/gitlab-org/gitlab-design/tree/master/current/
|
||||||
|
[license-finder-doc]: doc/development/licensing.md
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
2.7.2
|
3.0.0
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.7.1
|
0.7.5
|
||||||
|
|
45
Gemfile
45
Gemfile
|
@ -18,9 +18,8 @@ gem "mysql2", '~> 0.3.16', group: :mysql
|
||||||
gem "pg", '~> 0.18.2', group: :postgres
|
gem "pg", '~> 0.18.2', group: :postgres
|
||||||
|
|
||||||
# Authentication libraries
|
# Authentication libraries
|
||||||
gem 'devise', '~> 3.5.4'
|
gem 'devise', '~> 4.0'
|
||||||
gem 'doorkeeper', '~> 3.1'
|
gem 'doorkeeper', '~> 3.1'
|
||||||
gem 'devise-async', '~> 0.9.0'
|
|
||||||
gem 'omniauth', '~> 1.3.1'
|
gem 'omniauth', '~> 1.3.1'
|
||||||
gem 'omniauth-auth0', '~> 1.4.1'
|
gem 'omniauth-auth0', '~> 1.4.1'
|
||||||
gem 'omniauth-azure-oauth2', '~> 0.0.6'
|
gem 'omniauth-azure-oauth2', '~> 0.0.6'
|
||||||
|
@ -39,16 +38,17 @@ gem 'rack-oauth2', '~> 1.2.1'
|
||||||
gem 'jwt'
|
gem 'jwt'
|
||||||
|
|
||||||
# Spam and anti-bot protection
|
# Spam and anti-bot protection
|
||||||
gem 'recaptcha', require: 'recaptcha/rails'
|
gem 'recaptcha', '~> 3.0', require: 'recaptcha/rails'
|
||||||
gem 'akismet', '~> 2.0'
|
gem 'akismet', '~> 2.0'
|
||||||
|
|
||||||
# Two-factor authentication
|
# Two-factor authentication
|
||||||
gem 'devise-two-factor', '~> 2.0.0'
|
gem 'devise-two-factor', '~> 3.0.0'
|
||||||
gem 'rqrcode-rails3', '~> 0.1.7'
|
gem 'rqrcode-rails3', '~> 0.1.7'
|
||||||
gem 'attr_encrypted', '~> 1.3.4'
|
gem 'attr_encrypted', '~> 3.0.0'
|
||||||
|
gem 'u2f', '~> 0.2.1'
|
||||||
|
|
||||||
# Browser detection
|
# Browser detection
|
||||||
gem "browser", '~> 1.0.0'
|
gem "browser", '~> 2.0.3'
|
||||||
|
|
||||||
# Extracting information from a git repository
|
# Extracting information from a git repository
|
||||||
# Provide access to Gitlab::Git library
|
# Provide access to Gitlab::Git library
|
||||||
|
@ -73,7 +73,7 @@ gem 'grape-entity', '~> 0.4.2'
|
||||||
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||||
|
|
||||||
# Pagination
|
# Pagination
|
||||||
gem "kaminari", "~> 0.16.3"
|
gem "kaminari", "~> 0.17.0"
|
||||||
|
|
||||||
# HAML
|
# HAML
|
||||||
gem "haml-rails", '~> 0.9.0'
|
gem "haml-rails", '~> 0.9.0'
|
||||||
|
@ -84,8 +84,15 @@ gem "carrierwave", '~> 0.10.0'
|
||||||
# Drag and Drop UI
|
# Drag and Drop UI
|
||||||
gem 'dropzonejs-rails', '~> 0.7.1'
|
gem 'dropzonejs-rails', '~> 0.7.1'
|
||||||
|
|
||||||
|
# for backups
|
||||||
|
gem 'fog-aws', '~> 0.9'
|
||||||
|
gem 'fog-azure', '~> 0.0'
|
||||||
|
gem 'fog-core', '~> 1.40'
|
||||||
|
gem 'fog-local', '~> 0.3'
|
||||||
|
gem 'fog-google', '~> 0.3'
|
||||||
|
gem 'fog-openstack', '~> 0.1'
|
||||||
|
|
||||||
# for aws storage
|
# for aws storage
|
||||||
gem "fog", "~> 1.36.0"
|
|
||||||
gem "unf", '~> 0.1.4'
|
gem "unf", '~> 0.1.4'
|
||||||
|
|
||||||
# Authorization
|
# Authorization
|
||||||
|
@ -105,7 +112,7 @@ gem 'org-ruby', '~> 0.9.12'
|
||||||
gem 'creole', '~> 0.5.0'
|
gem 'creole', '~> 0.5.0'
|
||||||
gem 'wikicloth', '0.8.1'
|
gem 'wikicloth', '0.8.1'
|
||||||
gem 'asciidoctor', '~> 1.5.2'
|
gem 'asciidoctor', '~> 1.5.2'
|
||||||
gem 'rouge', '~> 1.10.1'
|
gem 'rouge', '~> 1.11'
|
||||||
|
|
||||||
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
|
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
|
||||||
# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
|
# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
|
||||||
|
@ -121,7 +128,7 @@ group :unicorn do
|
||||||
end
|
end
|
||||||
|
|
||||||
# State machine
|
# State machine
|
||||||
gem "state_machines-activerecord", '~> 0.3.0'
|
gem "state_machines-activerecord", '~> 0.4.0'
|
||||||
# Run events after state machine commits
|
# Run events after state machine commits
|
||||||
gem 'after_commit_queue'
|
gem 'after_commit_queue'
|
||||||
|
|
||||||
|
@ -138,7 +145,7 @@ gem 'redis-namespace'
|
||||||
gem "httparty", '~> 0.13.3'
|
gem "httparty", '~> 0.13.3'
|
||||||
|
|
||||||
# Colored output to console
|
# Colored output to console
|
||||||
gem "colorize", '~> 0.7.0'
|
gem "rainbow", '~> 2.1.0'
|
||||||
|
|
||||||
# GitLab settings
|
# GitLab settings
|
||||||
gem 'settingslogic', '~> 2.0.9'
|
gem 'settingslogic', '~> 2.0.9'
|
||||||
|
@ -178,9 +185,6 @@ gem 'ruby-fogbugz', '~> 0.2.1'
|
||||||
# d3
|
# d3
|
||||||
gem 'd3_rails', '~> 3.5.0'
|
gem 'd3_rails', '~> 3.5.0'
|
||||||
|
|
||||||
#cal-heatmap
|
|
||||||
gem 'cal-heatmap-rails', '~> 3.6.0'
|
|
||||||
|
|
||||||
# underscore-rails
|
# underscore-rails
|
||||||
gem "underscore-rails", "~> 1.8.0"
|
gem "underscore-rails", "~> 1.8.0"
|
||||||
|
|
||||||
|
@ -206,6 +210,9 @@ gem 'mousetrap-rails', '~> 1.4.6'
|
||||||
# Detect and convert string character encoding
|
# Detect and convert string character encoding
|
||||||
gem 'charlock_holmes', '~> 0.7.3'
|
gem 'charlock_holmes', '~> 0.7.3'
|
||||||
|
|
||||||
|
# Parse duration
|
||||||
|
gem 'chronic_duration', '~> 0.10.6'
|
||||||
|
|
||||||
gem "sass-rails", '~> 5.0.0'
|
gem "sass-rails", '~> 5.0.0'
|
||||||
gem "coffee-rails", '~> 4.1.0'
|
gem "coffee-rails", '~> 4.1.0'
|
||||||
gem "uglifier", '~> 2.7.2'
|
gem "uglifier", '~> 2.7.2'
|
||||||
|
@ -241,7 +248,7 @@ end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem "foreman"
|
gem "foreman"
|
||||||
gem 'brakeman', '~> 3.2.0', require: false
|
gem 'brakeman', '~> 3.3.0', require: false
|
||||||
|
|
||||||
gem 'letter_opener_web', '~> 1.3.0'
|
gem 'letter_opener_web', '~> 1.3.0'
|
||||||
gem 'quiet_assets', '~> 1.0.2'
|
gem 'quiet_assets', '~> 1.0.2'
|
||||||
|
@ -293,7 +300,8 @@ group :development, :test do
|
||||||
gem 'spring-commands-spinach', '~> 1.1.0'
|
gem 'spring-commands-spinach', '~> 1.1.0'
|
||||||
gem 'spring-commands-teaspoon', '~> 0.0.2'
|
gem 'spring-commands-teaspoon', '~> 0.0.2'
|
||||||
|
|
||||||
gem 'rubocop', '~> 0.38.0', require: false
|
gem 'rubocop', '~> 0.40.0', require: false
|
||||||
|
gem 'rubocop-rspec', '~> 1.5.0', require: false
|
||||||
gem 'scss_lint', '~> 0.47.0', require: false
|
gem 'scss_lint', '~> 0.47.0', require: false
|
||||||
gem 'coveralls', '~> 0.8.2', require: false
|
gem 'coveralls', '~> 0.8.2', require: false
|
||||||
gem 'simplecov', '~> 0.11.0', require: false
|
gem 'simplecov', '~> 0.11.0', require: false
|
||||||
|
@ -302,6 +310,9 @@ group :development, :test do
|
||||||
gem 'bundler-audit', require: false
|
gem 'bundler-audit', require: false
|
||||||
|
|
||||||
gem 'benchmark-ips', require: false
|
gem 'benchmark-ips', require: false
|
||||||
|
|
||||||
|
gem "license_finder", require: false
|
||||||
|
gem 'knapsack'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
@ -325,7 +336,7 @@ gem "mail_room", "~> 0.7"
|
||||||
gem 'email_reply_parser', '~> 0.5.8'
|
gem 'email_reply_parser', '~> 0.5.8'
|
||||||
|
|
||||||
## CI
|
## CI
|
||||||
gem 'activerecord-session_store', '~> 0.1.0'
|
gem 'activerecord-session_store', '~> 1.0.0'
|
||||||
gem "nested_form", '~> 0.3.2'
|
gem "nested_form", '~> 0.3.2'
|
||||||
|
|
||||||
# OAuth
|
# OAuth
|
||||||
|
|
288
Gemfile.lock
288
Gemfile.lock
|
@ -1,7 +1,6 @@
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
CFPropertyList (2.3.2)
|
|
||||||
RedCloth (4.2.9)
|
RedCloth (4.2.9)
|
||||||
ace-rails-ap (4.0.2)
|
ace-rails-ap (4.0.2)
|
||||||
actionmailer (4.2.6)
|
actionmailer (4.2.6)
|
||||||
|
@ -33,10 +32,12 @@ GEM
|
||||||
activemodel (= 4.2.6)
|
activemodel (= 4.2.6)
|
||||||
activesupport (= 4.2.6)
|
activesupport (= 4.2.6)
|
||||||
arel (~> 6.0)
|
arel (~> 6.0)
|
||||||
activerecord-session_store (0.1.2)
|
activerecord-session_store (1.0.0)
|
||||||
actionpack (>= 4.0.0, < 5)
|
actionpack (>= 4.0, < 5.1)
|
||||||
activerecord (>= 4.0.0, < 5)
|
activerecord (>= 4.0, < 5.1)
|
||||||
railties (>= 4.0.0, < 5)
|
multi_json (~> 1.11, >= 1.11.2)
|
||||||
|
rack (>= 1.5.2, < 3)
|
||||||
|
railties (>= 4.0, < 5.1)
|
||||||
activesupport (4.2.6)
|
activesupport (4.2.6)
|
||||||
i18n (~> 0.7)
|
i18n (~> 0.7)
|
||||||
json (~> 1.7, >= 1.7.7)
|
json (~> 1.7, >= 1.7.7)
|
||||||
|
@ -49,7 +50,7 @@ GEM
|
||||||
after_commit_queue (1.3.0)
|
after_commit_queue (1.3.0)
|
||||||
activerecord (>= 3.0)
|
activerecord (>= 3.0)
|
||||||
akismet (2.0.0)
|
akismet (2.0.0)
|
||||||
allocations (1.0.4)
|
allocations (1.0.5)
|
||||||
arel (6.0.3)
|
arel (6.0.3)
|
||||||
asana (0.4.0)
|
asana (0.4.0)
|
||||||
faraday (~> 0.9)
|
faraday (~> 0.9)
|
||||||
|
@ -58,8 +59,8 @@ GEM
|
||||||
oauth2 (~> 1.0)
|
oauth2 (~> 1.0)
|
||||||
asciidoctor (1.5.3)
|
asciidoctor (1.5.3)
|
||||||
ast (2.2.0)
|
ast (2.2.0)
|
||||||
attr_encrypted (1.3.4)
|
attr_encrypted (3.0.1)
|
||||||
encryptor (>= 1.3.0)
|
encryptor (~> 3.0.0)
|
||||||
attr_required (1.0.0)
|
attr_required (1.0.0)
|
||||||
autoprefixer-rails (6.2.3)
|
autoprefixer-rails (6.2.3)
|
||||||
execjs
|
execjs
|
||||||
|
@ -69,9 +70,24 @@ GEM
|
||||||
descendants_tracker (~> 0.0.4)
|
descendants_tracker (~> 0.0.4)
|
||||||
ice_nine (~> 0.11.0)
|
ice_nine (~> 0.11.0)
|
||||||
thread_safe (~> 0.3, >= 0.3.1)
|
thread_safe (~> 0.3, >= 0.3.1)
|
||||||
|
azure (0.7.5)
|
||||||
|
addressable (~> 2.3)
|
||||||
|
azure-core (~> 0.1)
|
||||||
|
faraday (~> 0.9)
|
||||||
|
faraday_middleware (~> 0.10)
|
||||||
|
json (~> 1.8)
|
||||||
|
mime-types (>= 1, < 3.0)
|
||||||
|
nokogiri (~> 1.6)
|
||||||
|
systemu (~> 2.6)
|
||||||
|
thor (~> 0.19)
|
||||||
|
uuid (~> 2.0)
|
||||||
|
azure-core (0.1.2)
|
||||||
|
faraday (~> 0.9)
|
||||||
|
faraday_middleware (~> 0.10)
|
||||||
|
nokogiri (~> 1.6)
|
||||||
babosa (1.0.2)
|
babosa (1.0.2)
|
||||||
base32 (0.3.2)
|
base32 (0.3.2)
|
||||||
bcrypt (3.1.10)
|
bcrypt (3.1.11)
|
||||||
benchmark-ips (2.3.0)
|
benchmark-ips (2.3.0)
|
||||||
better_errors (1.0.1)
|
better_errors (1.0.1)
|
||||||
coderay (>= 1.0.0)
|
coderay (>= 1.0.0)
|
||||||
|
@ -81,17 +97,8 @@ GEM
|
||||||
bootstrap-sass (3.3.6)
|
bootstrap-sass (3.3.6)
|
||||||
autoprefixer-rails (>= 5.2.1)
|
autoprefixer-rails (>= 5.2.1)
|
||||||
sass (>= 3.3.4)
|
sass (>= 3.3.4)
|
||||||
brakeman (3.2.1)
|
brakeman (3.3.2)
|
||||||
erubis (~> 2.6)
|
browser (2.0.3)
|
||||||
haml (>= 3.0, < 5.0)
|
|
||||||
highline (>= 1.6.20, < 2.0)
|
|
||||||
ruby2ruby (~> 2.3.0)
|
|
||||||
ruby_parser (~> 3.8.1)
|
|
||||||
safe_yaml (>= 1.0)
|
|
||||||
sass (~> 3.0)
|
|
||||||
slim (>= 1.3.6, < 4.0)
|
|
||||||
terminal-table (~> 1.4)
|
|
||||||
browser (1.0.1)
|
|
||||||
builder (3.2.2)
|
builder (3.2.2)
|
||||||
bullet (5.0.0)
|
bullet (5.0.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
|
@ -100,7 +107,6 @@ GEM
|
||||||
bundler (~> 1.2)
|
bundler (~> 1.2)
|
||||||
thor (~> 0.18)
|
thor (~> 0.18)
|
||||||
byebug (8.2.1)
|
byebug (8.2.1)
|
||||||
cal-heatmap-rails (3.6.0)
|
|
||||||
capybara (2.6.2)
|
capybara (2.6.2)
|
||||||
addressable
|
addressable
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
|
@ -118,6 +124,8 @@ GEM
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
cause (0.1)
|
cause (0.1)
|
||||||
charlock_holmes (0.7.3)
|
charlock_holmes (0.7.3)
|
||||||
|
chronic_duration (0.10.6)
|
||||||
|
numerizer (~> 0.1.1)
|
||||||
chunky_png (1.3.5)
|
chunky_png (1.3.5)
|
||||||
cliver (0.3.2)
|
cliver (0.3.2)
|
||||||
coderay (1.1.0)
|
coderay (1.1.0)
|
||||||
|
@ -154,21 +162,18 @@ GEM
|
||||||
activerecord (>= 3.2.0, < 5.0)
|
activerecord (>= 3.2.0, < 5.0)
|
||||||
descendants_tracker (0.0.4)
|
descendants_tracker (0.0.4)
|
||||||
thread_safe (~> 0.3, >= 0.3.1)
|
thread_safe (~> 0.3, >= 0.3.1)
|
||||||
devise (3.5.4)
|
devise (4.1.1)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
railties (>= 3.2.6, < 5)
|
railties (>= 4.1.0, < 5.1)
|
||||||
responders
|
responders
|
||||||
thread_safe (~> 0.1)
|
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise-async (0.9.0)
|
devise-two-factor (3.0.0)
|
||||||
devise (~> 3.2)
|
|
||||||
devise-two-factor (2.0.1)
|
|
||||||
activesupport
|
activesupport
|
||||||
attr_encrypted (~> 1.3.2)
|
attr_encrypted (>= 1.3, < 4, != 2)
|
||||||
devise (~> 3.5.0)
|
devise (~> 4.0)
|
||||||
railties
|
railties
|
||||||
rotp (~> 2)
|
rotp (~> 2.0)
|
||||||
diff-lcs (1.2.5)
|
diff-lcs (1.2.5)
|
||||||
diffy (3.0.7)
|
diffy (3.0.7)
|
||||||
docile (1.1.5)
|
docile (1.1.5)
|
||||||
|
@ -180,12 +185,12 @@ GEM
|
||||||
email_spec (1.6.0)
|
email_spec (1.6.0)
|
||||||
launchy (~> 2.1)
|
launchy (~> 2.1)
|
||||||
mail (~> 2.2)
|
mail (~> 2.2)
|
||||||
encryptor (1.3.0)
|
encryptor (3.0.0)
|
||||||
equalizer (0.0.11)
|
equalizer (0.0.11)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
escape_utils (1.1.1)
|
escape_utils (1.1.1)
|
||||||
eventmachine (1.0.8)
|
eventmachine (1.0.8)
|
||||||
excon (0.45.4)
|
excon (0.49.0)
|
||||||
execjs (2.6.0)
|
execjs (2.6.0)
|
||||||
expression_parser (0.9.0)
|
expression_parser (0.9.0)
|
||||||
factory_girl (4.5.0)
|
factory_girl (4.5.0)
|
||||||
|
@ -202,8 +207,6 @@ GEM
|
||||||
multi_json
|
multi_json
|
||||||
ffaker (2.0.0)
|
ffaker (2.0.0)
|
||||||
ffi (1.9.10)
|
ffi (1.9.10)
|
||||||
fission (0.5.0)
|
|
||||||
CFPropertyList (~> 2.2)
|
|
||||||
flay (2.6.1)
|
flay (2.6.1)
|
||||||
ruby_parser (~> 3.0)
|
ruby_parser (~> 3.0)
|
||||||
sexp_processor (~> 4.0)
|
sexp_processor (~> 4.0)
|
||||||
|
@ -213,109 +216,33 @@ GEM
|
||||||
flowdock (0.7.1)
|
flowdock (0.7.1)
|
||||||
httparty (~> 0.7)
|
httparty (~> 0.7)
|
||||||
multi_json
|
multi_json
|
||||||
fog (1.36.0)
|
fog-aws (0.9.2)
|
||||||
fog-aliyun (>= 0.1.0)
|
|
||||||
fog-atmos
|
|
||||||
fog-aws (>= 0.6.0)
|
|
||||||
fog-brightbox (~> 0.4)
|
|
||||||
fog-core (~> 1.32)
|
|
||||||
fog-dynect (~> 0.0.2)
|
|
||||||
fog-ecloud (~> 0.1)
|
|
||||||
fog-google (<= 0.1.0)
|
|
||||||
fog-json
|
|
||||||
fog-local
|
|
||||||
fog-powerdns (>= 0.1.1)
|
|
||||||
fog-profitbricks
|
|
||||||
fog-radosgw (>= 0.0.2)
|
|
||||||
fog-riakcs
|
|
||||||
fog-sakuracloud (>= 0.0.4)
|
|
||||||
fog-serverlove
|
|
||||||
fog-softlayer
|
|
||||||
fog-storm_on_demand
|
|
||||||
fog-terremark
|
|
||||||
fog-vmfusion
|
|
||||||
fog-voxel
|
|
||||||
fog-xenserver
|
|
||||||
fog-xml (~> 0.1.1)
|
|
||||||
ipaddress (~> 0.5)
|
|
||||||
nokogiri (~> 1.5, >= 1.5.11)
|
|
||||||
fog-aliyun (0.1.0)
|
|
||||||
fog-core (~> 1.27)
|
|
||||||
fog-json (~> 1.0)
|
|
||||||
ipaddress (~> 0.8)
|
|
||||||
xml-simple (~> 1.1)
|
|
||||||
fog-atmos (0.1.0)
|
|
||||||
fog-core
|
|
||||||
fog-xml
|
|
||||||
fog-aws (0.8.1)
|
|
||||||
fog-core (~> 1.27)
|
fog-core (~> 1.27)
|
||||||
fog-json (~> 1.0)
|
fog-json (~> 1.0)
|
||||||
fog-xml (~> 0.1)
|
fog-xml (~> 0.1)
|
||||||
ipaddress (~> 0.8)
|
ipaddress (~> 0.8)
|
||||||
fog-brightbox (0.10.1)
|
fog-azure (0.0.2)
|
||||||
fog-core (~> 1.22)
|
azure (~> 0.6)
|
||||||
fog-json
|
fog-core (~> 1.27)
|
||||||
inflecto (~> 0.0.2)
|
fog-json (~> 1.0)
|
||||||
fog-core (1.35.0)
|
fog-xml (~> 0.1)
|
||||||
|
fog-core (1.40.0)
|
||||||
builder
|
builder
|
||||||
excon (~> 0.45)
|
excon (~> 0.49)
|
||||||
formatador (~> 0.2)
|
formatador (~> 0.2)
|
||||||
fog-dynect (0.0.2)
|
fog-google (0.3.2)
|
||||||
fog-core
|
|
||||||
fog-json
|
|
||||||
fog-xml
|
|
||||||
fog-ecloud (0.3.0)
|
|
||||||
fog-core
|
|
||||||
fog-xml
|
|
||||||
fog-google (0.1.0)
|
|
||||||
fog-core
|
fog-core
|
||||||
fog-json
|
fog-json
|
||||||
fog-xml
|
fog-xml
|
||||||
fog-json (1.0.2)
|
fog-json (1.0.2)
|
||||||
fog-core (~> 1.0)
|
fog-core (~> 1.0)
|
||||||
multi_json (~> 1.10)
|
multi_json (~> 1.10)
|
||||||
fog-local (0.2.1)
|
fog-local (0.3.0)
|
||||||
fog-core (~> 1.27)
|
fog-core (~> 1.27)
|
||||||
fog-powerdns (0.1.1)
|
fog-openstack (0.1.6)
|
||||||
fog-core (~> 1.27)
|
fog-core (>= 1.39)
|
||||||
fog-json (~> 1.0)
|
fog-json (>= 1.0)
|
||||||
fog-xml (~> 0.1)
|
ipaddress (>= 0.8)
|
||||||
fog-profitbricks (0.0.5)
|
|
||||||
fog-core
|
|
||||||
fog-xml
|
|
||||||
nokogiri
|
|
||||||
fog-radosgw (0.0.5)
|
|
||||||
fog-core (>= 1.21.0)
|
|
||||||
fog-json
|
|
||||||
fog-xml (>= 0.0.1)
|
|
||||||
fog-riakcs (0.1.0)
|
|
||||||
fog-core
|
|
||||||
fog-json
|
|
||||||
fog-xml
|
|
||||||
fog-sakuracloud (1.7.5)
|
|
||||||
fog-core
|
|
||||||
fog-json
|
|
||||||
fog-serverlove (0.1.2)
|
|
||||||
fog-core
|
|
||||||
fog-json
|
|
||||||
fog-softlayer (1.0.3)
|
|
||||||
fog-core
|
|
||||||
fog-json
|
|
||||||
fog-storm_on_demand (0.1.1)
|
|
||||||
fog-core
|
|
||||||
fog-json
|
|
||||||
fog-terremark (0.1.0)
|
|
||||||
fog-core
|
|
||||||
fog-xml
|
|
||||||
fog-vmfusion (0.1.0)
|
|
||||||
fission
|
|
||||||
fog-core
|
|
||||||
fog-voxel (0.1.0)
|
|
||||||
fog-core
|
|
||||||
fog-xml
|
|
||||||
fog-xenserver (0.2.2)
|
|
||||||
fog-core
|
|
||||||
fog-xml
|
|
||||||
fog-xml (0.1.2)
|
fog-xml (0.1.2)
|
||||||
fog-core
|
fog-core
|
||||||
nokogiri (~> 1.5, >= 1.5.11)
|
nokogiri (~> 1.5, >= 1.5.11)
|
||||||
|
@ -350,7 +277,7 @@ GEM
|
||||||
posix-spawn (~> 0.3)
|
posix-spawn (~> 0.3)
|
||||||
gitlab_emoji (0.3.1)
|
gitlab_emoji (0.3.1)
|
||||||
gemojione (~> 2.2, >= 2.2.1)
|
gemojione (~> 2.2, >= 2.2.1)
|
||||||
gitlab_git (10.1.0)
|
gitlab_git (10.1.3)
|
||||||
activesupport (~> 4.0)
|
activesupport (~> 4.0)
|
||||||
charlock_holmes (~> 0.7.3)
|
charlock_holmes (~> 0.7.3)
|
||||||
github-linguist (~> 4.7.0)
|
github-linguist (~> 4.7.0)
|
||||||
|
@ -404,7 +331,6 @@ GEM
|
||||||
hashie (3.4.3)
|
hashie (3.4.3)
|
||||||
health_check (1.5.1)
|
health_check (1.5.1)
|
||||||
rails (>= 2.3.0)
|
rails (>= 2.3.0)
|
||||||
highline (1.7.8)
|
|
||||||
hipchat (1.5.2)
|
hipchat (1.5.2)
|
||||||
httparty
|
httparty
|
||||||
mimemagic
|
mimemagic
|
||||||
|
@ -424,11 +350,10 @@ GEM
|
||||||
httpclient (2.7.0.1)
|
httpclient (2.7.0.1)
|
||||||
i18n (0.7.0)
|
i18n (0.7.0)
|
||||||
ice_nine (0.11.1)
|
ice_nine (0.11.1)
|
||||||
inflecto (0.0.2)
|
|
||||||
influxdb (0.2.3)
|
influxdb (0.2.3)
|
||||||
cause
|
cause
|
||||||
json
|
json
|
||||||
ipaddress (0.8.2)
|
ipaddress (0.8.3)
|
||||||
jquery-atwho-rails (1.3.2)
|
jquery-atwho-rails (1.3.2)
|
||||||
jquery-rails (4.1.1)
|
jquery-rails (4.1.1)
|
||||||
rails-dom-testing (>= 1, < 3)
|
rails-dom-testing (>= 1, < 3)
|
||||||
|
@ -441,10 +366,13 @@ GEM
|
||||||
railties (>= 3.2.16)
|
railties (>= 3.2.16)
|
||||||
json (1.8.3)
|
json (1.8.3)
|
||||||
jwt (1.5.2)
|
jwt (1.5.2)
|
||||||
kaminari (0.16.3)
|
kaminari (0.17.0)
|
||||||
actionpack (>= 3.0.0)
|
actionpack (>= 3.0.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
kgio (2.10.0)
|
kgio (2.10.0)
|
||||||
|
knapsack (1.11.0)
|
||||||
|
rake
|
||||||
|
timecop (>= 0.1.0)
|
||||||
launchy (2.4.3)
|
launchy (2.4.3)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
letter_opener (1.4.1)
|
letter_opener (1.4.1)
|
||||||
|
@ -453,6 +381,12 @@ GEM
|
||||||
actionmailer (>= 3.2)
|
actionmailer (>= 3.2)
|
||||||
letter_opener (~> 1.0)
|
letter_opener (~> 1.0)
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
|
license_finder (2.1.0)
|
||||||
|
bundler
|
||||||
|
httparty
|
||||||
|
rubyzip
|
||||||
|
thor
|
||||||
|
xml-simple
|
||||||
licensee (8.0.0)
|
licensee (8.0.0)
|
||||||
rugged (>= 0.24b)
|
rugged (>= 0.24b)
|
||||||
listen (3.0.5)
|
listen (3.0.5)
|
||||||
|
@ -466,9 +400,9 @@ GEM
|
||||||
mime-types (>= 1.16, < 4)
|
mime-types (>= 1.16, < 4)
|
||||||
mail_room (0.7.0)
|
mail_room (0.7.0)
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (2.99.1)
|
mime-types (2.99.2)
|
||||||
mimemagic (0.3.0)
|
mimemagic (0.3.0)
|
||||||
mini_portile2 (2.0.0)
|
mini_portile2 (2.1.0)
|
||||||
minitest (5.7.0)
|
minitest (5.7.0)
|
||||||
mousetrap-rails (1.4.6)
|
mousetrap-rails (1.4.6)
|
||||||
multi_json (1.11.2)
|
multi_json (1.11.2)
|
||||||
|
@ -479,8 +413,10 @@ GEM
|
||||||
net-ldap (0.12.1)
|
net-ldap (0.12.1)
|
||||||
net-ssh (3.0.1)
|
net-ssh (3.0.1)
|
||||||
newrelic_rpm (3.14.1.311)
|
newrelic_rpm (3.14.1.311)
|
||||||
nokogiri (1.6.7.2)
|
nokogiri (1.6.8)
|
||||||
mini_portile2 (~> 2.0.0.rc2)
|
mini_portile2 (~> 2.1.0)
|
||||||
|
pkg-config (~> 1.1.7)
|
||||||
|
numerizer (0.1.1)
|
||||||
oauth (0.4.7)
|
oauth (0.4.7)
|
||||||
oauth2 (1.0.0)
|
oauth2 (1.0.0)
|
||||||
faraday (>= 0.8, < 0.10)
|
faraday (>= 0.8, < 0.10)
|
||||||
|
@ -549,9 +485,10 @@ GEM
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
paranoia (2.1.4)
|
paranoia (2.1.4)
|
||||||
activerecord (~> 4.0)
|
activerecord (~> 4.0)
|
||||||
parser (2.3.0.6)
|
parser (2.3.1.0)
|
||||||
ast (~> 2.2)
|
ast (~> 2.2)
|
||||||
pg (0.18.4)
|
pg (0.18.4)
|
||||||
|
pkg-config (1.1.7)
|
||||||
poltergeist (1.9.0)
|
poltergeist (1.9.0)
|
||||||
capybara (~> 2.1)
|
capybara (~> 2.1)
|
||||||
cliver (~> 0.3.1)
|
cliver (~> 0.3.1)
|
||||||
|
@ -627,7 +564,7 @@ GEM
|
||||||
debugger-ruby_core_source (~> 1.3)
|
debugger-ruby_core_source (~> 1.3)
|
||||||
rdoc (3.12.2)
|
rdoc (3.12.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
recaptcha (1.0.2)
|
recaptcha (3.0.0)
|
||||||
json
|
json
|
||||||
redcarpet (3.3.3)
|
redcarpet (3.3.3)
|
||||||
redis (3.3.0)
|
redis (3.3.0)
|
||||||
|
@ -655,8 +592,8 @@ GEM
|
||||||
responders (2.1.1)
|
responders (2.1.1)
|
||||||
railties (>= 4.2.0, < 5.1)
|
railties (>= 4.2.0, < 5.1)
|
||||||
rinku (1.7.3)
|
rinku (1.7.3)
|
||||||
rotp (2.1.1)
|
rotp (2.1.2)
|
||||||
rouge (1.10.1)
|
rouge (1.11.0)
|
||||||
rqrcode (0.7.0)
|
rqrcode (0.7.0)
|
||||||
chunky_png
|
chunky_png
|
||||||
rqrcode-rails3 (0.1.7)
|
rqrcode-rails3 (0.1.7)
|
||||||
|
@ -684,31 +621,31 @@ GEM
|
||||||
rspec-retry (0.4.5)
|
rspec-retry (0.4.5)
|
||||||
rspec-core
|
rspec-core
|
||||||
rspec-support (3.4.1)
|
rspec-support (3.4.1)
|
||||||
rubocop (0.38.0)
|
rubocop (0.40.0)
|
||||||
parser (>= 2.3.0.6, < 3.0)
|
parser (>= 2.3.1.0, < 3.0)
|
||||||
powerpack (~> 0.1)
|
powerpack (~> 0.1)
|
||||||
rainbow (>= 1.99.1, < 3.0)
|
rainbow (>= 1.99.1, < 3.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||||
|
rubocop-rspec (1.5.0)
|
||||||
|
rubocop (>= 0.40.0)
|
||||||
ruby-fogbugz (0.2.1)
|
ruby-fogbugz (0.2.1)
|
||||||
crack (~> 0.4)
|
crack (~> 0.4)
|
||||||
ruby-progressbar (1.7.5)
|
ruby-progressbar (1.8.1)
|
||||||
ruby-saml (1.1.2)
|
ruby-saml (1.1.2)
|
||||||
nokogiri (>= 1.5.10)
|
nokogiri (>= 1.5.10)
|
||||||
uuid (~> 2.3)
|
uuid (~> 2.3)
|
||||||
ruby2ruby (2.3.0)
|
ruby_parser (3.8.2)
|
||||||
ruby_parser (~> 3.1)
|
|
||||||
sexp_processor (~> 4.0)
|
|
||||||
ruby_parser (3.8.1)
|
|
||||||
sexp_processor (~> 4.1)
|
sexp_processor (~> 4.1)
|
||||||
rubyntlm (0.5.2)
|
rubyntlm (0.5.2)
|
||||||
rubypants (0.2.0)
|
rubypants (0.2.0)
|
||||||
|
rubyzip (1.2.0)
|
||||||
rufus-scheduler (3.1.10)
|
rufus-scheduler (3.1.10)
|
||||||
rugged (0.24.0)
|
rugged (0.24.0)
|
||||||
safe_yaml (1.0.4)
|
safe_yaml (1.0.4)
|
||||||
sanitize (2.1.0)
|
sanitize (2.1.0)
|
||||||
nokogiri (>= 1.4.4)
|
nokogiri (>= 1.4.4)
|
||||||
sass (3.4.21)
|
sass (3.4.22)
|
||||||
sass-rails (5.0.4)
|
sass-rails (5.0.4)
|
||||||
railties (>= 4.0.0, < 5.0)
|
railties (>= 4.0.0, < 5.0)
|
||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
|
@ -757,9 +694,6 @@ GEM
|
||||||
tilt (>= 1.3, < 3)
|
tilt (>= 1.3, < 3)
|
||||||
six (0.2.0)
|
six (0.2.0)
|
||||||
slack-notifier (1.2.1)
|
slack-notifier (1.2.1)
|
||||||
slim (3.0.6)
|
|
||||||
temple (~> 0.7.3)
|
|
||||||
tilt (>= 1.3.3, < 2.1)
|
|
||||||
slop (3.6.0)
|
slop (3.6.0)
|
||||||
spinach (0.8.10)
|
spinach (0.8.10)
|
||||||
colorize
|
colorize
|
||||||
|
@ -786,11 +720,11 @@ GEM
|
||||||
activesupport (>= 4.0)
|
activesupport (>= 4.0)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
state_machines (0.4.0)
|
state_machines (0.4.0)
|
||||||
state_machines-activemodel (0.3.0)
|
state_machines-activemodel (0.4.0)
|
||||||
activemodel (~> 4.1)
|
activemodel (>= 4.1, < 5.1)
|
||||||
state_machines (>= 0.4.0)
|
state_machines (>= 0.4.0)
|
||||||
state_machines-activerecord (0.3.0)
|
state_machines-activerecord (0.4.0)
|
||||||
activerecord (~> 4.1)
|
activerecord (>= 4.1, < 5.1)
|
||||||
state_machines-activemodel (>= 0.3.0)
|
state_machines-activemodel (>= 0.3.0)
|
||||||
stringex (2.5.2)
|
stringex (2.5.2)
|
||||||
systemu (2.6.5)
|
systemu (2.6.5)
|
||||||
|
@ -800,10 +734,8 @@ GEM
|
||||||
railties (>= 3.2.5, < 6)
|
railties (>= 3.2.5, < 6)
|
||||||
teaspoon-jasmine (2.2.0)
|
teaspoon-jasmine (2.2.0)
|
||||||
teaspoon (>= 1.0.0)
|
teaspoon (>= 1.0.0)
|
||||||
temple (0.7.6)
|
|
||||||
term-ansicolor (1.3.2)
|
term-ansicolor (1.3.2)
|
||||||
tins (~> 1.0)
|
tins (~> 1.0)
|
||||||
terminal-table (1.5.2)
|
|
||||||
test_after_commit (0.4.2)
|
test_after_commit (0.4.2)
|
||||||
activerecord (>= 3.2)
|
activerecord (>= 3.2)
|
||||||
thin (1.6.4)
|
thin (1.6.4)
|
||||||
|
@ -812,7 +744,8 @@ GEM
|
||||||
rack (~> 1.0)
|
rack (~> 1.0)
|
||||||
thor (0.19.1)
|
thor (0.19.1)
|
||||||
thread_safe (0.3.5)
|
thread_safe (0.3.5)
|
||||||
tilt (2.0.2)
|
tilt (2.0.5)
|
||||||
|
timecop (0.8.1)
|
||||||
timfel-krb5-auth (0.8.3)
|
timfel-krb5-auth (0.8.3)
|
||||||
tinder (1.10.1)
|
tinder (1.10.1)
|
||||||
eventmachine (~> 1.0)
|
eventmachine (~> 1.0)
|
||||||
|
@ -832,6 +765,7 @@ GEM
|
||||||
simple_oauth (~> 0.1.4)
|
simple_oauth (~> 0.1.4)
|
||||||
tzinfo (1.2.2)
|
tzinfo (1.2.2)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
|
u2f (0.2.1)
|
||||||
uglifier (2.7.2)
|
uglifier (2.7.2)
|
||||||
execjs (>= 0.3.0)
|
execjs (>= 0.3.0)
|
||||||
json (>= 1.8.0)
|
json (>= 1.8.0)
|
||||||
|
@ -839,7 +773,7 @@ GEM
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
unf_ext (0.0.7.2)
|
unf_ext (0.0.7.2)
|
||||||
unicode-display_width (1.0.2)
|
unicode-display_width (1.0.5)
|
||||||
unicorn (4.9.0)
|
unicorn (4.9.0)
|
||||||
kgio (~> 2.6)
|
kgio (~> 2.6)
|
||||||
rack
|
rack
|
||||||
|
@ -856,7 +790,7 @@ GEM
|
||||||
coercible (~> 1.0)
|
coercible (~> 1.0)
|
||||||
descendants_tracker (~> 0.0, >= 0.0.3)
|
descendants_tracker (~> 0.0, >= 0.0.3)
|
||||||
equalizer (~> 0.0, >= 0.0.9)
|
equalizer (~> 0.0, >= 0.0.9)
|
||||||
warden (1.2.4)
|
warden (1.2.6)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
web-console (2.3.0)
|
web-console (2.3.0)
|
||||||
activemodel (>= 4.0)
|
activemodel (>= 4.0)
|
||||||
|
@ -883,7 +817,7 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
RedCloth (~> 4.2.9)
|
RedCloth (~> 4.2.9)
|
||||||
ace-rails-ap (~> 4.0.2)
|
ace-rails-ap (~> 4.0.2)
|
||||||
activerecord-session_store (~> 0.1.0)
|
activerecord-session_store (~> 1.0.0)
|
||||||
acts-as-taggable-on (~> 3.4)
|
acts-as-taggable-on (~> 3.4)
|
||||||
addressable (~> 2.3.8)
|
addressable (~> 2.3.8)
|
||||||
after_commit_queue
|
after_commit_queue
|
||||||
|
@ -891,7 +825,7 @@ DEPENDENCIES
|
||||||
allocations (~> 1.0)
|
allocations (~> 1.0)
|
||||||
asana (~> 0.4.0)
|
asana (~> 0.4.0)
|
||||||
asciidoctor (~> 1.5.2)
|
asciidoctor (~> 1.5.2)
|
||||||
attr_encrypted (~> 1.3.4)
|
attr_encrypted (~> 3.0.0)
|
||||||
awesome_print (~> 1.2.0)
|
awesome_print (~> 1.2.0)
|
||||||
babosa (~> 1.0.2)
|
babosa (~> 1.0.2)
|
||||||
base32 (~> 0.3.0)
|
base32 (~> 0.3.0)
|
||||||
|
@ -899,27 +833,25 @@ DEPENDENCIES
|
||||||
better_errors (~> 1.0.1)
|
better_errors (~> 1.0.1)
|
||||||
binding_of_caller (~> 0.7.2)
|
binding_of_caller (~> 0.7.2)
|
||||||
bootstrap-sass (~> 3.3.0)
|
bootstrap-sass (~> 3.3.0)
|
||||||
brakeman (~> 3.2.0)
|
brakeman (~> 3.3.0)
|
||||||
browser (~> 1.0.0)
|
browser (~> 2.0.3)
|
||||||
bullet
|
bullet
|
||||||
bundler-audit
|
bundler-audit
|
||||||
byebug
|
byebug
|
||||||
cal-heatmap-rails (~> 3.6.0)
|
|
||||||
capybara (~> 2.6.2)
|
capybara (~> 2.6.2)
|
||||||
capybara-screenshot (~> 1.0.0)
|
capybara-screenshot (~> 1.0.0)
|
||||||
carrierwave (~> 0.10.0)
|
carrierwave (~> 0.10.0)
|
||||||
charlock_holmes (~> 0.7.3)
|
charlock_holmes (~> 0.7.3)
|
||||||
|
chronic_duration (~> 0.10.6)
|
||||||
coffee-rails (~> 4.1.0)
|
coffee-rails (~> 4.1.0)
|
||||||
colorize (~> 0.7.0)
|
|
||||||
connection_pool (~> 2.0)
|
connection_pool (~> 2.0)
|
||||||
coveralls (~> 0.8.2)
|
coveralls (~> 0.8.2)
|
||||||
creole (~> 0.5.0)
|
creole (~> 0.5.0)
|
||||||
d3_rails (~> 3.5.0)
|
d3_rails (~> 3.5.0)
|
||||||
database_cleaner (~> 1.4.0)
|
database_cleaner (~> 1.4.0)
|
||||||
default_value_for (~> 3.0.0)
|
default_value_for (~> 3.0.0)
|
||||||
devise (~> 3.5.4)
|
devise (~> 4.0)
|
||||||
devise-async (~> 0.9.0)
|
devise-two-factor (~> 3.0.0)
|
||||||
devise-two-factor (~> 2.0.0)
|
|
||||||
diffy (~> 3.0.3)
|
diffy (~> 3.0.3)
|
||||||
doorkeeper (~> 3.1)
|
doorkeeper (~> 3.1)
|
||||||
dropzonejs-rails (~> 0.7.1)
|
dropzonejs-rails (~> 0.7.1)
|
||||||
|
@ -929,7 +861,12 @@ DEPENDENCIES
|
||||||
ffaker (~> 2.0.0)
|
ffaker (~> 2.0.0)
|
||||||
flay
|
flay
|
||||||
flog
|
flog
|
||||||
fog (~> 1.36.0)
|
fog-aws (~> 0.9)
|
||||||
|
fog-azure (~> 0.0)
|
||||||
|
fog-core (~> 1.40)
|
||||||
|
fog-google (~> 0.3)
|
||||||
|
fog-local (~> 0.3)
|
||||||
|
fog-openstack (~> 0.1)
|
||||||
font-awesome-rails (~> 4.2)
|
font-awesome-rails (~> 4.2)
|
||||||
foreman
|
foreman
|
||||||
fuubar (~> 2.0.0)
|
fuubar (~> 2.0.0)
|
||||||
|
@ -957,8 +894,10 @@ DEPENDENCIES
|
||||||
jquery-turbolinks (~> 2.1.0)
|
jquery-turbolinks (~> 2.1.0)
|
||||||
jquery-ui-rails (~> 5.0.0)
|
jquery-ui-rails (~> 5.0.0)
|
||||||
jwt
|
jwt
|
||||||
kaminari (~> 0.16.3)
|
kaminari (~> 0.17.0)
|
||||||
|
knapsack
|
||||||
letter_opener_web (~> 1.3.0)
|
letter_opener_web (~> 1.3.0)
|
||||||
|
license_finder
|
||||||
licensee (~> 8.0.0)
|
licensee (~> 8.0.0)
|
||||||
loofah (~> 2.0.3)
|
loofah (~> 2.0.3)
|
||||||
mail_room (~> 0.7)
|
mail_room (~> 0.7)
|
||||||
|
@ -998,10 +937,11 @@ DEPENDENCIES
|
||||||
rack-oauth2 (~> 1.2.1)
|
rack-oauth2 (~> 1.2.1)
|
||||||
rails (= 4.2.6)
|
rails (= 4.2.6)
|
||||||
rails-deprecated_sanitizer (~> 1.0.3)
|
rails-deprecated_sanitizer (~> 1.0.3)
|
||||||
|
rainbow (~> 2.1.0)
|
||||||
raphael-rails (~> 2.1.2)
|
raphael-rails (~> 2.1.2)
|
||||||
rblineprof
|
rblineprof
|
||||||
rdoc (~> 3.6)
|
rdoc (~> 3.6)
|
||||||
recaptcha
|
recaptcha (~> 3.0)
|
||||||
redcarpet (~> 3.3.3)
|
redcarpet (~> 3.3.3)
|
||||||
redis (~> 3.2)
|
redis (~> 3.2)
|
||||||
redis-namespace
|
redis-namespace
|
||||||
|
@ -1009,11 +949,12 @@ DEPENDENCIES
|
||||||
request_store (~> 1.3.0)
|
request_store (~> 1.3.0)
|
||||||
rerun (~> 0.11.0)
|
rerun (~> 0.11.0)
|
||||||
responders (~> 2.0)
|
responders (~> 2.0)
|
||||||
rouge (~> 1.10.1)
|
rouge (~> 1.11)
|
||||||
rqrcode-rails3 (~> 0.1.7)
|
rqrcode-rails3 (~> 0.1.7)
|
||||||
rspec-rails (~> 3.4.0)
|
rspec-rails (~> 3.4.0)
|
||||||
rspec-retry
|
rspec-retry
|
||||||
rubocop (~> 0.38.0)
|
rubocop (~> 0.40.0)
|
||||||
|
rubocop-rspec (~> 1.5.0)
|
||||||
ruby-fogbugz (~> 0.2.1)
|
ruby-fogbugz (~> 0.2.1)
|
||||||
sanitize (~> 2.0)
|
sanitize (~> 2.0)
|
||||||
sass-rails (~> 5.0.0)
|
sass-rails (~> 5.0.0)
|
||||||
|
@ -1038,7 +979,7 @@ DEPENDENCIES
|
||||||
spring-commands-spinach (~> 1.1.0)
|
spring-commands-spinach (~> 1.1.0)
|
||||||
spring-commands-teaspoon (~> 0.0.2)
|
spring-commands-teaspoon (~> 0.0.2)
|
||||||
sprockets (~> 3.6.0)
|
sprockets (~> 3.6.0)
|
||||||
state_machines-activerecord (~> 0.3.0)
|
state_machines-activerecord (~> 0.4.0)
|
||||||
task_list (~> 1.0.2)
|
task_list (~> 1.0.2)
|
||||||
teaspoon (~> 1.1.0)
|
teaspoon (~> 1.1.0)
|
||||||
teaspoon-jasmine (~> 2.2.0)
|
teaspoon-jasmine (~> 2.2.0)
|
||||||
|
@ -1046,6 +987,7 @@ DEPENDENCIES
|
||||||
thin (~> 1.6.1)
|
thin (~> 1.6.1)
|
||||||
tinder (~> 1.10.0)
|
tinder (~> 1.10.0)
|
||||||
turbolinks (~> 2.5.0)
|
turbolinks (~> 2.5.0)
|
||||||
|
u2f (~> 0.2.1)
|
||||||
uglifier (~> 2.7.2)
|
uglifier (~> 2.7.2)
|
||||||
underscore-rails (~> 1.8.0)
|
underscore-rails (~> 1.8.0)
|
||||||
unf (~> 0.1.4)
|
unf (~> 0.1.4)
|
||||||
|
@ -1058,4 +1000,4 @@ DEPENDENCIES
|
||||||
wikicloth (= 0.8.1)
|
wikicloth (= 0.8.1)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.12.3
|
1.12.5
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
# GitLab
|
# GitLab
|
||||||
|
|
||||||
[![build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
|
[![build status](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/build.svg)](https://gitlab.com/gitlab-org/gitlab-ce/commits/master)
|
||||||
[![Build Status](https://semaphoreci.com/api/v1/projects/2f1a5809-418b-4cc2-a1f4-819607579fe7/400484/shields_badge.svg)](https://semaphoreci.com/gitlabhq/gitlabhq)
|
|
||||||
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
|
[![Code Climate](https://codeclimate.com/github/gitlabhq/gitlabhq.svg)](https://codeclimate.com/github/gitlabhq/gitlabhq)
|
||||||
[![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.svg?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq?branch=master)
|
|
||||||
|
|
||||||
## Canonical source
|
## Canonical source
|
||||||
|
|
||||||
|
|
2
Rakefile
2
Rakefile
|
@ -8,3 +8,5 @@ relative_url_conf = File.expand_path('../config/initializers/relative_url', __FI
|
||||||
require relative_url_conf if File.exist?("#{relative_url_conf}.rb")
|
require relative_url_conf if File.exist?("#{relative_url_conf}.rb")
|
||||||
|
|
||||||
Gitlab::Application.load_tasks
|
Gitlab::Application.load_tasks
|
||||||
|
|
||||||
|
Knapsack.load_tasks if defined?(Knapsack)
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
8.8.2
|
8.9.0-rc4
|
||||||
|
|
BIN
app/assets/images/mailers/gitlab_header_logo.png
Normal file
BIN
app/assets/images/mailers/gitlab_header_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.9 KiB |
BIN
app/assets/images/mailers/gitlab_tanuki_2x.png
Normal file
BIN
app/assets/images/mailers/gitlab_tanuki_2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
84
app/assets/javascripts/LabelManager.js.coffee
Normal file
84
app/assets/javascripts/LabelManager.js.coffee
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
class @LabelManager
|
||||||
|
errorMessage: 'Unable to update label prioritization at this time'
|
||||||
|
|
||||||
|
constructor: (opts = {}) ->
|
||||||
|
# Defaults
|
||||||
|
{
|
||||||
|
@togglePriorityButton = $('.js-toggle-priority')
|
||||||
|
@prioritizedLabels = $('.js-prioritized-labels')
|
||||||
|
@otherLabels = $('.js-other-labels')
|
||||||
|
} = opts
|
||||||
|
|
||||||
|
@prioritizedLabels.sortable(
|
||||||
|
items: 'li'
|
||||||
|
placeholder: 'list-placeholder'
|
||||||
|
axis: 'y'
|
||||||
|
update: @onPrioritySortUpdate.bind(@)
|
||||||
|
)
|
||||||
|
|
||||||
|
@bindEvents()
|
||||||
|
|
||||||
|
bindEvents: ->
|
||||||
|
@togglePriorityButton.on 'click', @, @onTogglePriorityClick
|
||||||
|
|
||||||
|
onTogglePriorityClick: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
_this = e.data
|
||||||
|
$btn = $(e.currentTarget)
|
||||||
|
$label = $("##{$btn.data('domId')}")
|
||||||
|
action = if $btn.parents('.js-prioritized-labels').length then 'remove' else 'add'
|
||||||
|
_this.toggleLabelPriority($label, action)
|
||||||
|
|
||||||
|
toggleLabelPriority: ($label, action, persistState = true) ->
|
||||||
|
_this = @
|
||||||
|
url = $label.find('.js-toggle-priority').data 'url'
|
||||||
|
|
||||||
|
$target = @prioritizedLabels
|
||||||
|
$from = @otherLabels
|
||||||
|
|
||||||
|
# Optimistic update
|
||||||
|
if action is 'remove'
|
||||||
|
$target = @otherLabels
|
||||||
|
$from = @prioritizedLabels
|
||||||
|
|
||||||
|
if $from.find('li').length is 1
|
||||||
|
$from.find('.empty-message').show()
|
||||||
|
|
||||||
|
if not $target.find('li').length
|
||||||
|
$target.find('.empty-message').hide()
|
||||||
|
|
||||||
|
$label.detach().appendTo($target)
|
||||||
|
|
||||||
|
# Return if we are not persisting state
|
||||||
|
return unless persistState
|
||||||
|
|
||||||
|
if action is 'remove'
|
||||||
|
xhr = $.ajax url: url, type: 'DELETE'
|
||||||
|
else
|
||||||
|
xhr = @savePrioritySort($label, action)
|
||||||
|
|
||||||
|
xhr.fail @rollbackLabelPosition.bind(@, $label, action)
|
||||||
|
|
||||||
|
onPrioritySortUpdate: ->
|
||||||
|
xhr = @savePrioritySort()
|
||||||
|
|
||||||
|
xhr.fail ->
|
||||||
|
new Flash(@errorMessage, 'alert')
|
||||||
|
|
||||||
|
savePrioritySort: () ->
|
||||||
|
$.post
|
||||||
|
url: @prioritizedLabels.data('url')
|
||||||
|
data:
|
||||||
|
label_ids: @getSortedLabelsIds()
|
||||||
|
|
||||||
|
rollbackLabelPosition: ($label, originalAction)->
|
||||||
|
action = if originalAction is 'remove' then 'add' else 'remove'
|
||||||
|
@toggleLabelPriority($label, action, false)
|
||||||
|
|
||||||
|
new Flash(@errorMessage, 'alert')
|
||||||
|
|
||||||
|
getSortedLabelsIds: ->
|
||||||
|
sortedIds = []
|
||||||
|
@prioritizedLabels.find('li').each ->
|
||||||
|
sortedIds.push $(@).data 'id'
|
||||||
|
sortedIds
|
|
@ -1,11 +1,14 @@
|
||||||
class @Activities
|
class @Activities
|
||||||
constructor: ->
|
constructor: ->
|
||||||
Pager.init 20, true
|
Pager.init 20, true, false, @updateTooltips
|
||||||
$(".event-filter-link").on "click", (event) =>
|
$(".event-filter-link").on "click", (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@toggleFilter($(event.currentTarget))
|
@toggleFilter($(event.currentTarget))
|
||||||
@reloadActivities()
|
@reloadActivities()
|
||||||
|
|
||||||
|
updateTooltips: ->
|
||||||
|
gl.utils.localTimeAgo($('.js-timeago', '#activity'))
|
||||||
|
|
||||||
reloadActivities: ->
|
reloadActivities: ->
|
||||||
$(".content_list").html ''
|
$(".content_list").html ''
|
||||||
Pager.init 20, true
|
Pager.init 20, true
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||||
# the compiled file.
|
# the compiled file.
|
||||||
#
|
#
|
||||||
#= require jquery
|
#= require jquery2
|
||||||
#= require jquery-ui/autocomplete
|
#= require jquery-ui/autocomplete
|
||||||
#= require jquery-ui/datepicker
|
#= require jquery-ui/datepicker
|
||||||
#= require jquery-ui/draggable
|
#= require jquery-ui/draggable
|
||||||
|
@ -18,8 +18,6 @@
|
||||||
#= require jquery.atwho
|
#= require jquery.atwho
|
||||||
#= require jquery.scrollTo
|
#= require jquery.scrollTo
|
||||||
#= require jquery.turbolinks
|
#= require jquery.turbolinks
|
||||||
#= require d3
|
|
||||||
#= require cal-heatmap
|
|
||||||
#= require turbolinks
|
#= require turbolinks
|
||||||
#= require autosave
|
#= require autosave
|
||||||
#= require bootstrap/affix
|
#= require bootstrap/affix
|
||||||
|
@ -37,7 +35,6 @@
|
||||||
#= require raphael
|
#= require raphael
|
||||||
#= require g.raphael
|
#= require g.raphael
|
||||||
#= require g.bar
|
#= require g.bar
|
||||||
#= require Chart
|
|
||||||
#= require branch-graph
|
#= require branch-graph
|
||||||
#= require ace/ace
|
#= require ace/ace
|
||||||
#= require ace/ext-searchbox
|
#= require ace/ext-searchbox
|
||||||
|
@ -52,9 +49,17 @@
|
||||||
#= require shortcuts_network
|
#= require shortcuts_network
|
||||||
#= require jquery.nicescroll
|
#= require jquery.nicescroll
|
||||||
#= require date.format
|
#= require date.format
|
||||||
#= require_tree .
|
#= require_directory ./behaviors
|
||||||
|
#= require_directory ./blob
|
||||||
|
#= require_directory ./ci
|
||||||
|
#= require_directory ./commit
|
||||||
|
#= require_directory ./extensions
|
||||||
|
#= require_directory ./lib
|
||||||
|
#= require_directory ./u2f
|
||||||
|
#= require_directory .
|
||||||
#= require fuzzaldrin-plus
|
#= require fuzzaldrin-plus
|
||||||
#= require cropper
|
#= require cropper
|
||||||
|
#= require u2f
|
||||||
|
|
||||||
window.slugify = (text) ->
|
window.slugify = (text) ->
|
||||||
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
|
text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase()
|
||||||
|
@ -120,6 +125,7 @@ window.onload = ->
|
||||||
setTimeout shiftWindow, 100
|
setTimeout shiftWindow, 100
|
||||||
|
|
||||||
$ ->
|
$ ->
|
||||||
|
gl.utils.preventDisabledButtons()
|
||||||
bootstrapBreakpoint = bp.getBreakpointSize()
|
bootstrapBreakpoint = bp.getBreakpointSize()
|
||||||
|
|
||||||
$(".nicescroll").niceScroll(cursoropacitymax: '0.4', cursorcolor: '#FFF', cursorborder: "1px solid #FFF")
|
$(".nicescroll").niceScroll(cursoropacitymax: '0.4', cursorcolor: '#FFF', cursorborder: "1px solid #FFF")
|
||||||
|
@ -157,19 +163,6 @@ $ ->
|
||||||
$el.data('placement') || 'bottom'
|
$el.data('placement') || 'bottom'
|
||||||
)
|
)
|
||||||
|
|
||||||
$('.header-logo .home').tooltip(
|
|
||||||
placement: (_, el) ->
|
|
||||||
$el = $(el)
|
|
||||||
if $('.page-with-sidebar').hasClass('page-sidebar-collapsed') then 'right' else 'bottom'
|
|
||||||
container: 'body'
|
|
||||||
)
|
|
||||||
|
|
||||||
$('.page-with-sidebar').tooltip(
|
|
||||||
selector: '.sidebar-collapsed .nav-sidebar a, .sidebar-collapsed a.sidebar-user'
|
|
||||||
placement: 'right'
|
|
||||||
container: 'body'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Form submitter
|
# Form submitter
|
||||||
$('.trigger-submit').on 'change', ->
|
$('.trigger-submit').on 'change', ->
|
||||||
$(@).parents('form').submit()
|
$(@).parents('form').submit()
|
||||||
|
@ -202,6 +195,7 @@ $ ->
|
||||||
|
|
||||||
$('.navbar-toggle').on 'click', ->
|
$('.navbar-toggle').on 'click', ->
|
||||||
$('.header-content .title').toggle()
|
$('.header-content .title').toggle()
|
||||||
|
$('.header-content .header-logo').toggle()
|
||||||
$('.header-content .navbar-collapse').toggle()
|
$('.header-content .navbar-collapse').toggle()
|
||||||
$('.navbar-toggle').toggleClass('active')
|
$('.navbar-toggle').toggleClass('active')
|
||||||
$('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left")
|
$('.navbar-toggle i').toggleClass("fa-angle-right fa-angle-left")
|
||||||
|
@ -220,6 +214,10 @@ $ ->
|
||||||
form = btn.closest("form")
|
form = btn.closest("form")
|
||||||
new ConfirmDangerModal(form, text)
|
new ConfirmDangerModal(form, text)
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on 'click', 'button', ->
|
||||||
|
$(this).blur()
|
||||||
|
|
||||||
$('input[type="search"]').each ->
|
$('input[type="search"]').each ->
|
||||||
$this = $(this)
|
$this = $(this)
|
||||||
$this.attr 'value', $this.val()
|
$this.attr 'value', $this.val()
|
||||||
|
@ -232,7 +230,6 @@ $ ->
|
||||||
$this.attr 'value', $this.val()
|
$this.attr 'value', $this.val()
|
||||||
|
|
||||||
$sidebarGutterToggle = $('.js-sidebar-toggle')
|
$sidebarGutterToggle = $('.js-sidebar-toggle')
|
||||||
$navIconToggle = $('.toggle-nav-collapse')
|
|
||||||
|
|
||||||
$(document)
|
$(document)
|
||||||
.off 'breakpoint:change'
|
.off 'breakpoint:change'
|
||||||
|
@ -242,42 +239,6 @@ $ ->
|
||||||
if $gutterIcon.hasClass('fa-angle-double-right')
|
if $gutterIcon.hasClass('fa-angle-double-right')
|
||||||
$sidebarGutterToggle.trigger('click')
|
$sidebarGutterToggle.trigger('click')
|
||||||
|
|
||||||
$navIcon = $navIconToggle.find('.fa')
|
|
||||||
if $navIcon.hasClass('fa-angle-left')
|
|
||||||
$navIconToggle.trigger('click')
|
|
||||||
|
|
||||||
$(document)
|
|
||||||
.off 'click', '.js-sidebar-toggle'
|
|
||||||
.on 'click', '.js-sidebar-toggle', (e, triggered) ->
|
|
||||||
e.preventDefault()
|
|
||||||
$this = $(this)
|
|
||||||
$thisIcon = $this.find 'i'
|
|
||||||
$allGutterToggleIcons = $('.js-sidebar-toggle i')
|
|
||||||
if $thisIcon.hasClass('fa-angle-double-right')
|
|
||||||
$allGutterToggleIcons
|
|
||||||
.removeClass('fa-angle-double-right')
|
|
||||||
.addClass('fa-angle-double-left')
|
|
||||||
$('aside.right-sidebar')
|
|
||||||
.removeClass('right-sidebar-expanded')
|
|
||||||
.addClass('right-sidebar-collapsed')
|
|
||||||
$('.page-with-sidebar')
|
|
||||||
.removeClass('right-sidebar-expanded')
|
|
||||||
.addClass('right-sidebar-collapsed')
|
|
||||||
else
|
|
||||||
$allGutterToggleIcons
|
|
||||||
.removeClass('fa-angle-double-left')
|
|
||||||
.addClass('fa-angle-double-right')
|
|
||||||
$('aside.right-sidebar')
|
|
||||||
.removeClass('right-sidebar-collapsed')
|
|
||||||
.addClass('right-sidebar-expanded')
|
|
||||||
$('.page-with-sidebar')
|
|
||||||
.removeClass('right-sidebar-collapsed')
|
|
||||||
.addClass('right-sidebar-expanded')
|
|
||||||
if not triggered
|
|
||||||
$.cookie("collapsed_gutter",
|
|
||||||
$('.right-sidebar')
|
|
||||||
.hasClass('right-sidebar-collapsed'), { path: '/' })
|
|
||||||
|
|
||||||
fitSidebarForSize = ->
|
fitSidebarForSize = ->
|
||||||
oldBootstrapBreakpoint = bootstrapBreakpoint
|
oldBootstrapBreakpoint = bootstrapBreakpoint
|
||||||
bootstrapBreakpoint = bp.getBreakpointSize()
|
bootstrapBreakpoint = bp.getBreakpointSize()
|
||||||
|
@ -290,9 +251,10 @@ $ ->
|
||||||
$(document).trigger('breakpoint:change', [bootstrapBreakpoint])
|
$(document).trigger('breakpoint:change', [bootstrapBreakpoint])
|
||||||
|
|
||||||
$(window)
|
$(window)
|
||||||
.off "resize"
|
.off "resize.app"
|
||||||
.on "resize", (e) ->
|
.on "resize.app", (e) ->
|
||||||
fitSidebarForSize()
|
fitSidebarForSize()
|
||||||
|
|
||||||
|
gl.awardsHandler = new AwardsHandler()
|
||||||
checkInitialSidebarSize()
|
checkInitialSidebarSize()
|
||||||
new Aside()
|
new Aside()
|
||||||
|
|
|
@ -1,201 +1,354 @@
|
||||||
class @AwardsHandler
|
class @AwardsHandler
|
||||||
constructor: (@getEmojisUrl, @postEmojiUrl, @noteableType, @noteableId, @unicodes) ->
|
|
||||||
$('.js-add-award').on 'click', (event) =>
|
|
||||||
event.stopPropagation()
|
|
||||||
event.preventDefault()
|
|
||||||
|
|
||||||
@showEmojiMenu()
|
constructor: ->
|
||||||
|
|
||||||
$('html').on 'click', (event) ->
|
@aliases = gl.emojiAliases()
|
||||||
if !$(event.target).closest('.emoji-menu').length
|
|
||||||
if $('.emoji-menu').is(':visible')
|
|
||||||
$('.emoji-menu').removeClass 'is-visible'
|
|
||||||
|
|
||||||
$('.awards')
|
$(document)
|
||||||
.off 'click'
|
.off 'click', '.js-add-award'
|
||||||
.on 'click', '.js-emoji-btn', @handleClick
|
.on 'click', '.js-add-award', (e) =>
|
||||||
|
e.stopPropagation()
|
||||||
@renderFrequentlyUsedBlock()
|
|
||||||
|
|
||||||
handleClick: (e) ->
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
emoji = $(this)
|
|
||||||
.find('.icon')
|
|
||||||
.data 'emoji'
|
|
||||||
|
|
||||||
if emoji is 'thumbsup' and awardsHandler.didUserClickEmoji $(this), 'thumbsdown'
|
@showEmojiMenu $(e.currentTarget)
|
||||||
awardsHandler.addAward 'thumbsdown'
|
|
||||||
|
|
||||||
else if emoji is 'thumbsdown' and awardsHandler.didUserClickEmoji $(this), 'thumbsup'
|
$('html').on 'click', (e) ->
|
||||||
awardsHandler.addAward 'thumbsup'
|
$target = $ e.target
|
||||||
|
|
||||||
awardsHandler.addAward emoji
|
unless $target.closest('.emoji-menu-content').length
|
||||||
|
$('.js-awards-block.current').removeClass 'current'
|
||||||
|
|
||||||
$(this).trigger 'blur'
|
unless $target.closest('.emoji-menu').length
|
||||||
|
if $('.emoji-menu').is(':visible')
|
||||||
didUserClickEmoji: (that, emoji) ->
|
$('.js-add-award.is-active').removeClass 'is-active'
|
||||||
if $(that).siblings("button:has([data-emoji=#{emoji}])").attr('data-original-title')
|
|
||||||
$(that).siblings("button:has([data-emoji=#{emoji}])").attr('data-original-title').indexOf('me') > -1
|
|
||||||
|
|
||||||
showEmojiMenu: ->
|
|
||||||
if $('.emoji-menu').length
|
|
||||||
if $('.emoji-menu').is '.is-visible'
|
|
||||||
$('.emoji-menu').removeClass 'is-visible'
|
$('.emoji-menu').removeClass 'is-visible'
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off 'click', '.js-emoji-btn'
|
||||||
|
.on 'click', '.js-emoji-btn', (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
$target = $ e.currentTarget
|
||||||
|
emoji = $target.find('.icon').data 'emoji'
|
||||||
|
|
||||||
|
$target.closest('.js-awards-block').addClass 'current'
|
||||||
|
@addAward @getVotesBlock(), @getAwardUrl(), emoji
|
||||||
|
|
||||||
|
|
||||||
|
showEmojiMenu: ($addBtn) ->
|
||||||
|
|
||||||
|
$menu = $ '.emoji-menu'
|
||||||
|
|
||||||
|
if $addBtn.hasClass 'js-note-emoji'
|
||||||
|
$addBtn.parents('.note').find('.js-awards-block').addClass 'current'
|
||||||
|
else
|
||||||
|
$addBtn.closest('.js-awards-block').addClass 'current'
|
||||||
|
|
||||||
|
if $menu.length
|
||||||
|
$holder = $addBtn.closest('.js-award-holder')
|
||||||
|
|
||||||
|
if $menu.is '.is-visible'
|
||||||
|
$addBtn.removeClass 'is-active'
|
||||||
|
$menu.removeClass 'is-visible'
|
||||||
$('#emoji_search').blur()
|
$('#emoji_search').blur()
|
||||||
else
|
else
|
||||||
$('.emoji-menu').addClass 'is-visible'
|
$addBtn.addClass 'is-active'
|
||||||
|
@positionMenu($menu, $addBtn)
|
||||||
|
|
||||||
|
$menu.addClass 'is-visible'
|
||||||
$('#emoji_search').focus()
|
$('#emoji_search').focus()
|
||||||
else
|
else
|
||||||
$('.js-add-award').addClass 'is-loading'
|
$addBtn.addClass 'is-loading is-active'
|
||||||
$.get @getEmojisUrl, (response) =>
|
url = @getAwardMenuUrl()
|
||||||
$('.js-add-award').removeClass 'is-loading'
|
|
||||||
$('.js-award-holder').append response
|
@createEmojiMenu url, =>
|
||||||
|
$addBtn.removeClass 'is-loading'
|
||||||
|
$menu = $('.emoji-menu')
|
||||||
|
@positionMenu($menu, $addBtn)
|
||||||
|
@renderFrequentlyUsedBlock() unless @frequentEmojiBlockRendered
|
||||||
|
|
||||||
setTimeout =>
|
setTimeout =>
|
||||||
$('.emoji-menu').addClass 'is-visible'
|
$menu.addClass 'is-visible'
|
||||||
$('#emoji_search').focus()
|
$('#emoji_search').focus()
|
||||||
@setupSearch()
|
@setupSearch()
|
||||||
, 200
|
, 200
|
||||||
|
|
||||||
addAward: (emoji) ->
|
|
||||||
@postEmoji emoji, =>
|
createEmojiMenu: (awardMenuUrl, callback) ->
|
||||||
@addAwardToEmojiBar(emoji)
|
|
||||||
|
$.get awardMenuUrl, (response) ->
|
||||||
|
$('body').append response
|
||||||
|
callback()
|
||||||
|
|
||||||
|
|
||||||
|
positionMenu: ($menu, $addBtn) ->
|
||||||
|
|
||||||
|
position = $addBtn.data('position')
|
||||||
|
|
||||||
|
# The menu could potentially be off-screen or in a hidden overflow element
|
||||||
|
# So we position the element absolute in the body
|
||||||
|
css =
|
||||||
|
top: "#{$addBtn.offset().top + $addBtn.outerHeight()}px"
|
||||||
|
|
||||||
|
if position? and position is 'right'
|
||||||
|
css.left = "#{($addBtn.offset().left - $menu.outerWidth()) + 20}px"
|
||||||
|
$menu.addClass 'is-aligned-right'
|
||||||
|
else
|
||||||
|
css.left = "#{$addBtn.offset().left}px"
|
||||||
|
$menu.removeClass 'is-aligned-right'
|
||||||
|
|
||||||
|
$menu.css(css)
|
||||||
|
|
||||||
|
|
||||||
|
addAward: (votesBlock, awardUrl, emoji, checkMutuality = true, callback) ->
|
||||||
|
|
||||||
|
emoji = @normilizeEmojiName emoji
|
||||||
|
|
||||||
|
@postEmoji awardUrl, emoji, =>
|
||||||
|
@addAwardToEmojiBar votesBlock, emoji, checkMutuality
|
||||||
|
callback?()
|
||||||
|
|
||||||
$('.emoji-menu').removeClass 'is-visible'
|
$('.emoji-menu').removeClass 'is-visible'
|
||||||
|
|
||||||
addAwardToEmojiBar: (emoji) ->
|
|
||||||
@addEmojiToFrequentlyUsedList(emoji)
|
|
||||||
|
|
||||||
if @exist(emoji)
|
addAwardToEmojiBar: (votesBlock, emoji, checkForMutuality = true) ->
|
||||||
if @isActive(emoji)
|
|
||||||
@decrementCounter(emoji)
|
@checkMutuality votesBlock, emoji if checkForMutuality
|
||||||
|
@addEmojiToFrequentlyUsedList emoji
|
||||||
|
|
||||||
|
emoji = @normilizeEmojiName emoji
|
||||||
|
$emojiButton = @findEmojiIcon(votesBlock, emoji).parent()
|
||||||
|
|
||||||
|
if $emojiButton.length > 0
|
||||||
|
if @isActive $emojiButton
|
||||||
|
@decrementCounter $emojiButton, emoji
|
||||||
else
|
else
|
||||||
counter = @findEmojiIcon(emoji).siblings('.js-counter')
|
counter = $emojiButton.find '.js-counter'
|
||||||
counter.text(parseInt(counter.text()) + 1)
|
counter.text parseInt(counter.text()) + 1
|
||||||
counter.parent().addClass('active')
|
$emojiButton.addClass 'active'
|
||||||
@addMeToAuthorList(emoji)
|
@addMeToUserList votesBlock, emoji
|
||||||
|
@animateEmoji $emojiButton
|
||||||
else
|
else
|
||||||
@createEmoji(emoji)
|
votesBlock.removeClass 'hidden'
|
||||||
|
@createEmoji votesBlock, emoji
|
||||||
|
|
||||||
exist: (emoji) ->
|
|
||||||
@findEmojiIcon(emoji).length > 0
|
|
||||||
|
|
||||||
isActive: (emoji) ->
|
getVotesBlock: ->
|
||||||
@findEmojiIcon(emoji).parent().hasClass('active')
|
|
||||||
|
|
||||||
decrementCounter: (emoji) ->
|
currentBlock = $ '.js-awards-block.current'
|
||||||
counter = @findEmojiIcon(emoji).siblings('.js-counter')
|
return if currentBlock.length then currentBlock else $('.js-awards-block').eq 0
|
||||||
emojiIcon = counter.parent()
|
|
||||||
if parseInt(counter.text()) > 1
|
|
||||||
counter.text(parseInt(counter.text()) - 1)
|
getAwardUrl: -> return @getVotesBlock().data 'award-url'
|
||||||
emojiIcon.removeClass('active')
|
|
||||||
@removeMeFromAuthorList(emoji)
|
|
||||||
else if emoji == 'thumbsup' || emoji == 'thumbsdown'
|
checkMutuality: (votesBlock, emoji) ->
|
||||||
emojiIcon.tooltip('destroy')
|
|
||||||
counter.text(0)
|
awardUrl = @getAwardUrl()
|
||||||
emojiIcon.removeClass('active')
|
|
||||||
@removeMeFromAuthorList(emoji)
|
if emoji in [ 'thumbsup', 'thumbsdown' ]
|
||||||
|
mutualVote = if emoji is 'thumbsup' then 'thumbsdown' else 'thumbsup'
|
||||||
|
$emojiButton = votesBlock.find("[data-emoji=#{mutualVote}]").parent()
|
||||||
|
isAlreadyVoted = $emojiButton.hasClass 'active'
|
||||||
|
|
||||||
|
if isAlreadyVoted
|
||||||
|
@showEmojiLoader $emojiButton
|
||||||
|
@addAward votesBlock, awardUrl, mutualVote, false, ->
|
||||||
|
$emojiButton.removeClass 'is-loading'
|
||||||
|
|
||||||
|
|
||||||
|
showEmojiLoader: ($emojiButton) ->
|
||||||
|
|
||||||
|
$loader = $emojiButton.find '.fa-spinner'
|
||||||
|
|
||||||
|
unless $loader.length
|
||||||
|
$emojiButton.append '<i class="fa fa-spinner fa-spin award-control-icon award-control-icon-loading"></i>'
|
||||||
|
|
||||||
|
$emojiButton.addClass 'is-loading'
|
||||||
|
|
||||||
|
|
||||||
|
isActive: ($emojiButton) -> $emojiButton.hasClass 'active'
|
||||||
|
|
||||||
|
|
||||||
|
decrementCounter: ($emojiButton, emoji) ->
|
||||||
|
|
||||||
|
counter = $ '.js-counter', $emojiButton
|
||||||
|
counterNumber = parseInt counter.text(), 10
|
||||||
|
|
||||||
|
if counterNumber > 1
|
||||||
|
counter.text counterNumber - 1
|
||||||
|
@removeMeFromUserList $emojiButton, emoji
|
||||||
|
else if emoji is 'thumbsup' or emoji is 'thumbsdown'
|
||||||
|
$emojiButton.tooltip 'destroy'
|
||||||
|
counter.text '0'
|
||||||
|
@removeMeFromUserList $emojiButton, emoji
|
||||||
|
@removeEmoji $emojiButton if $emojiButton.parents('.note').length
|
||||||
else
|
else
|
||||||
emojiIcon.tooltip('destroy')
|
@removeEmoji $emojiButton
|
||||||
emojiIcon.remove()
|
|
||||||
|
$emojiButton.removeClass 'active'
|
||||||
|
|
||||||
|
|
||||||
|
removeEmoji: ($emojiButton) ->
|
||||||
|
|
||||||
|
$emojiButton.tooltip('destroy')
|
||||||
|
$emojiButton.remove()
|
||||||
|
|
||||||
|
$votesBlock = @getVotesBlock()
|
||||||
|
|
||||||
|
if $votesBlock.find('.js-emoji-btn').length is 0
|
||||||
|
$votesBlock.addClass 'hidden'
|
||||||
|
|
||||||
|
|
||||||
|
getAwardTooltip: ($awardBlock) ->
|
||||||
|
|
||||||
|
return $awardBlock.attr('data-original-title') or $awardBlock.attr('data-title') or ''
|
||||||
|
|
||||||
|
|
||||||
|
removeMeFromUserList: ($emojiButton, emoji) ->
|
||||||
|
|
||||||
|
awardBlock = $emojiButton
|
||||||
|
originalTitle = @getAwardTooltip awardBlock
|
||||||
|
|
||||||
|
authors = originalTitle.split ', '
|
||||||
|
authors.splice authors.indexOf('me'), 1
|
||||||
|
|
||||||
|
newAuthors = authors.join ', '
|
||||||
|
|
||||||
removeMeFromAuthorList: (emoji) ->
|
|
||||||
awardBlock = @findEmojiIcon(emoji).parent()
|
|
||||||
authors = awardBlock
|
|
||||||
.attr('data-original-title')
|
|
||||||
.split(', ')
|
|
||||||
authors.splice(authors.indexOf('me'),1)
|
|
||||||
awardBlock
|
awardBlock
|
||||||
.closest('.js-emoji-btn')
|
.closest '.js-emoji-btn'
|
||||||
.attr('data-original-title', authors.join(', '))
|
.removeData 'original-title'
|
||||||
@resetTooltip(awardBlock)
|
.attr 'data-original-title', newAuthors
|
||||||
|
|
||||||
|
@resetTooltip awardBlock
|
||||||
|
|
||||||
|
|
||||||
|
addMeToUserList: (votesBlock, emoji) ->
|
||||||
|
|
||||||
|
awardBlock = @findEmojiIcon(votesBlock, emoji).parent()
|
||||||
|
origTitle = @getAwardTooltip awardBlock
|
||||||
|
users = []
|
||||||
|
|
||||||
addMeToAuthorList: (emoji) ->
|
|
||||||
awardBlock = @findEmojiIcon(emoji).parent()
|
|
||||||
origTitle = awardBlock.attr('data-original-title').trim()
|
|
||||||
authors = []
|
|
||||||
if origTitle
|
if origTitle
|
||||||
authors = origTitle.split(', ')
|
users = origTitle.trim().split ', '
|
||||||
authors.push('me')
|
|
||||||
awardBlock.attr('data-original-title', authors.join(', '))
|
users.push 'me'
|
||||||
@resetTooltip(awardBlock)
|
awardBlock.attr 'title', users.join ', '
|
||||||
|
|
||||||
|
@resetTooltip awardBlock
|
||||||
|
|
||||||
|
|
||||||
resetTooltip: (award) ->
|
resetTooltip: (award) ->
|
||||||
award.tooltip('destroy')
|
|
||||||
|
|
||||||
# "destroy" call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
|
award.tooltip 'destroy'
|
||||||
setTimeout (->
|
|
||||||
award.tooltip()
|
# 'destroy' call is asynchronous and there is no appropriate callback on it, this is why we need to set timeout.
|
||||||
), 200
|
cb = -> award.tooltip()
|
||||||
|
setTimeout cb, 200
|
||||||
|
|
||||||
|
|
||||||
createEmoji: (emoji) ->
|
createEmoji_: (votesBlock, emoji) ->
|
||||||
emojiCssClass = @resolveNameToCssClass(emoji)
|
|
||||||
|
|
||||||
nodes = []
|
emojiCssClass = @resolveNameToCssClass emoji
|
||||||
nodes.push(
|
buttonHtml = "<button class='btn award-control js-emoji-btn has-tooltip active' title='me' data-placement='bottom'>
|
||||||
"<button class='btn award-control js-emoji-btn has-tooltip active' data-original-title='me'>",
|
<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>
|
||||||
"<div class='icon emoji-icon #{emojiCssClass}' data-emoji='#{emoji}'></div>",
|
<span class='award-control-text js-counter'>1</span>
|
||||||
"<span class='award-control-text js-counter'>1</span>",
|
</button>"
|
||||||
"</button>"
|
|
||||||
)
|
|
||||||
|
|
||||||
$(nodes.join("\n"))
|
$emojiButton = $ buttonHtml
|
||||||
.insertBefore('.js-award-holder')
|
$emojiButton
|
||||||
.find('.emoji-icon')
|
.insertBefore votesBlock.find '.js-award-holder'
|
||||||
.data('emoji', emoji)
|
.find '.emoji-icon'
|
||||||
|
.data 'emoji', emoji
|
||||||
|
|
||||||
|
@animateEmoji $emojiButton
|
||||||
$('.award-control').tooltip()
|
$('.award-control').tooltip()
|
||||||
|
votesBlock.removeClass 'current'
|
||||||
|
|
||||||
|
|
||||||
|
animateEmoji: ($emoji) ->
|
||||||
|
|
||||||
|
className = 'pulse animated'
|
||||||
|
|
||||||
|
$emoji.addClass className
|
||||||
|
setTimeout (-> $emoji.removeClass className), 321
|
||||||
|
|
||||||
|
|
||||||
|
createEmoji: (votesBlock, emoji) ->
|
||||||
|
|
||||||
|
if $('.emoji-menu').length
|
||||||
|
return @createEmoji_ votesBlock, emoji
|
||||||
|
|
||||||
|
@createEmojiMenu @getAwardMenuUrl(), => @createEmoji_ votesBlock, emoji
|
||||||
|
|
||||||
|
|
||||||
|
getAwardMenuUrl: -> return gon.award_menu_url
|
||||||
|
|
||||||
|
|
||||||
resolveNameToCssClass: (emoji) ->
|
resolveNameToCssClass: (emoji) ->
|
||||||
emojiIcon = $(".emoji-menu-content [data-emoji='#{emoji}']")
|
|
||||||
|
emojiIcon = $ ".emoji-menu-content [data-emoji='#{emoji}']"
|
||||||
|
|
||||||
if emojiIcon.length > 0
|
if emojiIcon.length > 0
|
||||||
unicodeName = emojiIcon.data('unicode-name')
|
unicodeName = emojiIcon.data 'unicode-name'
|
||||||
else
|
else
|
||||||
# Find by alias
|
# Find by alias
|
||||||
unicodeName = $(".emoji-menu-content [data-aliases*=':#{emoji}:']").data('unicode-name')
|
unicodeName = $(".emoji-menu-content [data-aliases*=':#{emoji}:']").data 'unicode-name'
|
||||||
|
|
||||||
"emoji-#{unicodeName}"
|
return "emoji-#{unicodeName}"
|
||||||
|
|
||||||
postEmoji: (emoji, callback) ->
|
|
||||||
$.post @postEmojiUrl, { note: {
|
|
||||||
note: ":#{emoji}:"
|
|
||||||
noteable_type: @noteableType
|
|
||||||
noteable_id: @noteableId
|
|
||||||
}},(data) ->
|
|
||||||
if data.ok
|
|
||||||
callback.call()
|
|
||||||
|
|
||||||
findEmojiIcon: (emoji) ->
|
postEmoji: (awardUrl, emoji, callback) ->
|
||||||
$(".awards > .js-emoji-btn [data-emoji='#{emoji}']")
|
|
||||||
|
$.post awardUrl, { name: emoji }, (data) ->
|
||||||
|
callback() if data.ok
|
||||||
|
|
||||||
|
|
||||||
|
findEmojiIcon: (votesBlock, emoji) ->
|
||||||
|
|
||||||
|
return votesBlock.find ".js-emoji-btn [data-emoji='#{emoji}']"
|
||||||
|
|
||||||
|
|
||||||
scrollToAwards: ->
|
scrollToAwards: ->
|
||||||
$('body, html').animate({
|
|
||||||
scrollTop: $('.awards').offset().top - 80
|
options = scrollTop: $('.awards').offset().top - 110
|
||||||
}, 200)
|
$('body, html').animate options, 200
|
||||||
|
|
||||||
|
|
||||||
|
normilizeEmojiName: (emoji) -> return @aliases[emoji] or emoji
|
||||||
|
|
||||||
|
|
||||||
addEmojiToFrequentlyUsedList: (emoji) ->
|
addEmojiToFrequentlyUsedList: (emoji) ->
|
||||||
|
|
||||||
frequentlyUsedEmojis = @getFrequentlyUsedEmojis()
|
frequentlyUsedEmojis = @getFrequentlyUsedEmojis()
|
||||||
frequentlyUsedEmojis.push(emoji)
|
frequentlyUsedEmojis.push emoji
|
||||||
$.cookie('frequently_used_emojis', frequentlyUsedEmojis.join(','), { expires: 365 })
|
$.cookie 'frequently_used_emojis', frequentlyUsedEmojis.join(','), { expires: 365 }
|
||||||
|
|
||||||
|
|
||||||
getFrequentlyUsedEmojis: ->
|
getFrequentlyUsedEmojis: ->
|
||||||
frequentlyUsedEmojis = ($.cookie('frequently_used_emojis') || '').split(',')
|
|
||||||
_.compact(_.uniq(frequentlyUsedEmojis))
|
frequentlyUsedEmojis = ($.cookie('frequently_used_emojis') or '').split(',')
|
||||||
|
return _.compact _.uniq frequentlyUsedEmojis
|
||||||
|
|
||||||
|
|
||||||
renderFrequentlyUsedBlock: ->
|
renderFrequentlyUsedBlock: ->
|
||||||
if $.cookie('frequently_used_emojis')
|
|
||||||
|
if $.cookie 'frequently_used_emojis'
|
||||||
frequentlyUsedEmojis = @getFrequentlyUsedEmojis()
|
frequentlyUsedEmojis = @getFrequentlyUsedEmojis()
|
||||||
|
|
||||||
ul = $('<ul>')
|
ul = $("<ul class='clearfix emoji-menu-list frequent-emojis'>")
|
||||||
|
|
||||||
for emoji in frequentlyUsedEmojis
|
for emoji in frequentlyUsedEmojis
|
||||||
do (emoji) ->
|
|
||||||
$(".emoji-menu-content [data-emoji='#{emoji}']").closest('li').clone().appendTo(ul)
|
$(".emoji-menu-content [data-emoji='#{emoji}']").closest('li').clone().appendTo(ul)
|
||||||
|
|
||||||
$('input.emoji-search').after(ul).after($('<h5>').text('Frequently used'))
|
$('input.emoji-search').after(ul).after($('<h5>').text('Frequently used'))
|
||||||
|
|
||||||
|
@frequentEmojiBlockRendered = true
|
||||||
|
|
||||||
|
|
||||||
setupSearch: ->
|
setupSearch: ->
|
||||||
$('input.emoji-search').keyup (ev) =>
|
|
||||||
|
$('input.emoji-search').on 'keyup', (ev) =>
|
||||||
term = $(ev.target).val()
|
term = $(ev.target).val()
|
||||||
|
|
||||||
# Clean previous search results
|
# Clean previous search results
|
||||||
|
@ -204,12 +357,14 @@ class @AwardsHandler
|
||||||
if term
|
if term
|
||||||
# Generate a search result block
|
# Generate a search result block
|
||||||
h5 = $('<h5>').text('Search results').addClass('emoji-search')
|
h5 = $('<h5>').text('Search results').addClass('emoji-search')
|
||||||
foundEmojis = @searchEmojis(term).show()
|
found_emojis = @searchEmojis(term).show()
|
||||||
ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(foundEmojis)
|
ul = $('<ul>').addClass('emoji-menu-list emoji-menu-search').append(found_emojis)
|
||||||
$('.emoji-menu-content ul, .emoji-menu-content h5').hide()
|
$('.emoji-menu-content ul, .emoji-menu-content h5').hide()
|
||||||
$('.emoji-menu-content').append(h5).append(ul)
|
$('.emoji-menu-content').append(h5).append(ul)
|
||||||
else
|
else
|
||||||
$('.emoji-menu-content').children().show()
|
$('.emoji-menu-content').children().show()
|
||||||
|
|
||||||
searchEmojis: (term)->
|
|
||||||
$(".emoji-menu-content [data-emoji*='#{term}']").closest("li").clone()
|
searchEmojis: (term) ->
|
||||||
|
|
||||||
|
$(".emoji-menu-list:not(.frequent-emojis) [data-emoji*='#{term}']").closest('li').clone()
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
class @Calendar
|
|
||||||
constructor: (timestamps, starting_year, starting_month, calendar_activities_path) ->
|
|
||||||
cal = new CalHeatMap()
|
|
||||||
cal.init
|
|
||||||
itemName: ["contribution"]
|
|
||||||
data: timestamps
|
|
||||||
start: new Date(starting_year, starting_month)
|
|
||||||
domainLabelFormat: "%b"
|
|
||||||
id: "cal-heatmap"
|
|
||||||
domain: "month"
|
|
||||||
subDomain: "day"
|
|
||||||
range: 12
|
|
||||||
tooltip: true
|
|
||||||
label:
|
|
||||||
position: "top"
|
|
||||||
legend: [
|
|
||||||
0
|
|
||||||
10
|
|
||||||
20
|
|
||||||
30
|
|
||||||
]
|
|
||||||
legendCellPadding: 3
|
|
||||||
cellSize: $('.user-calendar').width() / 73
|
|
||||||
onClick: (date, count) ->
|
|
||||||
formated_date = date.getFullYear() + "-" + (date.getMonth()+1) + "-" + date.getDate()
|
|
||||||
$.ajax
|
|
||||||
url: calendar_activities_path
|
|
||||||
data:
|
|
||||||
date: formated_date
|
|
||||||
cache: false
|
|
||||||
dataType: "html"
|
|
||||||
success: (data) ->
|
|
||||||
$(".user-calendar-activities").html data
|
|
||||||
|
|
|
@ -1,19 +1,33 @@
|
||||||
class CiBuild
|
class @CiBuild
|
||||||
@interval: null
|
@interval: null
|
||||||
@state: null
|
@state: null
|
||||||
|
|
||||||
constructor: (build_url, build_status, build_state) ->
|
constructor: (@build_url, @build_status, @state) ->
|
||||||
clearInterval(CiBuild.interval)
|
clearInterval(CiBuild.interval)
|
||||||
|
|
||||||
@state = build_state
|
# Init breakpoint checker
|
||||||
|
@bp = Breakpoints.get()
|
||||||
|
@hideSidebar()
|
||||||
|
$('.js-build-sidebar').niceScroll()
|
||||||
|
$(document)
|
||||||
|
.off 'click', '.js-sidebar-build-toggle'
|
||||||
|
.on 'click', '.js-sidebar-build-toggle', @toggleSidebar
|
||||||
|
|
||||||
|
$(window)
|
||||||
|
.off 'resize.build'
|
||||||
|
.on 'resize.build', @hideSidebar
|
||||||
|
|
||||||
|
@updateArtifactRemoveDate()
|
||||||
|
|
||||||
|
if $('#build-trace').length
|
||||||
|
@getInitialBuildTrace()
|
||||||
@initScrollButtonAffix()
|
@initScrollButtonAffix()
|
||||||
|
|
||||||
if build_status == "running" || build_status == "pending"
|
if @build_status is "running" or @build_status is "pending"
|
||||||
#
|
#
|
||||||
# Bind autoscroll button to follow build output
|
# Bind autoscroll button to follow build output
|
||||||
#
|
#
|
||||||
$("#autoscroll-button").bind "click", ->
|
$('#autoscroll-button').on 'click', ->
|
||||||
state = $(this).data("state")
|
state = $(this).data("state")
|
||||||
if "enabled" is state
|
if "enabled" is state
|
||||||
$(this).data "state", "disabled"
|
$(this).data "state", "disabled"
|
||||||
|
@ -27,25 +41,36 @@ class CiBuild
|
||||||
# Only valid for runnig build when output changes during time
|
# Only valid for runnig build when output changes during time
|
||||||
#
|
#
|
||||||
CiBuild.interval = setInterval =>
|
CiBuild.interval = setInterval =>
|
||||||
if window.location.href.split("#").first() is build_url
|
if window.location.href.split("#").first() is @build_url
|
||||||
last_state = @state
|
@getBuildTrace()
|
||||||
|
, 4000
|
||||||
|
|
||||||
|
getInitialBuildTrace: ->
|
||||||
$.ajax
|
$.ajax
|
||||||
url: build_url + "/trace.json?state=" + encodeURIComponent(@state)
|
url: @build_url
|
||||||
|
dataType: 'json'
|
||||||
|
success: (build_data) ->
|
||||||
|
$('.js-build-output').html build_data.trace_html
|
||||||
|
|
||||||
|
if build_data.status is 'success' or build_data.status is 'failed'
|
||||||
|
$('.js-build-refresh').remove()
|
||||||
|
|
||||||
|
getBuildTrace: ->
|
||||||
|
$.ajax
|
||||||
|
url: "#{@build_url}/trace.json?state=#{encodeURIComponent(@state)}"
|
||||||
dataType: "json"
|
dataType: "json"
|
||||||
success: (log) =>
|
success: (log) =>
|
||||||
return unless last_state is @state
|
if log.state
|
||||||
|
|
||||||
if log.state and log.status is "running"
|
|
||||||
@state = log.state
|
@state = log.state
|
||||||
|
|
||||||
|
if log.status is "running"
|
||||||
if log.append
|
if log.append
|
||||||
$('.fa-refresh').before log.html
|
$('.js-build-output').append log.html
|
||||||
else
|
else
|
||||||
$('#build-trace code').html log.html
|
$('.js-build-output').html log.html
|
||||||
$('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>'
|
|
||||||
@checkAutoscroll()
|
@checkAutoscroll()
|
||||||
else if log.status isnt build_status
|
else if log.status isnt @build_status
|
||||||
Turbolinks.visit build_url
|
Turbolinks.visit @build_url
|
||||||
, 4000
|
|
||||||
|
|
||||||
checkAutoscroll: ->
|
checkAutoscroll: ->
|
||||||
$("html,body").scrollTop $("#build-trace").height() if "enabled" is $("#autoscroll-button").data("state")
|
$("html,body").scrollTop $("#build-trace").height() if "enabled" is $("#autoscroll-button").data("state")
|
||||||
|
@ -61,4 +86,29 @@ class CiBuild
|
||||||
$body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top)
|
$body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top)
|
||||||
)
|
)
|
||||||
|
|
||||||
@CiBuild = CiBuild
|
shouldHideSidebar: ->
|
||||||
|
bootstrapBreakpoint = @bp.getBreakpointSize()
|
||||||
|
|
||||||
|
bootstrapBreakpoint is 'xs' or bootstrapBreakpoint is 'sm'
|
||||||
|
|
||||||
|
toggleSidebar: =>
|
||||||
|
if @shouldHideSidebar()
|
||||||
|
$('.js-build-sidebar')
|
||||||
|
.toggleClass 'right-sidebar-expanded right-sidebar-collapsed'
|
||||||
|
|
||||||
|
hideSidebar: =>
|
||||||
|
if @shouldHideSidebar()
|
||||||
|
$('.js-build-sidebar')
|
||||||
|
.removeClass 'right-sidebar-expanded'
|
||||||
|
.addClass 'right-sidebar-collapsed'
|
||||||
|
else
|
||||||
|
$('.js-build-sidebar')
|
||||||
|
.removeClass 'right-sidebar-collapsed'
|
||||||
|
.addClass 'right-sidebar-expanded'
|
||||||
|
|
||||||
|
updateArtifactRemoveDate: ->
|
||||||
|
$date = $('.js-artifacts-remove')
|
||||||
|
|
||||||
|
if $date.length
|
||||||
|
date = $date.text()
|
||||||
|
$date.text $.timefor(new Date(date), ' ')
|
||||||
|
|
|
@ -16,8 +16,8 @@ class Dispatcher
|
||||||
shortcut_handler = null
|
shortcut_handler = null
|
||||||
switch page
|
switch page
|
||||||
when 'projects:issues:index'
|
when 'projects:issues:index'
|
||||||
Issues.init()
|
|
||||||
Issuable.init()
|
Issuable.init()
|
||||||
|
new IssuableBulkActions()
|
||||||
shortcut_handler = new ShortcutsNavigation()
|
shortcut_handler = new ShortcutsNavigation()
|
||||||
when 'projects:issues:show'
|
when 'projects:issues:show'
|
||||||
new Issue()
|
new Issue()
|
||||||
|
@ -53,9 +53,13 @@ class Dispatcher
|
||||||
new Diff()
|
new Diff()
|
||||||
shortcut_handler = new ShortcutsIssuable(true)
|
shortcut_handler = new ShortcutsIssuable(true)
|
||||||
new ZenMode()
|
new ZenMode()
|
||||||
|
new MergedButtons()
|
||||||
|
when 'projects:merge_requests:commits', 'projects:merge_requests:builds'
|
||||||
|
new MergedButtons()
|
||||||
when "projects:merge_requests:diffs"
|
when "projects:merge_requests:diffs"
|
||||||
new Diff()
|
new Diff()
|
||||||
new ZenMode()
|
new ZenMode()
|
||||||
|
new MergedButtons()
|
||||||
when 'projects:merge_requests:index'
|
when 'projects:merge_requests:index'
|
||||||
shortcut_handler = new ShortcutsNavigation()
|
shortcut_handler = new ShortcutsNavigation()
|
||||||
Issuable.init()
|
Issuable.init()
|
||||||
|
@ -98,6 +102,8 @@ class Dispatcher
|
||||||
shortcut_handler = new ShortcutsNavigation()
|
shortcut_handler = new ShortcutsNavigation()
|
||||||
when 'projects:labels:new', 'projects:labels:edit'
|
when 'projects:labels:new', 'projects:labels:edit'
|
||||||
new Labels()
|
new Labels()
|
||||||
|
when 'projects:labels:index'
|
||||||
|
new LabelManager() if $('.prioritized-labels').length
|
||||||
when 'projects:network:show'
|
when 'projects:network:show'
|
||||||
# Ensure we don't create a particular shortcut handler here. This is
|
# Ensure we don't create a particular shortcut handler here. This is
|
||||||
# already created, where the network graph is created.
|
# already created, where the network graph is created.
|
||||||
|
@ -119,7 +125,7 @@ class Dispatcher
|
||||||
new UsersSelect()
|
new UsersSelect()
|
||||||
when 'projects'
|
when 'projects'
|
||||||
new NamespaceSelect()
|
new NamespaceSelect()
|
||||||
when 'dashboard'
|
when 'dashboard', 'root'
|
||||||
shortcut_handler = new ShortcutsDashboardNavigation()
|
shortcut_handler = new ShortcutsDashboardNavigation()
|
||||||
when 'profiles'
|
when 'profiles'
|
||||||
new Profile()
|
new Profile()
|
||||||
|
|
|
@ -21,7 +21,7 @@ class @DueDateSelect
|
||||||
$dropdown.glDropdown(
|
$dropdown.glDropdown(
|
||||||
hidden: ->
|
hidden: ->
|
||||||
$selectbox.hide()
|
$selectbox.hide()
|
||||||
$value.removeAttr('style')
|
$value.css('display', '')
|
||||||
)
|
)
|
||||||
|
|
||||||
addDueDate = (isDropdown) ->
|
addDueDate = (isDropdown) ->
|
||||||
|
@ -42,12 +42,13 @@ class @DueDateSelect
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
url: issueUpdateURL
|
url: issueUpdateURL
|
||||||
data: data
|
data: data
|
||||||
|
dataType: 'json'
|
||||||
beforeSend: ->
|
beforeSend: ->
|
||||||
$loading.fadeIn()
|
$loading.fadeIn()
|
||||||
if isDropdown
|
if isDropdown
|
||||||
$dropdown.trigger('loading.gl.dropdown')
|
$dropdown.trigger('loading.gl.dropdown')
|
||||||
$selectbox.hide()
|
$selectbox.hide()
|
||||||
$value.removeAttr('style')
|
$value.css('display', '')
|
||||||
|
|
||||||
$valueContent.html(mediumDate)
|
$valueContent.html(mediumDate)
|
||||||
$sidebarValue.html(mediumDate)
|
$sidebarValue.html(mediumDate)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class @Flash
|
class @Flash
|
||||||
constructor: (message, type)->
|
constructor: (message, type = 'alert')->
|
||||||
@flash = $(".flash-container")
|
@flash = $(".flash-container")
|
||||||
@flash.html("")
|
@flash.html("")
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
window.GitLab ?= {}
|
window.GitLab ?= {}
|
||||||
GitLab.GfmAutoComplete =
|
GitLab.GfmAutoComplete =
|
||||||
dataLoading: false
|
dataLoading: false
|
||||||
|
dataLoaded: false
|
||||||
|
|
||||||
dataSource: ''
|
dataSource: ''
|
||||||
|
|
||||||
|
@ -22,6 +23,24 @@ GitLab.GfmAutoComplete =
|
||||||
Milestones:
|
Milestones:
|
||||||
template: '<li>${title}</li>'
|
template: '<li>${title}</li>'
|
||||||
|
|
||||||
|
Loading:
|
||||||
|
template: '<li><i class="fa fa-refresh fa-spin"></i> Loading...</li>'
|
||||||
|
|
||||||
|
DefaultOptions:
|
||||||
|
sorter: (query, items, searchKey) ->
|
||||||
|
return items if items[0].name? and items[0].name is 'loading'
|
||||||
|
|
||||||
|
$.fn.atwho.default.callbacks.sorter(query, items, searchKey)
|
||||||
|
filter: (query, data, searchKey) ->
|
||||||
|
return data if data[0] is 'loading'
|
||||||
|
|
||||||
|
$.fn.atwho.default.callbacks.filter(query, data, searchKey)
|
||||||
|
beforeInsert: (value) ->
|
||||||
|
if not GitLab.GfmAutoComplete.dataLoaded
|
||||||
|
@at
|
||||||
|
else
|
||||||
|
value
|
||||||
|
|
||||||
# Add GFM auto-completion to all input fields, that accept GFM input.
|
# Add GFM auto-completion to all input fields, that accept GFM input.
|
||||||
setup: (wrap) ->
|
setup: (wrap) ->
|
||||||
@input = $('.js-gfm-input')
|
@input = $('.js-gfm-input')
|
||||||
|
@ -53,18 +72,37 @@ GitLab.GfmAutoComplete =
|
||||||
# Emoji
|
# Emoji
|
||||||
@input.atwho
|
@input.atwho
|
||||||
at: ':'
|
at: ':'
|
||||||
displayTpl: @Emoji.template
|
displayTpl: (value) =>
|
||||||
|
if value.path?
|
||||||
|
@Emoji.template
|
||||||
|
else
|
||||||
|
@Loading.template
|
||||||
insertTpl: ':${name}:'
|
insertTpl: ':${name}:'
|
||||||
|
data: ['loading']
|
||||||
|
callbacks:
|
||||||
|
sorter: @DefaultOptions.sorter
|
||||||
|
filter: @DefaultOptions.filter
|
||||||
|
beforeInsert: @DefaultOptions.beforeInsert
|
||||||
|
|
||||||
# Team Members
|
# Team Members
|
||||||
@input.atwho
|
@input.atwho
|
||||||
at: '@'
|
at: '@'
|
||||||
displayTpl: @Members.template
|
displayTpl: (value) =>
|
||||||
|
if value.username?
|
||||||
|
@Members.template
|
||||||
|
else
|
||||||
|
@Loading.template
|
||||||
insertTpl: '${atwho-at}${username}'
|
insertTpl: '${atwho-at}${username}'
|
||||||
searchKey: 'search'
|
searchKey: 'search'
|
||||||
|
data: ['loading']
|
||||||
callbacks:
|
callbacks:
|
||||||
|
sorter: @DefaultOptions.sorter
|
||||||
|
filter: @DefaultOptions.filter
|
||||||
|
beforeInsert: @DefaultOptions.beforeInsert
|
||||||
beforeSave: (members) ->
|
beforeSave: (members) ->
|
||||||
$.map members, (m) ->
|
$.map members, (m) ->
|
||||||
|
return m if not m.username?
|
||||||
|
|
||||||
title = m.name
|
title = m.name
|
||||||
title += " (#{m.count})" if m.count
|
title += " (#{m.count})" if m.count
|
||||||
|
|
||||||
|
@ -76,11 +114,21 @@ GitLab.GfmAutoComplete =
|
||||||
at: '#'
|
at: '#'
|
||||||
alias: 'issues'
|
alias: 'issues'
|
||||||
searchKey: 'search'
|
searchKey: 'search'
|
||||||
displayTpl: @Issues.template
|
displayTpl: (value) =>
|
||||||
|
if value.title?
|
||||||
|
@Issues.template
|
||||||
|
else
|
||||||
|
@Loading.template
|
||||||
|
data: ['loading']
|
||||||
insertTpl: '${atwho-at}${id}'
|
insertTpl: '${atwho-at}${id}'
|
||||||
callbacks:
|
callbacks:
|
||||||
|
sorter: @DefaultOptions.sorter
|
||||||
|
filter: @DefaultOptions.filter
|
||||||
|
beforeInsert: @DefaultOptions.beforeInsert
|
||||||
beforeSave: (issues) ->
|
beforeSave: (issues) ->
|
||||||
$.map issues, (i) ->
|
$.map issues, (i) ->
|
||||||
|
return i if not i.title?
|
||||||
|
|
||||||
id: i.iid
|
id: i.iid
|
||||||
title: sanitize(i.title)
|
title: sanitize(i.title)
|
||||||
search: "#{i.iid} #{i.title}"
|
search: "#{i.iid} #{i.title}"
|
||||||
|
@ -89,11 +137,18 @@ GitLab.GfmAutoComplete =
|
||||||
at: '%'
|
at: '%'
|
||||||
alias: 'milestones'
|
alias: 'milestones'
|
||||||
searchKey: 'search'
|
searchKey: 'search'
|
||||||
displayTpl: @Milestones.template
|
displayTpl: (value) =>
|
||||||
|
if value.title?
|
||||||
|
@Milestones.template
|
||||||
|
else
|
||||||
|
@Loading.template
|
||||||
insertTpl: '${atwho-at}"${title}"'
|
insertTpl: '${atwho-at}"${title}"'
|
||||||
|
data: ['loading']
|
||||||
callbacks:
|
callbacks:
|
||||||
beforeSave: (milestones) ->
|
beforeSave: (milestones) ->
|
||||||
$.map milestones, (m) ->
|
$.map milestones, (m) ->
|
||||||
|
return m if not m.title?
|
||||||
|
|
||||||
id: m.iid
|
id: m.iid
|
||||||
title: sanitize(m.title)
|
title: sanitize(m.title)
|
||||||
search: "#{m.title}"
|
search: "#{m.title}"
|
||||||
|
@ -102,11 +157,21 @@ GitLab.GfmAutoComplete =
|
||||||
at: '!'
|
at: '!'
|
||||||
alias: 'mergerequests'
|
alias: 'mergerequests'
|
||||||
searchKey: 'search'
|
searchKey: 'search'
|
||||||
displayTpl: @Issues.template
|
displayTpl: (value) =>
|
||||||
|
if value.title?
|
||||||
|
@Issues.template
|
||||||
|
else
|
||||||
|
@Loading.template
|
||||||
|
data: ['loading']
|
||||||
insertTpl: '${atwho-at}${id}'
|
insertTpl: '${atwho-at}${id}'
|
||||||
callbacks:
|
callbacks:
|
||||||
|
sorter: @DefaultOptions.sorter
|
||||||
|
filter: @DefaultOptions.filter
|
||||||
|
beforeInsert: @DefaultOptions.beforeInsert
|
||||||
beforeSave: (merges) ->
|
beforeSave: (merges) ->
|
||||||
$.map merges, (m) ->
|
$.map merges, (m) ->
|
||||||
|
return m if not m.title?
|
||||||
|
|
||||||
id: m.iid
|
id: m.iid
|
||||||
title: sanitize(m.title)
|
title: sanitize(m.title)
|
||||||
search: "#{m.iid} #{m.title}"
|
search: "#{m.iid} #{m.title}"
|
||||||
|
@ -118,6 +183,8 @@ GitLab.GfmAutoComplete =
|
||||||
$.getJSON(dataSource)
|
$.getJSON(dataSource)
|
||||||
|
|
||||||
loadData: (data) ->
|
loadData: (data) ->
|
||||||
|
@dataLoaded = true
|
||||||
|
|
||||||
# load members
|
# load members
|
||||||
@input.atwho 'load', '@', data.members
|
@input.atwho 'load', '@', data.members
|
||||||
# load issues
|
# load issues
|
||||||
|
@ -128,3 +195,7 @@ GitLab.GfmAutoComplete =
|
||||||
@input.atwho 'load', 'mergerequests', data.mergerequests
|
@input.atwho 'load', 'mergerequests', data.mergerequests
|
||||||
# load emojis
|
# load emojis
|
||||||
@input.atwho 'load', ':', data.emojis
|
@input.atwho 'load', ':', data.emojis
|
||||||
|
|
||||||
|
# This trigger at.js again
|
||||||
|
# otherwise we would be stuck with loading until the user types
|
||||||
|
$(':focus').trigger('keyup')
|
||||||
|
|
|
@ -11,6 +11,8 @@ class GitLabDropdownFilter
|
||||||
$inputContainer = @input.parent()
|
$inputContainer = @input.parent()
|
||||||
$clearButton = $inputContainer.find('.js-dropdown-input-clear')
|
$clearButton = $inputContainer.find('.js-dropdown-input-clear')
|
||||||
|
|
||||||
|
@indeterminateIds = []
|
||||||
|
|
||||||
# Clear click
|
# Clear click
|
||||||
$clearButton.on 'click', (e) =>
|
$clearButton.on 'click', (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -35,20 +37,20 @@ class GitLabDropdownFilter
|
||||||
if keyCode is 13
|
if keyCode is 13
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
# Only filter asynchronously only if option remote is set
|
||||||
|
if @options.remote
|
||||||
clearTimeout timeout
|
clearTimeout timeout
|
||||||
timeout = setTimeout =>
|
timeout = setTimeout =>
|
||||||
blur_field = @shouldBlur keyCode
|
blur_field = @shouldBlur keyCode
|
||||||
search_text = @input.val()
|
|
||||||
|
|
||||||
if blur_field and @filterInputBlur
|
if blur_field and @filterInputBlur
|
||||||
@input.blur()
|
@input.blur()
|
||||||
|
|
||||||
if @options.remote
|
@options.query @input.val(), (data) =>
|
||||||
@options.query search_text, (data) =>
|
|
||||||
@options.callback(data)
|
@options.callback(data)
|
||||||
else
|
|
||||||
@filter search_text
|
|
||||||
, 250
|
, 250
|
||||||
|
else
|
||||||
|
@filter @input.val()
|
||||||
|
|
||||||
shouldBlur: (keyCode) ->
|
shouldBlur: (keyCode) ->
|
||||||
return BLUR_KEYCODES.indexOf(keyCode) >= 0
|
return BLUR_KEYCODES.indexOf(keyCode) >= 0
|
||||||
|
@ -142,6 +144,7 @@ class GitLabDropdown
|
||||||
LOADING_CLASS = "is-loading"
|
LOADING_CLASS = "is-loading"
|
||||||
PAGE_TWO_CLASS = "is-page-two"
|
PAGE_TWO_CLASS = "is-page-two"
|
||||||
ACTIVE_CLASS = "is-active"
|
ACTIVE_CLASS = "is-active"
|
||||||
|
INDETERMINATE_CLASS = "is-indeterminate"
|
||||||
currentIndex = -1
|
currentIndex = -1
|
||||||
|
|
||||||
FILTER_INPUT = '.dropdown-input .dropdown-input-field'
|
FILTER_INPUT = '.dropdown-input .dropdown-input-field'
|
||||||
|
@ -182,9 +185,6 @@ class GitLabDropdown
|
||||||
@fullData = data
|
@fullData = data
|
||||||
|
|
||||||
@parseData @fullData
|
@parseData @fullData
|
||||||
|
|
||||||
if @options.filterable
|
|
||||||
@filterInput.trigger 'keyup'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Init filterable
|
# Init filterable
|
||||||
|
@ -211,6 +211,7 @@ class GitLabDropdown
|
||||||
|
|
||||||
@dropdown.on "shown.bs.dropdown", @opened
|
@dropdown.on "shown.bs.dropdown", @opened
|
||||||
@dropdown.on "hidden.bs.dropdown", @hidden
|
@dropdown.on "hidden.bs.dropdown", @hidden
|
||||||
|
$(@el).on "update.label", @updateLabel
|
||||||
@dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate
|
@dropdown.on "click", ".dropdown-menu, .dropdown-menu-close", @shouldPropagate
|
||||||
@dropdown.on 'keyup', (e) =>
|
@dropdown.on 'keyup', (e) =>
|
||||||
if e.which is 27 # Escape key
|
if e.which is 27 # Escape key
|
||||||
|
@ -298,6 +299,13 @@ class GitLabDropdown
|
||||||
opened: =>
|
opened: =>
|
||||||
@addArrowKeyEvent()
|
@addArrowKeyEvent()
|
||||||
|
|
||||||
|
if @options.setIndeterminateIds
|
||||||
|
@options.setIndeterminateIds.call(@)
|
||||||
|
|
||||||
|
# Makes indeterminate items effective
|
||||||
|
if @fullData and @dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')
|
||||||
|
@parseData @fullData
|
||||||
|
|
||||||
contentHtml = $('.dropdown-content', @dropdown).html()
|
contentHtml = $('.dropdown-content', @dropdown).html()
|
||||||
if @remote && contentHtml is ""
|
if @remote && contentHtml is ""
|
||||||
@remote.execute()
|
@remote.execute()
|
||||||
|
@ -309,12 +317,18 @@ class GitLabDropdown
|
||||||
|
|
||||||
hidden: (e) =>
|
hidden: (e) =>
|
||||||
@removeArrayKeyEvent()
|
@removeArrayKeyEvent()
|
||||||
|
|
||||||
|
$input = @dropdown.find(".dropdown-input-field")
|
||||||
|
|
||||||
if @options.filterable
|
if @options.filterable
|
||||||
@dropdown
|
$input
|
||||||
.find(".dropdown-input-field")
|
|
||||||
.blur()
|
.blur()
|
||||||
.val("")
|
.val("")
|
||||||
.trigger("keyup")
|
|
||||||
|
# Triggering 'keyup' will re-render the dropdown which is not always required
|
||||||
|
# specially if we want to keep the state of the dropdown needed for bulk-assignment
|
||||||
|
if not @options.persistWhenHide
|
||||||
|
$input.trigger("keyup")
|
||||||
|
|
||||||
if @dropdown.find(".dropdown-toggle-page").length
|
if @dropdown.find(".dropdown-toggle-page").length
|
||||||
$('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS
|
$('.dropdown-menu', @dropdown).removeClass PAGE_TWO_CLASS
|
||||||
|
@ -358,7 +372,7 @@ class GitLabDropdown
|
||||||
|
|
||||||
if @options.renderRow
|
if @options.renderRow
|
||||||
# Call the render function
|
# Call the render function
|
||||||
html = @options.renderRow(data)
|
html = @options.renderRow.call(@options, data, @)
|
||||||
else
|
else
|
||||||
if not selected
|
if not selected
|
||||||
value = if @options.id then @options.id(data) else data.id
|
value = if @options.id then @options.id(data) else data.id
|
||||||
|
@ -440,9 +454,20 @@ class GitLabDropdown
|
||||||
|
|
||||||
# Toggle the dropdown label
|
# Toggle the dropdown label
|
||||||
if @options.toggleLabel
|
if @options.toggleLabel
|
||||||
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel
|
@updateLabel()
|
||||||
else
|
else
|
||||||
selectedObject
|
selectedObject
|
||||||
|
else if el.hasClass(INDETERMINATE_CLASS)
|
||||||
|
el.addClass ACTIVE_CLASS
|
||||||
|
el.removeClass INDETERMINATE_CLASS
|
||||||
|
|
||||||
|
if not value?
|
||||||
|
field.remove()
|
||||||
|
|
||||||
|
if not field.length and fieldName
|
||||||
|
@addInput(fieldName, value)
|
||||||
|
|
||||||
|
return selectedObject
|
||||||
else
|
else
|
||||||
if not @options.multiSelect or el.hasClass('dropdown-clear-active')
|
if not @options.multiSelect or el.hasClass('dropdown-clear-active')
|
||||||
@dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS
|
@dropdown.find(".#{ACTIVE_CLASS}").removeClass ACTIVE_CLASS
|
||||||
|
@ -456,34 +481,45 @@ class GitLabDropdown
|
||||||
|
|
||||||
# Toggle the dropdown label
|
# Toggle the dropdown label
|
||||||
if @options.toggleLabel
|
if @options.toggleLabel
|
||||||
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selectedObject, el)
|
@updateLabel(selectedObject, el)
|
||||||
if value?
|
if value?
|
||||||
if !field.length and fieldName
|
if !field.length and fieldName
|
||||||
# Create hidden input for form
|
@addInput(fieldName, value)
|
||||||
input = "<input type='hidden' name='#{fieldName}' value='#{value}' />"
|
|
||||||
if @options.inputId?
|
|
||||||
input = $(input)
|
|
||||||
.attr('id', @options.inputId)
|
|
||||||
@dropdown.before input
|
|
||||||
else
|
else
|
||||||
field.val value
|
field.val value
|
||||||
|
|
||||||
return selectedObject
|
return selectedObject
|
||||||
|
|
||||||
selectRowAtIndex: (index) ->
|
addInput: (fieldName, value)->
|
||||||
selector = ".dropdown-content li:not(.divider):eq(#{index}) a"
|
# Create hidden input for form
|
||||||
|
$input = $('<input>').attr('type', 'hidden')
|
||||||
|
.attr('name', fieldName)
|
||||||
|
.val(value)
|
||||||
|
|
||||||
|
if @options.inputId?
|
||||||
|
$input.attr('id', @options.inputId)
|
||||||
|
|
||||||
|
@dropdown.before $input
|
||||||
|
|
||||||
|
selectRowAtIndex: (e, index) ->
|
||||||
|
selector = ".dropdown-content li:not(.divider,.dropdown-header,.separator):eq(#{index}) a"
|
||||||
|
|
||||||
if @dropdown.find(".dropdown-toggle-page").length
|
if @dropdown.find(".dropdown-toggle-page").length
|
||||||
selector = ".dropdown-page-one #{selector}"
|
selector = ".dropdown-page-one #{selector}"
|
||||||
|
|
||||||
# simulate a click on the first link
|
# simulate a click on the first link
|
||||||
$(selector, @dropdown).trigger "click"
|
$el = $(selector, @dropdown)
|
||||||
|
|
||||||
|
if $el.length
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopImmediatePropagation()
|
||||||
|
$(selector, @dropdown)[0].click()
|
||||||
|
|
||||||
addArrowKeyEvent: ->
|
addArrowKeyEvent: ->
|
||||||
ARROW_KEY_CODES = [38, 40]
|
ARROW_KEY_CODES = [38, 40]
|
||||||
$input = @dropdown.find(".dropdown-input-field")
|
$input = @dropdown.find(".dropdown-input-field")
|
||||||
|
|
||||||
selector = '.dropdown-content li:not(.divider)'
|
selector = '.dropdown-content li:not(.divider,.dropdown-header,.separator)'
|
||||||
if @dropdown.find(".dropdown-toggle-page").length
|
if @dropdown.find(".dropdown-toggle-page").length
|
||||||
selector = ".dropdown-page-one #{selector}"
|
selector = ".dropdown-page-one #{selector}"
|
||||||
|
|
||||||
|
@ -511,8 +547,8 @@ class GitLabDropdown
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if currentKeyCode is 13
|
if currentKeyCode is 13 and currentIndex isnt -1
|
||||||
@selectRowAtIndex if currentIndex < 0 then 0 else currentIndex
|
@selectRowAtIndex e, currentIndex
|
||||||
|
|
||||||
removeArrayKeyEvent: ->
|
removeArrayKeyEvent: ->
|
||||||
$('body').off 'keydown'
|
$('body').off 'keydown'
|
||||||
|
@ -544,6 +580,9 @@ class GitLabDropdown
|
||||||
# Scroll the dropdown content up
|
# Scroll the dropdown content up
|
||||||
$dropdownContent.scrollTop(listItemTop - dropdownContentTop)
|
$dropdownContent.scrollTop(listItemTop - dropdownContentTop)
|
||||||
|
|
||||||
|
updateLabel: (selected = null, el = null) =>
|
||||||
|
$(@el).find(".dropdown-toggle-text").text @options.toggleLabel(selected, el)
|
||||||
|
|
||||||
$.fn.glDropdown = (opts) ->
|
$.fn.glDropdown = (opts) ->
|
||||||
return @.each ->
|
return @.each ->
|
||||||
if (!$.data @, 'glDropdown')
|
if (!$.data @, 'glDropdown')
|
||||||
|
|
8
app/assets/javascripts/graphs/application.js.coffee
Normal file
8
app/assets/javascripts/graphs/application.js.coffee
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# This is a manifest file that'll be compiled into including all the files listed below.
|
||||||
|
# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
||||||
|
# be included in the compiled file accessible from http://example.com/assets/application.js
|
||||||
|
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||||
|
# the compiled file.
|
||||||
|
#
|
||||||
|
#= require Chart
|
||||||
|
#= require_tree .
|
|
@ -1,5 +1,4 @@
|
||||||
#= require d3
|
#= require d3
|
||||||
#= require stat_graph_contributors_util
|
|
||||||
|
|
||||||
class @ContributorsStatGraph
|
class @ContributorsStatGraph
|
||||||
init: (log) ->
|
init: (log) ->
|
|
@ -1,6 +1,4 @@
|
||||||
#= require d3
|
#= require d3
|
||||||
#= require jquery
|
|
||||||
#= require underscore
|
|
||||||
|
|
||||||
class @ContributorsGraph
|
class @ContributorsGraph
|
||||||
MARGIN:
|
MARGIN:
|
|
@ -1,13 +1,23 @@
|
||||||
|
issuable_created = false
|
||||||
@Issuable =
|
@Issuable =
|
||||||
init: ->
|
init: ->
|
||||||
|
unless issuable_created
|
||||||
|
issuable_created = true
|
||||||
Issuable.initTemplates()
|
Issuable.initTemplates()
|
||||||
Issuable.initSearch()
|
Issuable.initSearch()
|
||||||
|
Issuable.initChecks()
|
||||||
|
Issuable.initLabelFilterRemove()
|
||||||
|
|
||||||
initTemplates: ->
|
initTemplates: ->
|
||||||
Issuable.labelRow = _.template(
|
Issuable.labelRow = _.template(
|
||||||
'<% _.each(labels, function(label){ %>
|
'<% _.each(labels, function(label){ %>
|
||||||
<span class="label-row">
|
<span class="label-row btn-group" role="group" aria-label="<%= _.escape(label.title) %>" style="color: <%= label.text_color %>;">
|
||||||
<a href="#"><span class="label color-label has-tooltip" style="background-color: <%= label.color %>; color: <%= label.text_color %>" title="<%= _.escape(label.description) %>" data-container="body"><%= _.escape(label.title) %></span></a>
|
<a href="#" class="btn btn-transparent has-tooltip" style="background-color: <%= label.color %>;" title="<%= _.escape(label.description) %>" data-container="body">
|
||||||
|
<%= _.escape(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) %>">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<% }); %>'
|
<% }); %>'
|
||||||
)
|
)
|
||||||
|
@ -19,15 +29,32 @@
|
||||||
.on 'keyup', ->
|
.on 'keyup', ->
|
||||||
clearTimeout(@timer)
|
clearTimeout(@timer)
|
||||||
@timer = setTimeout( ->
|
@timer = setTimeout( ->
|
||||||
Issuable.filterResults $('#issue_search_form')
|
$search = $('#issue_search')
|
||||||
|
$form = $('.js-filter-form')
|
||||||
|
$input = $("input[name='#{$search.attr('name')}']", $form)
|
||||||
|
|
||||||
|
if $input.length is 0
|
||||||
|
$form.append "<input type='hidden' name='#{$search.attr('name')}' value='#{_.escape($search.val())}'/>"
|
||||||
|
else
|
||||||
|
$input.val $search.val()
|
||||||
|
|
||||||
|
Issuable.filterResults $form
|
||||||
, 500)
|
, 500)
|
||||||
|
|
||||||
toggleLabelFilters: ->
|
initLabelFilterRemove: ->
|
||||||
$filteredLabels = $('.filtered-labels')
|
$(document)
|
||||||
if $filteredLabels.find('.label-row').length > 0
|
.off 'click', '.js-label-filter-remove'
|
||||||
$filteredLabels.removeClass('hidden')
|
.on 'click', '.js-label-filter-remove', (e) ->
|
||||||
else
|
$button = $(@)
|
||||||
$filteredLabels.addClass('hidden')
|
|
||||||
|
# Remove the label input box
|
||||||
|
$('input[name="label_name[]"]')
|
||||||
|
.filter -> @value is $button.data('label')
|
||||||
|
.remove()
|
||||||
|
|
||||||
|
# Submit the form to get new data
|
||||||
|
Issuable.filterResults $('.filter-form')
|
||||||
|
$('.js-label-select').trigger('update.label')
|
||||||
|
|
||||||
filterResults: (form) =>
|
filterResults: (form) =>
|
||||||
formData = form.serialize()
|
formData = form.serialize()
|
||||||
|
@ -37,48 +64,27 @@
|
||||||
issuesUrl = formAction
|
issuesUrl = formAction
|
||||||
issuesUrl += ("#{if formAction.indexOf('?') < 0 then '?' else '&'}")
|
issuesUrl += ("#{if formAction.indexOf('?') < 0 then '?' else '&'}")
|
||||||
issuesUrl += formData
|
issuesUrl += formData
|
||||||
$.ajax
|
|
||||||
type: 'GET'
|
|
||||||
url: formAction
|
|
||||||
data: formData
|
|
||||||
complete: ->
|
|
||||||
$('.issues-holder, .merge-requests-holder').css('opacity', '1.0')
|
|
||||||
success: (data) ->
|
|
||||||
$('.issues-holder, .merge-requests-holder').html(data.html)
|
|
||||||
# Change url so if user reload a page - search results are saved
|
|
||||||
history.replaceState {page: issuesUrl}, document.title, issuesUrl
|
|
||||||
Issuable.reload()
|
|
||||||
Issuable.updateStateFilters()
|
|
||||||
$filteredLabels = $('.filtered-labels')
|
|
||||||
|
|
||||||
if typeof Issuable.labelRow is 'function'
|
Turbolinks.visit(issuesUrl);
|
||||||
$filteredLabels.html(Issuable.labelRow(data))
|
|
||||||
|
|
||||||
Issuable.toggleLabelFilters()
|
initChecks: ->
|
||||||
|
$('.check_all_issues').off('click').on('click', ->
|
||||||
|
$('.selected_issue').prop('checked', @checked)
|
||||||
|
Issuable.checkChanged()
|
||||||
|
)
|
||||||
|
|
||||||
dataType: "json"
|
$('.selected_issue').off('change').on('change', Issuable.checkChanged)
|
||||||
|
|
||||||
reload: ->
|
checkChanged: ->
|
||||||
if Issues.created
|
checked_issues = $('.selected_issue:checked')
|
||||||
Issues.initChecks()
|
if checked_issues.length > 0
|
||||||
|
ids = $.map checked_issues, (value) ->
|
||||||
|
$(value).data('id')
|
||||||
|
|
||||||
$('#filter_issue_search').val($('#issue_search').val())
|
$('#update_issues_ids').val ids
|
||||||
|
$('.issues-other-filters').hide()
|
||||||
updateStateFilters: ->
|
$('.issues_bulk_update').show()
|
||||||
stateFilters = $('.issues-state-filters')
|
|
||||||
newParams = {}
|
|
||||||
paramKeys = ['author_id', 'milestone_title', 'assignee_id', 'issue_search']
|
|
||||||
|
|
||||||
for paramKey in paramKeys
|
|
||||||
newParams[paramKey] = gl.utils.getParameterValues(paramKey)[0] or ''
|
|
||||||
|
|
||||||
if stateFilters.length
|
|
||||||
stateFilters.find('a').each ->
|
|
||||||
initialUrl = gl.utils.removeParamQueryString($(this).attr('href'), 'label_name[]')
|
|
||||||
labelNameValues = gl.utils.getParameterValues('label_name[]')
|
|
||||||
if labelNameValues
|
|
||||||
labelNameQueryString = ("label_name[]=#{value}" for value in labelNameValues).join('&')
|
|
||||||
newUrl = "#{gl.utils.mergeUrlParams(newParams, initialUrl)}&#{labelNameQueryString}"
|
|
||||||
else
|
else
|
||||||
newUrl = gl.utils.mergeUrlParams(newParams, initialUrl)
|
$('#update_issues_ids').val []
|
||||||
$(this).attr 'href', newUrl
|
$('.issues_bulk_update').hide()
|
||||||
|
$('.issues-other-filters').show()
|
||||||
|
|
|
@ -19,6 +19,16 @@ class @IssuableForm
|
||||||
@form.on "click", ".btn-cancel", @resetAutosave
|
@form.on "click", ".btn-cancel", @resetAutosave
|
||||||
|
|
||||||
@initWip()
|
@initWip()
|
||||||
|
@initMoveDropdown()
|
||||||
|
|
||||||
|
$issuableDueDate = $('#issuable-due-date')
|
||||||
|
|
||||||
|
if $issuableDueDate.length
|
||||||
|
$('.datepicker').datepicker(
|
||||||
|
dateFormat: 'yy-mm-dd',
|
||||||
|
onSelect: (dateText, inst) ->
|
||||||
|
$issuableDueDate.val dateText
|
||||||
|
).datepicker 'setDate', $.datepicker.parseDate('yy-mm-dd', $issuableDueDate.val())
|
||||||
|
|
||||||
initAutosave: ->
|
initAutosave: ->
|
||||||
new Autosave @titleField, [
|
new Autosave @titleField, [
|
||||||
|
@ -80,3 +90,23 @@ class @IssuableForm
|
||||||
|
|
||||||
addWip: ->
|
addWip: ->
|
||||||
@titleField.val "WIP: #{@titleField.val()}"
|
@titleField.val "WIP: #{@titleField.val()}"
|
||||||
|
|
||||||
|
initMoveDropdown: ->
|
||||||
|
$moveDropdown = $('.js-move-dropdown')
|
||||||
|
|
||||||
|
if $moveDropdown.length
|
||||||
|
$('.js-move-dropdown').select2
|
||||||
|
ajax:
|
||||||
|
url: $moveDropdown.data('projects-url')
|
||||||
|
results: (data) ->
|
||||||
|
return {
|
||||||
|
results: data
|
||||||
|
}
|
||||||
|
data: (query) ->
|
||||||
|
{
|
||||||
|
search: query
|
||||||
|
}
|
||||||
|
formatResult: (project) ->
|
||||||
|
project.name_with_namespace
|
||||||
|
formatSelection: (project) ->
|
||||||
|
project.name_with_namespace
|
||||||
|
|
121
app/assets/javascripts/issues-bulk-assignment.js.coffee
Normal file
121
app/assets/javascripts/issues-bulk-assignment.js.coffee
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
class @IssuableBulkActions
|
||||||
|
constructor: (opts = {}) ->
|
||||||
|
# Set defaults
|
||||||
|
{
|
||||||
|
@container = $('.content')
|
||||||
|
@form = @getElement('.bulk-update')
|
||||||
|
@issues = @getElement('.issues-list .issue')
|
||||||
|
} = opts
|
||||||
|
|
||||||
|
@bindEvents()
|
||||||
|
|
||||||
|
# Fixes bulk-assign not working when navigating through pages
|
||||||
|
Issuable.initChecks();
|
||||||
|
|
||||||
|
getElement: (selector) ->
|
||||||
|
@container.find selector
|
||||||
|
|
||||||
|
bindEvents: ->
|
||||||
|
@form.off('submit').on('submit', @onFormSubmit.bind(@))
|
||||||
|
|
||||||
|
onFormSubmit: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
@submit()
|
||||||
|
|
||||||
|
submit: ->
|
||||||
|
_this = @
|
||||||
|
|
||||||
|
xhr = $.ajax
|
||||||
|
url: @form.attr 'action'
|
||||||
|
method: @form.attr 'method'
|
||||||
|
dataType: 'JSON',
|
||||||
|
data: @getFormDataAsObject()
|
||||||
|
|
||||||
|
xhr.done (response, status, xhr) ->
|
||||||
|
location.reload()
|
||||||
|
|
||||||
|
xhr.fail ->
|
||||||
|
new Flash("Issue update failed")
|
||||||
|
|
||||||
|
xhr.always @onFormSubmitAlways.bind(@)
|
||||||
|
|
||||||
|
onFormSubmitAlways: ->
|
||||||
|
@form.find('[type="submit"]').enable()
|
||||||
|
|
||||||
|
getSelectedIssues: ->
|
||||||
|
@issues.has('.selected_issue:checked')
|
||||||
|
|
||||||
|
getLabelsFromSelection: ->
|
||||||
|
labels = []
|
||||||
|
|
||||||
|
@getSelectedIssues().map ->
|
||||||
|
_labels = $(@).data('labels')
|
||||||
|
if _labels
|
||||||
|
_labels.map (labelId) ->
|
||||||
|
labels.push(labelId) if labels.indexOf(labelId) is -1
|
||||||
|
|
||||||
|
labels
|
||||||
|
|
||||||
|
###*
|
||||||
|
* Will return only labels that were marked previously and the user has unmarked
|
||||||
|
* @return {Array} Label IDs
|
||||||
|
###
|
||||||
|
getUnmarkedIndeterminedLabels: ->
|
||||||
|
result = []
|
||||||
|
labelsToKeep = []
|
||||||
|
|
||||||
|
for el in @getElement('.labels-filter .is-indeterminate')
|
||||||
|
labelsToKeep.push $(el).data('labelId')
|
||||||
|
|
||||||
|
for id in @getLabelsFromSelection()
|
||||||
|
# Only the ones that we are not going to keep
|
||||||
|
result.push(id) if labelsToKeep.indexOf(id) is -1
|
||||||
|
|
||||||
|
result
|
||||||
|
|
||||||
|
###*
|
||||||
|
* Simple form serialization, it will return just what we need
|
||||||
|
* Returns key/value pairs from form data
|
||||||
|
###
|
||||||
|
getFormDataAsObject: ->
|
||||||
|
formData =
|
||||||
|
update:
|
||||||
|
state_event : @form.find('input[name="update[state_event]"]').val()
|
||||||
|
assignee_id : @form.find('input[name="update[assignee_id]"]').val()
|
||||||
|
milestone_id : @form.find('input[name="update[milestone_id]"]').val()
|
||||||
|
issues_ids : @form.find('input[name="update[issues_ids]"]').val()
|
||||||
|
add_label_ids : []
|
||||||
|
remove_label_ids : []
|
||||||
|
|
||||||
|
@getLabelsToApply().map (id) ->
|
||||||
|
formData.update.add_label_ids.push id
|
||||||
|
|
||||||
|
@getLabelsToRemove().map (id) ->
|
||||||
|
formData.update.remove_label_ids.push id
|
||||||
|
|
||||||
|
formData
|
||||||
|
|
||||||
|
getLabelsToApply: ->
|
||||||
|
labelIds = []
|
||||||
|
$labels = @form.find('.labels-filter input[name="update[label_ids][]"]')
|
||||||
|
|
||||||
|
$labels.each (k, label) ->
|
||||||
|
labelIds.push parseInt($(label).val()) if label
|
||||||
|
|
||||||
|
labelIds
|
||||||
|
|
||||||
|
###*
|
||||||
|
* Returns Label IDs that will be removed from issue selection
|
||||||
|
* @return {Array} Array of labels IDs
|
||||||
|
###
|
||||||
|
getLabelsToRemove: ->
|
||||||
|
result = []
|
||||||
|
indeterminatedLabels = @getUnmarkedIndeterminedLabels()
|
||||||
|
labelsToApply = @getLabelsToApply()
|
||||||
|
|
||||||
|
indeterminatedLabels.map (id) ->
|
||||||
|
# We need to exclude label IDs that will be applied
|
||||||
|
# By not doing this will cause issues from selection to not add labels at all
|
||||||
|
result.push(id) if labelsToApply.indexOf(id) is -1
|
||||||
|
|
||||||
|
result
|
|
@ -1,38 +0,0 @@
|
||||||
@Issues =
|
|
||||||
init: ->
|
|
||||||
Issues.created = true
|
|
||||||
Issues.initChecks()
|
|
||||||
|
|
||||||
$("body").on "ajax:success", ".close_issue, .reopen_issue", ->
|
|
||||||
t = $(this)
|
|
||||||
totalIssues = undefined
|
|
||||||
reopen = t.hasClass("reopen_issue")
|
|
||||||
$(".issue_counter").each ->
|
|
||||||
issue = $(this)
|
|
||||||
totalIssues = parseInt($(this).html(), 10)
|
|
||||||
if reopen and issue.closest(".main_menu").length
|
|
||||||
$(this).html totalIssues + 1
|
|
||||||
else
|
|
||||||
$(this).html totalIssues - 1
|
|
||||||
|
|
||||||
initChecks: ->
|
|
||||||
$(".check_all_issues").click ->
|
|
||||||
$(".selected_issue").prop("checked", @checked)
|
|
||||||
Issues.checkChanged()
|
|
||||||
|
|
||||||
$(".selected_issue").bind "change", Issues.checkChanged
|
|
||||||
|
|
||||||
checkChanged: ->
|
|
||||||
checked_issues = $(".selected_issue:checked")
|
|
||||||
if checked_issues.length > 0
|
|
||||||
ids = []
|
|
||||||
$.each checked_issues, (index, value) ->
|
|
||||||
ids.push $(value).attr("data-id")
|
|
||||||
|
|
||||||
$("#update_issues_ids").val ids
|
|
||||||
$(".issues-other-filters").hide()
|
|
||||||
$(".issues_bulk_update").show()
|
|
||||||
else
|
|
||||||
$("#update_issues_ids").val []
|
|
||||||
$(".issues_bulk_update").hide()
|
|
||||||
$(".issues-other-filters").show()
|
|
|
@ -1,5 +1,7 @@
|
||||||
class @LabelsSelect
|
class @LabelsSelect
|
||||||
constructor: ->
|
constructor: ->
|
||||||
|
_this = @
|
||||||
|
|
||||||
$('.js-label-select').each (i, dropdown) ->
|
$('.js-label-select').each (i, dropdown) ->
|
||||||
$dropdown = $(dropdown)
|
$dropdown = $(dropdown)
|
||||||
projectId = $dropdown.data('project-id')
|
projectId = $dropdown.data('project-id')
|
||||||
|
@ -93,8 +95,11 @@ class @LabelsSelect
|
||||||
$newLabelCreateButton.enable()
|
$newLabelCreateButton.enable()
|
||||||
|
|
||||||
if label.message?
|
if label.message?
|
||||||
|
errors = _.map label.message, (value, key) ->
|
||||||
|
"#{key} #{value[0]}"
|
||||||
|
|
||||||
$newLabelError
|
$newLabelError
|
||||||
.text label.message
|
.html errors.join("<br/>")
|
||||||
.show()
|
.show()
|
||||||
else
|
else
|
||||||
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
|
$('.dropdown-menu-back', $dropdown.parent()).trigger 'click'
|
||||||
|
@ -196,10 +201,18 @@ class @LabelsSelect
|
||||||
|
|
||||||
callback data
|
callback data
|
||||||
|
|
||||||
renderRow: (label) ->
|
renderRow: (label, instance) ->
|
||||||
removesAll = label.id is 0 or not label.id?
|
$li = $('<li>')
|
||||||
|
$a = $('<a href="#">')
|
||||||
|
|
||||||
selectedClass = []
|
selectedClass = []
|
||||||
|
removesAll = label.id is 0 or not label.id?
|
||||||
|
|
||||||
|
if $dropdown.hasClass('js-filter-bulk-update')
|
||||||
|
indeterminate = instance.indeterminateIds
|
||||||
|
if indeterminate.indexOf(label.id) isnt -1
|
||||||
|
selectedClass.push 'is-indeterminate'
|
||||||
|
|
||||||
if $form.find("input[type='hidden']\
|
if $form.find("input[type='hidden']\
|
||||||
[name='#{$dropdown.data('fieldName')}']\
|
[name='#{$dropdown.data('fieldName')}']\
|
||||||
[value='#{this.id(label)}']").length
|
[value='#{this.id(label)}']").length
|
||||||
|
@ -230,17 +243,21 @@ class @LabelsSelect
|
||||||
else
|
else
|
||||||
colorEl = ''
|
colorEl = ''
|
||||||
|
|
||||||
"<li>
|
# We need to identify which items are actually labels
|
||||||
<a href='#' class='#{selectedClass.join(' ')}'>
|
if label.id
|
||||||
#{colorEl}
|
selectedClass.push('label-item')
|
||||||
#{_.escape(label.title)}
|
$a.attr('data-label-id', label.id)
|
||||||
</a>
|
|
||||||
</li>"
|
$a.addClass(selectedClass.join(' '))
|
||||||
filterable: true
|
.html("#{colorEl} #{_.escape(label.title)}")
|
||||||
|
|
||||||
|
# Return generated html
|
||||||
|
$li.html($a).prop('outerHTML')
|
||||||
|
persistWhenHide: $dropdown.data('persistWhenHide')
|
||||||
search:
|
search:
|
||||||
fields: ['title']
|
fields: ['title']
|
||||||
selectable: true
|
selectable: true
|
||||||
|
filterable: true
|
||||||
toggleLabel: (selected, el) ->
|
toggleLabel: (selected, el) ->
|
||||||
selected_labels = $('.js-label-select').siblings('.dropdown-menu-labels').find('.is-active')
|
selected_labels = $('.js-label-select').siblings('.dropdown-menu-labels').find('.is-active')
|
||||||
|
|
||||||
|
@ -280,10 +297,19 @@ class @LabelsSelect
|
||||||
else if $dropdown.hasClass('js-filter-submit')
|
else if $dropdown.hasClass('js-filter-submit')
|
||||||
$dropdown.closest('form').submit()
|
$dropdown.closest('form').submit()
|
||||||
else
|
else
|
||||||
|
if not $dropdown.hasClass 'js-filter-bulk-update'
|
||||||
saveLabelData()
|
saveLabelData()
|
||||||
|
|
||||||
|
if $dropdown.hasClass('js-filter-bulk-update')
|
||||||
|
# If we are persisting state we need the classes
|
||||||
|
if not @options.persistWhenHide
|
||||||
|
$dropdown.parent().find('.is-active, .is-indeterminate').removeClass()
|
||||||
|
|
||||||
multiSelect: $dropdown.hasClass 'js-multiselect'
|
multiSelect: $dropdown.hasClass 'js-multiselect'
|
||||||
clicked: (label) ->
|
clicked: (label) ->
|
||||||
|
if $dropdown.hasClass('js-filter-bulk-update')
|
||||||
|
return
|
||||||
|
|
||||||
page = $('body').data 'page'
|
page = $('body').data 'page'
|
||||||
isIssueIndex = page is 'projects:issues:index'
|
isIssueIndex = page is 'projects:issues:index'
|
||||||
isMRIndex = page is 'projects:merge_requests:index'
|
isMRIndex = page is 'projects:merge_requests:index'
|
||||||
|
@ -298,4 +324,31 @@ class @LabelsSelect
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
saveLabelData()
|
saveLabelData()
|
||||||
|
|
||||||
|
setIndeterminateIds: ->
|
||||||
|
if @dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')
|
||||||
|
@indeterminateIds = _this.getIndeterminateIds()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@bindEvents()
|
||||||
|
|
||||||
|
bindEvents: ->
|
||||||
|
$('body').on 'change', '.selected_issue', @onSelectCheckboxIssue
|
||||||
|
|
||||||
|
onSelectCheckboxIssue: ->
|
||||||
|
return if $('.selected_issue:checked').length
|
||||||
|
|
||||||
|
# Remove inputs
|
||||||
|
$('.issues_bulk_update .labels-filter input[type="hidden"]').remove()
|
||||||
|
|
||||||
|
# Also restore button text
|
||||||
|
$('.issues_bulk_update .labels-filter .dropdown-toggle-text').text('Label')
|
||||||
|
|
||||||
|
getIndeterminateIds: ->
|
||||||
|
label_ids = []
|
||||||
|
|
||||||
|
$('.selected_issue:checked').each (i, el) ->
|
||||||
|
issue_id = $(el).data('id')
|
||||||
|
label_ids.push $("#issue_#{issue_id}").data('labels')
|
||||||
|
|
||||||
|
_.flatten(label_ids)
|
||||||
|
|
25
app/assets/javascripts/layout_nav.js.coffee
Normal file
25
app/assets/javascripts/layout_nav.js.coffee
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
hideEndFade = ($scrollingTabs) ->
|
||||||
|
$scrollingTabs.each ->
|
||||||
|
$this = $(@)
|
||||||
|
|
||||||
|
$this
|
||||||
|
.find('.fade-right')
|
||||||
|
.toggleClass('end-scroll', $this.width() is $this.prop('scrollWidth'))
|
||||||
|
|
||||||
|
$ ->
|
||||||
|
$('.fade-left').addClass('end-scroll')
|
||||||
|
|
||||||
|
hideEndFade($('.scrolling-tabs'))
|
||||||
|
|
||||||
|
$(window)
|
||||||
|
.off 'resize.nav'
|
||||||
|
.on 'resize.nav', ->
|
||||||
|
hideEndFade($('.scrolling-tabs'))
|
||||||
|
|
||||||
|
$('.scrolling-tabs').on 'scroll', (event) ->
|
||||||
|
$this = $(this)
|
||||||
|
currentPosition = $this.scrollLeft()
|
||||||
|
maxPosition = $this.prop('scrollWidth') - $this.outerWidth()
|
||||||
|
|
||||||
|
$this.find('.fade-left').toggleClass('end-scroll', currentPosition is 0)
|
||||||
|
$this.find('.fade-right').toggleClass('end-scroll', currentPosition is maxPosition)
|
43
app/assets/javascripts/lib/common_utils.js.coffee
Normal file
43
app/assets/javascripts/lib/common_utils.js.coffee
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
((w) ->
|
||||||
|
|
||||||
|
window.gl or= {}
|
||||||
|
window.gl.utils or= {}
|
||||||
|
|
||||||
|
jQuery.timefor = (time, suffix, expiredLabel) ->
|
||||||
|
|
||||||
|
return '' unless time
|
||||||
|
|
||||||
|
suffix or= 'remaining'
|
||||||
|
expiredLabel or= 'Past due'
|
||||||
|
|
||||||
|
jQuery.timeago.settings.allowFuture = yes
|
||||||
|
|
||||||
|
{ suffixFromNow } = jQuery.timeago.settings.strings
|
||||||
|
jQuery.timeago.settings.strings.suffixFromNow = suffix
|
||||||
|
|
||||||
|
timefor = $.timeago time
|
||||||
|
|
||||||
|
if timefor.indexOf('ago') > -1
|
||||||
|
timefor = expiredLabel
|
||||||
|
|
||||||
|
jQuery.timeago.settings.strings.suffixFromNow = suffixFromNow
|
||||||
|
|
||||||
|
return timefor
|
||||||
|
|
||||||
|
|
||||||
|
gl.utils.updateTooltipTitle = ($tooltipEl, newTitle) ->
|
||||||
|
|
||||||
|
$tooltipEl
|
||||||
|
.tooltip 'destroy'
|
||||||
|
.attr 'title', newTitle
|
||||||
|
.tooltip 'fixTitle'
|
||||||
|
|
||||||
|
gl.utils.preventDisabledButtons = ->
|
||||||
|
|
||||||
|
$('.btn').click (e) ->
|
||||||
|
if $(this).hasClass 'disabled'
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopImmediatePropagation()
|
||||||
|
return false
|
||||||
|
|
||||||
|
) window
|
|
@ -12,6 +12,13 @@
|
||||||
$el.attr('title', gl.utils.formatDate($el.attr('datetime')))
|
$el.attr('title', gl.utils.formatDate($el.attr('datetime')))
|
||||||
)
|
)
|
||||||
|
|
||||||
$timeagoEls.timeago() if setTimeago
|
if setTimeago
|
||||||
|
$timeagoEls.timeago()
|
||||||
|
$timeagoEls.tooltip('destroy')
|
||||||
|
|
||||||
|
# Recreate with custom template
|
||||||
|
$timeagoEls.tooltip(
|
||||||
|
template: '<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
|
||||||
|
)
|
||||||
|
|
||||||
) window
|
) window
|
||||||
|
|
2
app/assets/javascripts/lib/emoji_aliases.js.coffee.erb
Normal file
2
app/assets/javascripts/lib/emoji_aliases.js.coffee.erb
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
gl.emojiAliases = ->
|
||||||
|
JSON.parse('<%= Gitlab::AwardEmoji.aliases.to_json %>')
|
|
@ -26,10 +26,19 @@
|
||||||
newUrl = decodeURIComponent(url)
|
newUrl = decodeURIComponent(url)
|
||||||
for paramName, paramValue of params
|
for paramName, paramValue of params
|
||||||
pattern = new RegExp "\\b(#{paramName}=).*?(&|$)"
|
pattern = new RegExp "\\b(#{paramName}=).*?(&|$)"
|
||||||
if url.search(pattern) >= 0
|
if not paramValue?
|
||||||
|
newUrl = newUrl.replace pattern, ''
|
||||||
|
else if url.search(pattern) isnt -1
|
||||||
newUrl = newUrl.replace pattern, "$1#{paramValue}$2"
|
newUrl = newUrl.replace pattern, "$1#{paramValue}$2"
|
||||||
else
|
else
|
||||||
newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
|
newUrl = "#{newUrl}#{(if newUrl.indexOf('?') > 0 then '&' else '?')}#{paramName}=#{paramValue}"
|
||||||
|
|
||||||
|
# Remove a trailing ampersand
|
||||||
|
lastChar = newUrl[newUrl.length - 1]
|
||||||
|
|
||||||
|
if lastChar is '&'
|
||||||
|
newUrl = newUrl.slice 0, -1
|
||||||
|
|
||||||
newUrl
|
newUrl
|
||||||
|
|
||||||
# removes parameter query string from url. returns the modified url
|
# removes parameter query string from url. returns the modified url
|
||||||
|
|
|
@ -42,9 +42,3 @@ work = ->
|
||||||
|
|
||||||
$(document).on('page:fetch', start)
|
$(document).on('page:fetch', start)
|
||||||
$(document).on('page:change', stop)
|
$(document).on('page:change', stop)
|
||||||
|
|
||||||
$ ->
|
|
||||||
# Make logo clickable as part of a workaround for Safari visited
|
|
||||||
# link behaviour (See !2690).
|
|
||||||
$('#logo').on 'click', ->
|
|
||||||
$('#js-shortcuts-home').get(0).click()
|
|
||||||
|
|
|
@ -75,6 +75,9 @@ class @MergeRequestTabs
|
||||||
@loadDiff($target.attr('href'))
|
@loadDiff($target.attr('href'))
|
||||||
if bp? and bp.getBreakpointSize() isnt 'lg'
|
if bp? and bp.getBreakpointSize() isnt 'lg'
|
||||||
@shrinkView()
|
@shrinkView()
|
||||||
|
|
||||||
|
navBarHeight = $('.navbar-gitlab').outerHeight()
|
||||||
|
$.scrollTo(".merge-request-details .merge-request-tabs", offset: -navBarHeight)
|
||||||
else if action == 'builds'
|
else if action == 'builds'
|
||||||
@loadBuilds($target.attr('href'))
|
@loadBuilds($target.attr('href'))
|
||||||
@expandView()
|
@expandView()
|
||||||
|
|
|
@ -10,6 +10,7 @@ class @MergeRequestWidget
|
||||||
$('#modal_merge_info').modal(show: false)
|
$('#modal_merge_info').modal(show: false)
|
||||||
@firstCICheck = true
|
@firstCICheck = true
|
||||||
@readyForCICheck = false
|
@readyForCICheck = false
|
||||||
|
@cancel = false
|
||||||
clearInterval @fetchBuildStatusInterval
|
clearInterval @fetchBuildStatusInterval
|
||||||
|
|
||||||
@clearEventListeners()
|
@clearEventListeners()
|
||||||
|
@ -21,10 +22,16 @@ class @MergeRequestWidget
|
||||||
clearEventListeners: ->
|
clearEventListeners: ->
|
||||||
$(document).off 'page:change.merge_request'
|
$(document).off 'page:change.merge_request'
|
||||||
|
|
||||||
|
cancelPolling: ->
|
||||||
|
@cancel = true
|
||||||
|
|
||||||
addEventListeners: ->
|
addEventListeners: ->
|
||||||
|
allowedPages = ['show', 'commits', 'builds', 'changes']
|
||||||
$(document).on 'page:change.merge_request', =>
|
$(document).on 'page:change.merge_request', =>
|
||||||
if $('body').data('page') isnt 'projects:merge_requests:show'
|
page = $('body').data('page').split(':').last()
|
||||||
|
if allowedPages.indexOf(page) < 0
|
||||||
clearInterval @fetchBuildStatusInterval
|
clearInterval @fetchBuildStatusInterval
|
||||||
|
@cancelPolling()
|
||||||
@clearEventListeners()
|
@clearEventListeners()
|
||||||
|
|
||||||
mergeInProgress: (deleteSourceBranch = false)->
|
mergeInProgress: (deleteSourceBranch = false)->
|
||||||
|
@ -67,6 +74,7 @@ class @MergeRequestWidget
|
||||||
$('.ci-widget-fetching').show()
|
$('.ci-widget-fetching').show()
|
||||||
|
|
||||||
$.getJSON @opts.ci_status_url, (data) =>
|
$.getJSON @opts.ci_status_url, (data) =>
|
||||||
|
return if @cancel
|
||||||
@readyForCICheck = true
|
@readyForCICheck = true
|
||||||
|
|
||||||
if data.status is ''
|
if data.status is ''
|
||||||
|
@ -106,6 +114,7 @@ class @MergeRequestWidget
|
||||||
@firstCICheck = false
|
@firstCICheck = false
|
||||||
|
|
||||||
showCIStatus: (state) ->
|
showCIStatus: (state) ->
|
||||||
|
return if not state?
|
||||||
$('.ci_widget').hide()
|
$('.ci_widget').hide()
|
||||||
allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"]
|
allowed_states = ["failed", "canceled", "running", "pending", "success", "skipped", "not_found"]
|
||||||
if state in allowed_states
|
if state in allowed_states
|
||||||
|
@ -126,6 +135,6 @@ class @MergeRequestWidget
|
||||||
$('.ci_widget:visible .ci-coverage').text(text)
|
$('.ci_widget:visible .ci-coverage').text(text)
|
||||||
|
|
||||||
setMergeButtonClass: (css_class) ->
|
setMergeButtonClass: (css_class) ->
|
||||||
$('.js-merge-button')
|
$('.js-merge-button,.accept-action .dropdown-toggle')
|
||||||
.removeClass('btn-danger btn-warning btn-create')
|
.removeClass('btn-danger btn-warning btn-create')
|
||||||
.addClass(css_class)
|
.addClass(css_class)
|
||||||
|
|
30
app/assets/javascripts/merged_buttons.js.coffee
Normal file
30
app/assets/javascripts/merged_buttons.js.coffee
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
class @MergedButtons
|
||||||
|
constructor: ->
|
||||||
|
@$removeBranchWidget = $('.remove_source_branch_widget')
|
||||||
|
@$removeBranchProgress = $('.remove_source_branch_in_progress')
|
||||||
|
@$removeBranchFailed = $('.remove_source_branch_widget.failed')
|
||||||
|
|
||||||
|
@cleanEventListeners()
|
||||||
|
@initEventListeners()
|
||||||
|
|
||||||
|
cleanEventListeners: ->
|
||||||
|
$(document).off 'click', '.remove_source_branch'
|
||||||
|
$(document).off 'ajax:success', '.remove_source_branch'
|
||||||
|
$(document).off 'ajax:error', '.remove_source_branch'
|
||||||
|
|
||||||
|
initEventListeners: ->
|
||||||
|
$(document).on 'click', '.remove_source_branch', @removeSourceBranch
|
||||||
|
$(document).on 'ajax:success', '.remove_source_branch', @removeBranchSuccess
|
||||||
|
$(document).on 'ajax:error', '.remove_source_branch', @removeBranchError
|
||||||
|
|
||||||
|
removeSourceBranch: =>
|
||||||
|
@$removeBranchWidget.hide()
|
||||||
|
@$removeBranchProgress.show()
|
||||||
|
|
||||||
|
removeBranchSuccess: ->
|
||||||
|
location.reload()
|
||||||
|
|
||||||
|
removeBranchError: ->
|
||||||
|
@$removeBranchWidget.hide()
|
||||||
|
@$removeBranchProgress.hide()
|
||||||
|
@$removeBranchFailed.show()
|
|
@ -24,11 +24,21 @@ class @MilestoneSelect
|
||||||
|
|
||||||
if issueUpdateURL
|
if issueUpdateURL
|
||||||
milestoneLinkTemplate = _.template(
|
milestoneLinkTemplate = _.template(
|
||||||
'<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>"><%= _.escape(title) %></a>'
|
'<a href="/<%= namespace %>/<%= path %>/milestones/<%= iid %>">
|
||||||
|
<span class="has-tooltip" data-container="body" title="<%= remaining %>">
|
||||||
|
<%= _.escape(title) %>
|
||||||
|
</span>
|
||||||
|
</a>'
|
||||||
)
|
)
|
||||||
|
|
||||||
milestoneLinkNoneTemplate = '<div class="light">None</div>'
|
milestoneLinkNoneTemplate = '<div class="light">None</div>'
|
||||||
|
|
||||||
|
collapsedSidebarLabelTemplate = _.template(
|
||||||
|
'<span class="has-tooltip" data-container="body" title="<%= remaining %>" data-placement="left">
|
||||||
|
<%= _.escape(title) %>
|
||||||
|
</span>'
|
||||||
|
)
|
||||||
|
|
||||||
$dropdown.glDropdown(
|
$dropdown.glDropdown(
|
||||||
data: (term, callback) ->
|
data: (term, callback) ->
|
||||||
$.ajax(
|
$.ajax(
|
||||||
|
@ -83,7 +93,7 @@ class @MilestoneSelect
|
||||||
$selectbox.hide()
|
$selectbox.hide()
|
||||||
|
|
||||||
# display:block overrides the hide-collapse rule
|
# display:block overrides the hide-collapse rule
|
||||||
$value.removeAttr('style')
|
$value.css('display', '')
|
||||||
clicked: (selected) ->
|
clicked: (selected) ->
|
||||||
page = $('body').data 'page'
|
page = $('body').data 'page'
|
||||||
isIssueIndex = page is 'projects:issues:index'
|
isIssueIndex = page is 'projects:issues:index'
|
||||||
|
@ -106,7 +116,7 @@ class @MilestoneSelect
|
||||||
.val()
|
.val()
|
||||||
data = {}
|
data = {}
|
||||||
data[abilityName] = {}
|
data[abilityName] = {}
|
||||||
data[abilityName].milestone_id = selected
|
data[abilityName].milestone_id = if selected? then selected else null
|
||||||
$loading
|
$loading
|
||||||
.fadeIn()
|
.fadeIn()
|
||||||
$dropdown.trigger('loading.gl.dropdown')
|
$dropdown.trigger('loading.gl.dropdown')
|
||||||
|
@ -118,12 +128,13 @@ class @MilestoneSelect
|
||||||
$dropdown.trigger('loaded.gl.dropdown')
|
$dropdown.trigger('loaded.gl.dropdown')
|
||||||
$loading.fadeOut()
|
$loading.fadeOut()
|
||||||
$selectbox.hide()
|
$selectbox.hide()
|
||||||
$value.removeAttr('style')
|
$value.css('display', '')
|
||||||
if data.milestone?
|
if data.milestone?
|
||||||
data.milestone.namespace = _this.currentProject.namespace
|
data.milestone.namespace = _this.currentProject.namespace
|
||||||
data.milestone.path = _this.currentProject.path
|
data.milestone.path = _this.currentProject.path
|
||||||
|
data.milestone.remaining = $.timefor data.milestone.due_date
|
||||||
$value.html(milestoneLinkTemplate(data.milestone))
|
$value.html(milestoneLinkTemplate(data.milestone))
|
||||||
$sidebarCollapsedValue.find('span').text(data.milestone.title)
|
$sidebarCollapsedValue.find('span').html(collapsedSidebarLabelTemplate(data.milestone))
|
||||||
else
|
else
|
||||||
$value.html(milestoneLinkNoneTemplate)
|
$value.html(milestoneLinkNoneTemplate)
|
||||||
$sidebarCollapsedValue.find('span').text('No')
|
$sidebarCollapsedValue.find('span').text('No')
|
||||||
|
|
|
@ -114,13 +114,15 @@ class @Notes
|
||||||
@refresh()
|
@refresh()
|
||||||
, @pollingInterval
|
, @pollingInterval
|
||||||
|
|
||||||
refresh: ->
|
refresh: =>
|
||||||
return if @refreshing is true
|
|
||||||
refreshing = true
|
|
||||||
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
|
if not document.hidden and document.URL.indexOf(@noteable_url) is 0
|
||||||
@getContent()
|
@getContent()
|
||||||
|
|
||||||
getContent: ->
|
getContent: ->
|
||||||
|
return if @refreshing
|
||||||
|
|
||||||
|
@refreshing = true
|
||||||
|
|
||||||
$.ajax
|
$.ajax
|
||||||
url: @notes_url
|
url: @notes_url
|
||||||
data: "last_fetched_at=" + @last_fetched_at
|
data: "last_fetched_at=" + @last_fetched_at
|
||||||
|
@ -134,7 +136,7 @@ class @Notes
|
||||||
@renderDiscussionNote(note)
|
@renderDiscussionNote(note)
|
||||||
else
|
else
|
||||||
@renderNote(note)
|
@renderNote(note)
|
||||||
always: =>
|
.always () =>
|
||||||
@refreshing = false
|
@refreshing = false
|
||||||
|
|
||||||
###
|
###
|
||||||
|
@ -162,13 +164,14 @@ class @Notes
|
||||||
renderNote: (note) ->
|
renderNote: (note) ->
|
||||||
unless note.valid
|
unless note.valid
|
||||||
if note.award
|
if note.award
|
||||||
flash = new Flash('You have already used this award emoji!', 'alert')
|
flash = new Flash('You have already awarded this emoji!', 'alert')
|
||||||
flash.pinTo('.header-content')
|
flash.pinTo('.header-content')
|
||||||
return
|
return
|
||||||
|
|
||||||
if note.award
|
if note.award
|
||||||
awardsHandler.addAwardToEmojiBar(note.note)
|
votesBlock = $('.js-awards-block').eq 0
|
||||||
awardsHandler.scrollToAwards()
|
gl.awardsHandler.addAwardToEmojiBar votesBlock, note.name
|
||||||
|
gl.awardsHandler.scrollToAwards()
|
||||||
|
|
||||||
# render note if it not present in loaded list
|
# render note if it not present in loaded list
|
||||||
# or skip if rendered
|
# or skip if rendered
|
||||||
|
@ -329,7 +332,7 @@ class @Notes
|
||||||
@renderDiscussionNote(note)
|
@renderDiscussionNote(note)
|
||||||
|
|
||||||
# cleanup after successfully creating a diff/discussion note
|
# cleanup after successfully creating a diff/discussion note
|
||||||
@removeDiscussionNoteForm($("#new-discussion-note-form-#{note.discussion_id}"))
|
@removeDiscussionNoteForm($(xhr.target))
|
||||||
|
|
||||||
###
|
###
|
||||||
Called in response to the edit note form being submitted
|
Called in response to the edit note form being submitted
|
||||||
|
@ -353,8 +356,7 @@ class @Notes
|
||||||
Called in response to clicking the edit note link
|
Called in response to clicking the edit note link
|
||||||
|
|
||||||
Replaces the note text with the note edit form
|
Replaces the note text with the note edit form
|
||||||
Adds a hidden div with the original content of the note to fill the edit note form with
|
Adds a data attribute to the form with the original content of the note for cancellations
|
||||||
if the user cancels
|
|
||||||
###
|
###
|
||||||
showEditForm: (e, scrollTo, myLastNote) ->
|
showEditForm: (e, scrollTo, myLastNote) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -370,6 +372,8 @@ class @Notes
|
||||||
done = ($noteText) ->
|
done = ($noteText) ->
|
||||||
# Neat little trick to put the cursor at the end
|
# Neat little trick to put the cursor at the end
|
||||||
noteTextVal = $noteText.val()
|
noteTextVal = $noteText.val()
|
||||||
|
# Store the original note text in a data attribute to retrieve if a user cancels edit.
|
||||||
|
form.find('form.edit-note').data 'original-note', noteTextVal
|
||||||
$noteText.val('').val(noteTextVal);
|
$noteText.val('').val(noteTextVal);
|
||||||
|
|
||||||
new GLForm form
|
new GLForm form
|
||||||
|
@ -392,14 +396,16 @@ class @Notes
|
||||||
###
|
###
|
||||||
Called in response to clicking the edit note link
|
Called in response to clicking the edit note link
|
||||||
|
|
||||||
Hides edit form
|
Hides edit form and restores the original note text to the editor textarea.
|
||||||
###
|
###
|
||||||
cancelEdit: (e) ->
|
cancelEdit: (e) ->
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
note = $(this).closest(".note")
|
note = $(this).closest(".note")
|
||||||
|
form = note.find(".current-note-edit-form")
|
||||||
note.removeClass "is-editting"
|
note.removeClass "is-editting"
|
||||||
note.find(".current-note-edit-form")
|
form.removeClass("current-note-edit-form")
|
||||||
.removeClass("current-note-edit-form")
|
# Replace markdown textarea text with original note text.
|
||||||
|
form.find(".js-note-text").val(form.find('form.edit-note').data('original-note'))
|
||||||
|
|
||||||
###
|
###
|
||||||
Called in response to deleting a note of any kind.
|
Called in response to deleting a note of any kind.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@Pager =
|
@Pager =
|
||||||
init: (@limit = 0, preload, @disable = false) ->
|
init: (@limit = 0, preload, @disable = false, @callback = $.noop) ->
|
||||||
@loading = $('.loading').first()
|
@loading = $('.loading').first()
|
||||||
|
|
||||||
if preload
|
if preload
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
@loading.hide()
|
@loading.hide()
|
||||||
success: (data) ->
|
success: (data) ->
|
||||||
Pager.append(data.count, data.html)
|
Pager.append(data.count, data.html)
|
||||||
|
Pager.callback()
|
||||||
dataType: "json"
|
dataType: "json"
|
||||||
|
|
||||||
append: (count, html) ->
|
append: (count, html) ->
|
||||||
|
|
|
@ -7,12 +7,17 @@ class @ProjectNew
|
||||||
@toggleSettingsOnclick()
|
@toggleSettingsOnclick()
|
||||||
|
|
||||||
|
|
||||||
toggleSettings: ->
|
toggleSettings: =>
|
||||||
checked = $("#project_builds_enabled").prop("checked")
|
@_showOrHide('#project_builds_enabled', '.builds-feature')
|
||||||
if checked
|
@_showOrHide('#project_merge_requests_enabled', '.merge-requests-feature')
|
||||||
$('.builds-feature').show()
|
|
||||||
else
|
|
||||||
$('.builds-feature').hide()
|
|
||||||
|
|
||||||
toggleSettingsOnclick: ->
|
toggleSettingsOnclick: ->
|
||||||
$("#project_builds_enabled").on 'click', @toggleSettings
|
$('#project_builds_enabled, #project_merge_requests_enabled').on 'click', @toggleSettings
|
||||||
|
|
||||||
|
_showOrHide: (checkElement, container) ->
|
||||||
|
$container = $(container)
|
||||||
|
|
||||||
|
if $(checkElement).prop('checked')
|
||||||
|
$container.show()
|
||||||
|
else
|
||||||
|
$container.hide()
|
||||||
|
|
|
@ -10,6 +10,89 @@ class @Sidebar
|
||||||
$('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading)
|
$('.dropdown').on('loading.gl.dropdown', @sidebarDropdownLoading)
|
||||||
$('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded)
|
$('.dropdown').on('loaded.gl.dropdown', @sidebarDropdownLoaded)
|
||||||
|
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off 'click', '.js-sidebar-toggle'
|
||||||
|
.on 'click', '.js-sidebar-toggle', (e, triggered) ->
|
||||||
|
e.preventDefault()
|
||||||
|
$this = $(this)
|
||||||
|
$thisIcon = $this.find 'i'
|
||||||
|
$allGutterToggleIcons = $('.js-sidebar-toggle i')
|
||||||
|
if $thisIcon.hasClass('fa-angle-double-right')
|
||||||
|
$allGutterToggleIcons
|
||||||
|
.removeClass('fa-angle-double-right')
|
||||||
|
.addClass('fa-angle-double-left')
|
||||||
|
$('aside.right-sidebar')
|
||||||
|
.removeClass('right-sidebar-expanded')
|
||||||
|
.addClass('right-sidebar-collapsed')
|
||||||
|
$('.page-with-sidebar')
|
||||||
|
.removeClass('right-sidebar-expanded')
|
||||||
|
.addClass('right-sidebar-collapsed')
|
||||||
|
else
|
||||||
|
$allGutterToggleIcons
|
||||||
|
.removeClass('fa-angle-double-left')
|
||||||
|
.addClass('fa-angle-double-right')
|
||||||
|
$('aside.right-sidebar')
|
||||||
|
.removeClass('right-sidebar-collapsed')
|
||||||
|
.addClass('right-sidebar-expanded')
|
||||||
|
$('.page-with-sidebar')
|
||||||
|
.removeClass('right-sidebar-collapsed')
|
||||||
|
.addClass('right-sidebar-expanded')
|
||||||
|
if not triggered
|
||||||
|
$.cookie("collapsed_gutter",
|
||||||
|
$('.right-sidebar')
|
||||||
|
.hasClass('right-sidebar-collapsed'), { path: '/' })
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.off 'click', '.js-issuable-todo'
|
||||||
|
.on 'click', '.js-issuable-todo', @toggleTodo
|
||||||
|
|
||||||
|
toggleTodo: (e) =>
|
||||||
|
$this = $(e.currentTarget)
|
||||||
|
$todoLoading = $('.js-issuable-todo-loading')
|
||||||
|
$btnText = $('.js-issuable-todo-text', $this)
|
||||||
|
ajaxType = if $this.attr('data-id') then 'PATCH' else 'POST'
|
||||||
|
ajaxUrlExtra = if $this.attr('data-id') then "/#{$this.attr('data-id')}" else ''
|
||||||
|
|
||||||
|
$.ajax(
|
||||||
|
url: "#{$this.data('url')}#{ajaxUrlExtra}"
|
||||||
|
type: ajaxType
|
||||||
|
dataType: 'json'
|
||||||
|
data:
|
||||||
|
issuable_id: $this.data('issuable')
|
||||||
|
issuable_type: $this.data('issuable-type')
|
||||||
|
beforeSend: =>
|
||||||
|
@beforeTodoSend($this, $todoLoading)
|
||||||
|
).done (data) =>
|
||||||
|
@todoUpdateDone(data, $this, $btnText, $todoLoading)
|
||||||
|
|
||||||
|
beforeTodoSend: ($btn, $todoLoading) ->
|
||||||
|
$btn.disable()
|
||||||
|
$todoLoading.removeClass 'hidden'
|
||||||
|
|
||||||
|
todoUpdateDone: (data, $btn, $btnText, $todoLoading) ->
|
||||||
|
$todoPendingCount = $('.todos-pending-count')
|
||||||
|
$todoPendingCount.text data.count
|
||||||
|
|
||||||
|
$btn.enable()
|
||||||
|
$todoLoading.addClass 'hidden'
|
||||||
|
|
||||||
|
if data.count is 0
|
||||||
|
$todoPendingCount.addClass 'hidden'
|
||||||
|
else
|
||||||
|
$todoPendingCount.removeClass 'hidden'
|
||||||
|
|
||||||
|
if data.todo?
|
||||||
|
$btn
|
||||||
|
.attr 'aria-label', $btn.data('mark-text')
|
||||||
|
.attr 'data-id', data.todo.id
|
||||||
|
$btnText.text $btn.data('mark-text')
|
||||||
|
else
|
||||||
|
$btn
|
||||||
|
.attr 'aria-label', $btn.data('todo-text')
|
||||||
|
.removeAttr 'data-id'
|
||||||
|
$btnText.text $btn.data('todo-text')
|
||||||
|
|
||||||
sidebarDropdownLoading: (e) ->
|
sidebarDropdownLoading: (e) ->
|
||||||
$sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon')
|
$sidebarCollapsedIcon = $(@).closest('.block').find('.sidebar-collapsed-icon')
|
||||||
img = $sidebarCollapsedIcon.find('img')
|
img = $sidebarCollapsedIcon.find('img')
|
||||||
|
@ -76,12 +159,10 @@ class @Sidebar
|
||||||
@triggerOpenSidebar() if not @isOpen()
|
@triggerOpenSidebar() if not @isOpen()
|
||||||
|
|
||||||
if action is 'hide'
|
if action is 'hide'
|
||||||
@triggerOpenSidebar() is @isOpen()
|
@triggerOpenSidebar() if @isOpen()
|
||||||
|
|
||||||
isOpen: ->
|
isOpen: ->
|
||||||
@sidebar.is('.right-sidebar-expanded')
|
@sidebar.is('.right-sidebar-expanded')
|
||||||
|
|
||||||
getBlock: (name) ->
|
getBlock: (name) ->
|
||||||
@sidebar.find(".block.#{name}")
|
@sidebar.find(".block.#{name}")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,7 @@ class @SearchAutocomplete
|
||||||
@dropdown = @wrap.find('.dropdown')
|
@dropdown = @wrap.find('.dropdown')
|
||||||
@dropdownContent = @dropdown.find('.dropdown-content')
|
@dropdownContent = @dropdown.find('.dropdown-content')
|
||||||
|
|
||||||
@locationBadgeEl = @getElement('.search-location-badge')
|
@locationBadgeEl = @getElement('.location-badge')
|
||||||
@locationText = @getElement('.location-text')
|
|
||||||
@scopeInputEl = @getElement('#scope')
|
@scopeInputEl = @getElement('#scope')
|
||||||
@searchInput = @getElement('.search-input')
|
@searchInput = @getElement('.search-input')
|
||||||
@projectInputEl = @getElement('#search_project_id')
|
@projectInputEl = @getElement('#search_project_id')
|
||||||
|
@ -133,7 +132,7 @@ class @SearchAutocomplete
|
||||||
scope: @scopeInputEl.val()
|
scope: @scopeInputEl.val()
|
||||||
|
|
||||||
# Location badge
|
# Location badge
|
||||||
_location: @locationText.text()
|
_location: @locationBadgeEl.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
bindEvents: ->
|
bindEvents: ->
|
||||||
|
@ -143,22 +142,27 @@ class @SearchAutocomplete
|
||||||
@searchInput.on 'click', @onSearchInputClick
|
@searchInput.on 'click', @onSearchInputClick
|
||||||
@searchInput.on 'focus', @onSearchInputFocus
|
@searchInput.on 'focus', @onSearchInputFocus
|
||||||
@clearInput.on 'click', @onClearInputClick
|
@clearInput.on 'click', @onClearInputClick
|
||||||
|
@locationBadgeEl.on 'click', =>
|
||||||
|
@searchInput.focus()
|
||||||
|
|
||||||
onDocumentClick: (e) =>
|
onDocumentClick: (e) =>
|
||||||
# If clicking outside the search box
|
# If clicking outside the search box
|
||||||
# And search input is not focused
|
# And search input is not focused
|
||||||
# And we are not clicking inside a suggestion
|
# And we are not clicking inside a suggestion
|
||||||
if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).parents('ul').length
|
if not $.contains(@dropdown[0], e.target) and @isFocused and not $(e.target).closest('.search-form').length
|
||||||
@onSearchInputBlur()
|
@onSearchInputBlur()
|
||||||
|
|
||||||
enableAutocomplete: ->
|
enableAutocomplete: ->
|
||||||
# No need to enable anything if user is not logged in
|
# No need to enable anything if user is not logged in
|
||||||
return if !gon.current_user_id
|
return if !gon.current_user_id
|
||||||
|
|
||||||
|
unless @dropdown.hasClass('open')
|
||||||
_this = @
|
_this = @
|
||||||
@loadingSuggestions = false
|
@loadingSuggestions = false
|
||||||
|
|
||||||
@dropdown.addClass('open')
|
@dropdown
|
||||||
|
.addClass('open')
|
||||||
|
.trigger('shown.bs.dropdown')
|
||||||
@searchInput.removeClass('disabled')
|
@searchInput.removeClass('disabled')
|
||||||
|
|
||||||
onSearchInputKeyDown: =>
|
onSearchInputKeyDown: =>
|
||||||
|
@ -190,7 +194,7 @@ class @SearchAutocomplete
|
||||||
@disableAutocomplete()
|
@disableAutocomplete()
|
||||||
else
|
else
|
||||||
# We should display the menu only when input is not empty
|
# We should display the menu only when input is not empty
|
||||||
@enableAutocomplete()
|
@enableAutocomplete() if e.keyCode isnt KEYCODE.ENTER
|
||||||
|
|
||||||
@wrap.toggleClass 'has-value', !!e.target.value
|
@wrap.toggleClass 'has-value', !!e.target.value
|
||||||
|
|
||||||
|
@ -221,10 +225,8 @@ class @SearchAutocomplete
|
||||||
category = if item.category? then "#{item.category}: " else ''
|
category = if item.category? then "#{item.category}: " else ''
|
||||||
value = if item.value? then item.value else ''
|
value = if item.value? then item.value else ''
|
||||||
|
|
||||||
html = "<span class='location-badge'>
|
badgeText = "#{category}#{value}"
|
||||||
<i class='location-text'>#{category}#{value}</i>
|
@locationBadgeEl.text(badgeText).show()
|
||||||
</span>"
|
|
||||||
@locationBadgeEl.html(html)
|
|
||||||
@wrap.addClass('has-location-badge')
|
@wrap.addClass('has-location-badge')
|
||||||
|
|
||||||
restoreOriginalState: ->
|
restoreOriginalState: ->
|
||||||
|
@ -233,9 +235,8 @@ class @SearchAutocomplete
|
||||||
for input in inputs
|
for input in inputs
|
||||||
@getElement("##{input}").val(@originalState[input])
|
@getElement("##{input}").val(@originalState[input])
|
||||||
|
|
||||||
|
|
||||||
if @originalState._location is ''
|
if @originalState._location is ''
|
||||||
@locationBadgeEl.empty()
|
@locationBadgeEl.hide()
|
||||||
else
|
else
|
||||||
@addLocationBadge(
|
@addLocationBadge(
|
||||||
value: @originalState._location
|
value: @originalState._location
|
||||||
|
@ -244,7 +245,7 @@ class @SearchAutocomplete
|
||||||
@dropdown.removeClass 'open'
|
@dropdown.removeClass 'open'
|
||||||
|
|
||||||
badgePresent: ->
|
badgePresent: ->
|
||||||
@locationBadgeEl.children().length
|
@locationBadgeEl.length
|
||||||
|
|
||||||
resetSearchState: ->
|
resetSearchState: ->
|
||||||
inputs = Object.keys @originalState
|
inputs = Object.keys @originalState
|
||||||
|
@ -257,7 +258,7 @@ class @SearchAutocomplete
|
||||||
@getElement("##{input}").val('')
|
@getElement("##{input}").val('')
|
||||||
|
|
||||||
removeLocationBadge: ->
|
removeLocationBadge: ->
|
||||||
@locationBadgeEl.empty()
|
@locationBadgeEl.hide()
|
||||||
|
|
||||||
# Reset state
|
# Reset state
|
||||||
@resetSearchState()
|
@resetSearchState()
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
class @ShortcutsDashboardNavigation extends Shortcuts
|
class @ShortcutsDashboardNavigation extends Shortcuts
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super()
|
super()
|
||||||
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-activity'))
|
Mousetrap.bind('g a', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-activity'))
|
||||||
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-issues'))
|
Mousetrap.bind('g i', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-issues'))
|
||||||
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-merge_requests'))
|
Mousetrap.bind('g m', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-merge_requests'))
|
||||||
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.shortcuts-projects'))
|
Mousetrap.bind('g p', -> ShortcutsDashboardNavigation.findAndFollowLink('.dashboard-shortcuts-projects'))
|
||||||
|
|
||||||
@findAndFollowLink: (selector) ->
|
@findAndFollowLink: (selector) ->
|
||||||
link = $(selector).attr('href')
|
link = $(selector).attr('href')
|
||||||
|
|
|
@ -10,14 +10,6 @@ class @ShortcutsIssuable extends ShortcutsNavigation
|
||||||
@replyWithSelectedText()
|
@replyWithSelectedText()
|
||||||
return false
|
return false
|
||||||
)
|
)
|
||||||
Mousetrap.bind('j', =>
|
|
||||||
@prevIssue()
|
|
||||||
return false
|
|
||||||
)
|
|
||||||
Mousetrap.bind('k', =>
|
|
||||||
@nextIssue()
|
|
||||||
return false
|
|
||||||
)
|
|
||||||
Mousetrap.bind('e', =>
|
Mousetrap.bind('e', =>
|
||||||
@editIssue()
|
@editIssue()
|
||||||
return false
|
return false
|
||||||
|
@ -29,16 +21,6 @@ class @ShortcutsIssuable extends ShortcutsNavigation
|
||||||
else
|
else
|
||||||
@enabledHelp.push('.hidden-shortcut.issues')
|
@enabledHelp.push('.hidden-shortcut.issues')
|
||||||
|
|
||||||
prevIssue: ->
|
|
||||||
$prevBtn = $('.prev-btn')
|
|
||||||
if not $prevBtn.hasClass('disabled')
|
|
||||||
Turbolinks.visit($prevBtn.attr('href'))
|
|
||||||
|
|
||||||
nextIssue: ->
|
|
||||||
$nextBtn = $('.next-btn')
|
|
||||||
if not $nextBtn.hasClass('disabled')
|
|
||||||
Turbolinks.visit($nextBtn.attr('href'))
|
|
||||||
|
|
||||||
replyWithSelectedText: ->
|
replyWithSelectedText: ->
|
||||||
if window.getSelection
|
if window.getSelection
|
||||||
selected = window.getSelection().toString()
|
selected = window.getSelection().toString()
|
||||||
|
|
|
@ -4,8 +4,6 @@ expanded = 'page-sidebar-expanded'
|
||||||
toggleSidebar = ->
|
toggleSidebar = ->
|
||||||
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
|
$('.page-with-sidebar').toggleClass("#{collapsed} #{expanded}")
|
||||||
$('header').toggleClass("header-collapsed header-expanded")
|
$('header').toggleClass("header-collapsed header-expanded")
|
||||||
$('.toggle-nav-collapse i').toggleClass("fa-angle-right fa-angle-left")
|
|
||||||
$.cookie("collapsed_nav", $('.page-with-sidebar').hasClass(collapsed), { path: '/' })
|
|
||||||
|
|
||||||
setTimeout ( ->
|
setTimeout ( ->
|
||||||
niceScrollBars = $('.nicescroll').niceScroll();
|
niceScrollBars = $('.nicescroll').niceScroll();
|
||||||
|
@ -17,10 +15,3 @@ $(document).on("click", '.toggle-nav-collapse, .side-nav-toggle', (e) ->
|
||||||
|
|
||||||
toggleSidebar()
|
toggleSidebar()
|
||||||
)
|
)
|
||||||
|
|
||||||
$ ->
|
|
||||||
size = bp.getBreakpointSize()
|
|
||||||
|
|
||||||
if size is "xs" or size is "sm"
|
|
||||||
if $('.page-with-sidebar').hasClass(expanded)
|
|
||||||
toggleSidebar()
|
|
||||||
|
|
|
@ -9,9 +9,11 @@ class @Star
|
||||||
$this.parent().find('.star-count').text data.star_count
|
$this.parent().find('.star-count').text data.star_count
|
||||||
if isStarred
|
if isStarred
|
||||||
$starSpan.removeClass('starred').text 'Star'
|
$starSpan.removeClass('starred').text 'Star'
|
||||||
|
gl.utils.updateTooltipTitle $this, 'Star project'
|
||||||
$starIcon.removeClass('fa-star').addClass 'fa-star-o'
|
$starIcon.removeClass('fa-star').addClass 'fa-star-o'
|
||||||
else
|
else
|
||||||
$starSpan.addClass('starred').text 'Unstar'
|
$starSpan.addClass('starred').text 'Unstar'
|
||||||
|
gl.utils.updateTooltipTitle $this, 'Unstar project'
|
||||||
$starIcon.removeClass('fa-star-o').addClass 'fa-star'
|
$starIcon.removeClass('fa-star-o').addClass 'fa-star'
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -19,3 +19,8 @@ class @Subscription
|
||||||
action = if status == 'subscribed' then 'Unsubscribe' else 'Subscribe'
|
action = if status == 'subscribed' then 'Unsubscribe' else 'Subscribe'
|
||||||
btn.find('span').text(action)
|
btn.find('span').text(action)
|
||||||
@subscription_status.find('>div').toggleClass('hidden')
|
@subscription_status.find('>div').toggleClass('hidden')
|
||||||
|
|
||||||
|
if btn.attr('data-original-title')
|
||||||
|
btn.tooltip('hide')
|
||||||
|
.attr('data-original-title', action)
|
||||||
|
.tooltip('fixTitle')
|
||||||
|
|
63
app/assets/javascripts/u2f/authenticate.js.coffee
Normal file
63
app/assets/javascripts/u2f/authenticate.js.coffee
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# Authenticate U2F (universal 2nd factor) devices for users to authenticate with.
|
||||||
|
#
|
||||||
|
# State Flow #1: setup -> in_progress -> authenticated -> POST to server
|
||||||
|
# State Flow #2: setup -> in_progress -> error -> setup
|
||||||
|
|
||||||
|
class @U2FAuthenticate
|
||||||
|
constructor: (@container, u2fParams) ->
|
||||||
|
@appId = u2fParams.app_id
|
||||||
|
@challenges = u2fParams.challenges
|
||||||
|
@signRequests = u2fParams.sign_requests
|
||||||
|
|
||||||
|
start: () =>
|
||||||
|
if U2FUtil.isU2FSupported()
|
||||||
|
@renderSetup()
|
||||||
|
else
|
||||||
|
@renderNotSupported()
|
||||||
|
|
||||||
|
authenticate: () =>
|
||||||
|
u2f.sign(@appId, @challenges, @signRequests, (response) =>
|
||||||
|
if response.errorCode
|
||||||
|
error = new U2FError(response.errorCode)
|
||||||
|
@renderError(error);
|
||||||
|
else
|
||||||
|
@renderAuthenticated(JSON.stringify(response))
|
||||||
|
, 10)
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Rendering #
|
||||||
|
#############
|
||||||
|
|
||||||
|
templates: {
|
||||||
|
"notSupported": "#js-authenticate-u2f-not-supported",
|
||||||
|
"setup": '#js-authenticate-u2f-setup',
|
||||||
|
"inProgress": '#js-authenticate-u2f-in-progress',
|
||||||
|
"error": '#js-authenticate-u2f-error',
|
||||||
|
"authenticated": '#js-authenticate-u2f-authenticated'
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTemplate: (name, params) =>
|
||||||
|
templateString = $(@templates[name]).html()
|
||||||
|
template = _.template(templateString)
|
||||||
|
@container.html(template(params))
|
||||||
|
|
||||||
|
renderSetup: () =>
|
||||||
|
@renderTemplate('setup')
|
||||||
|
@container.find('#js-login-u2f-device').on('click', @renderInProgress)
|
||||||
|
|
||||||
|
renderInProgress: () =>
|
||||||
|
@renderTemplate('inProgress')
|
||||||
|
@authenticate()
|
||||||
|
|
||||||
|
renderError: (error) =>
|
||||||
|
@renderTemplate('error', {error_message: error.message()})
|
||||||
|
@container.find('#js-u2f-try-again').on('click', @renderSetup)
|
||||||
|
|
||||||
|
renderAuthenticated: (deviceResponse) =>
|
||||||
|
@renderTemplate('authenticated')
|
||||||
|
# Prefer to do this instead of interpolating using Underscore templates
|
||||||
|
# because of JSON escaping issues.
|
||||||
|
@container.find("#js-device-response").val(deviceResponse)
|
||||||
|
|
||||||
|
renderNotSupported: () =>
|
||||||
|
@renderTemplate('notSupported')
|
13
app/assets/javascripts/u2f/error.js.coffee
Normal file
13
app/assets/javascripts/u2f/error.js.coffee
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class @U2FError
|
||||||
|
constructor: (@errorCode) ->
|
||||||
|
@httpsDisabled = (window.location.protocol isnt 'https:')
|
||||||
|
console.error("U2F Error Code: #{@errorCode}")
|
||||||
|
|
||||||
|
message: () =>
|
||||||
|
switch
|
||||||
|
when (@errorCode is u2f.ErrorCodes.BAD_REQUEST and @httpsDisabled)
|
||||||
|
"U2F only works with HTTPS-enabled websites. Contact your administrator for more details."
|
||||||
|
when @errorCode is u2f.ErrorCodes.DEVICE_INELIGIBLE
|
||||||
|
"This device has already been registered with us."
|
||||||
|
else
|
||||||
|
"There was a problem communicating with your device."
|
63
app/assets/javascripts/u2f/register.js.coffee
Normal file
63
app/assets/javascripts/u2f/register.js.coffee
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# Register U2F (universal 2nd factor) devices for users to authenticate with.
|
||||||
|
#
|
||||||
|
# State Flow #1: setup -> in_progress -> registered -> POST to server
|
||||||
|
# State Flow #2: setup -> in_progress -> error -> setup
|
||||||
|
|
||||||
|
class @U2FRegister
|
||||||
|
constructor: (@container, u2fParams) ->
|
||||||
|
@appId = u2fParams.app_id
|
||||||
|
@registerRequests = u2fParams.register_requests
|
||||||
|
@signRequests = u2fParams.sign_requests
|
||||||
|
|
||||||
|
start: () =>
|
||||||
|
if U2FUtil.isU2FSupported()
|
||||||
|
@renderSetup()
|
||||||
|
else
|
||||||
|
@renderNotSupported()
|
||||||
|
|
||||||
|
register: () =>
|
||||||
|
u2f.register(@appId, @registerRequests, @signRequests, (response) =>
|
||||||
|
if response.errorCode
|
||||||
|
error = new U2FError(response.errorCode)
|
||||||
|
@renderError(error);
|
||||||
|
else
|
||||||
|
@renderRegistered(JSON.stringify(response))
|
||||||
|
, 10)
|
||||||
|
|
||||||
|
#############
|
||||||
|
# Rendering #
|
||||||
|
#############
|
||||||
|
|
||||||
|
templates: {
|
||||||
|
"notSupported": "#js-register-u2f-not-supported",
|
||||||
|
"setup": '#js-register-u2f-setup',
|
||||||
|
"inProgress": '#js-register-u2f-in-progress',
|
||||||
|
"error": '#js-register-u2f-error',
|
||||||
|
"registered": '#js-register-u2f-registered'
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTemplate: (name, params) =>
|
||||||
|
templateString = $(@templates[name]).html()
|
||||||
|
template = _.template(templateString)
|
||||||
|
@container.html(template(params))
|
||||||
|
|
||||||
|
renderSetup: () =>
|
||||||
|
@renderTemplate('setup')
|
||||||
|
@container.find('#js-setup-u2f-device').on('click', @renderInProgress)
|
||||||
|
|
||||||
|
renderInProgress: () =>
|
||||||
|
@renderTemplate('inProgress')
|
||||||
|
@register()
|
||||||
|
|
||||||
|
renderError: (error) =>
|
||||||
|
@renderTemplate('error', {error_message: error.message()})
|
||||||
|
@container.find('#js-u2f-try-again').on('click', @renderSetup)
|
||||||
|
|
||||||
|
renderRegistered: (deviceResponse) =>
|
||||||
|
@renderTemplate('registered')
|
||||||
|
# Prefer to do this instead of interpolating using Underscore templates
|
||||||
|
# because of JSON escaping issues.
|
||||||
|
@container.find("#js-device-response").val(deviceResponse)
|
||||||
|
|
||||||
|
renderNotSupported: () =>
|
||||||
|
@renderTemplate('notSupported')
|
15
app/assets/javascripts/u2f/util.js.coffee.erb
Normal file
15
app/assets/javascripts/u2f/util.js.coffee.erb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Helper class for U2F (universal 2nd factor) device registration and authentication.
|
||||||
|
|
||||||
|
class @U2FUtil
|
||||||
|
@isU2FSupported: ->
|
||||||
|
if @testMode
|
||||||
|
true
|
||||||
|
else
|
||||||
|
gon.u2f.browser_supports_u2f
|
||||||
|
|
||||||
|
@enableTestMode: ->
|
||||||
|
@testMode = true
|
||||||
|
|
||||||
|
<% if Rails.env.test? %>
|
||||||
|
U2FUtil.enableTestMode();
|
||||||
|
<% end %>
|
|
@ -122,6 +122,9 @@ class @UserTabs
|
||||||
@parentEl.find(tabSelector).html(data.html)
|
@parentEl.find(tabSelector).html(data.html)
|
||||||
@loaded[action] = true
|
@loaded[action] = true
|
||||||
|
|
||||||
|
# Fix tooltips
|
||||||
|
gl.utils.localTimeAgo($('.js-timeago', tabSelector))
|
||||||
|
|
||||||
loadActivities: (source) ->
|
loadActivities: (source) ->
|
||||||
return if @loaded['activity'] is true
|
return if @loaded['activity'] is true
|
||||||
|
|
||||||
|
|
8
app/assets/javascripts/users/application.js.coffee
Normal file
8
app/assets/javascripts/users/application.js.coffee
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# This is a manifest file that'll be compiled into including all the files listed below.
|
||||||
|
# Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
||||||
|
# be included in the compiled file accessible from http://example.com/assets/application.js
|
||||||
|
# It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
||||||
|
# the compiled file.
|
||||||
|
#
|
||||||
|
#= require d3
|
||||||
|
#= require_tree .
|
198
app/assets/javascripts/users/calendar.js.coffee
Normal file
198
app/assets/javascripts/users/calendar.js.coffee
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
class @Calendar
|
||||||
|
constructor: (timestamps, @calendar_activities_path) ->
|
||||||
|
@currentSelectedDate = ''
|
||||||
|
@daySpace = 1
|
||||||
|
@daySize = 15
|
||||||
|
@daySizeWithSpace = @daySize + (@daySpace * 2)
|
||||||
|
@monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||||
|
@months = []
|
||||||
|
@highestValue = 0
|
||||||
|
|
||||||
|
# Get the highest value from the timestampes
|
||||||
|
_.each timestamps, (count) =>
|
||||||
|
if count > @highestValue
|
||||||
|
@highestValue = count
|
||||||
|
|
||||||
|
# Loop through the timestamps to create a group of objects
|
||||||
|
# The group of objects will be grouped based on the day of the week they are
|
||||||
|
@timestampsTmp = []
|
||||||
|
i = 0
|
||||||
|
group = 0
|
||||||
|
_.each timestamps, (count, date) =>
|
||||||
|
newDate = new Date parseInt(date) * 1000
|
||||||
|
day = newDate.getDay()
|
||||||
|
|
||||||
|
# Create a new group array if this is the first day of the week
|
||||||
|
# or if is first object
|
||||||
|
if (day is 0 and i isnt 0) or i is 0
|
||||||
|
@timestampsTmp.push []
|
||||||
|
group++
|
||||||
|
|
||||||
|
innerArray = @timestampsTmp[group-1]
|
||||||
|
|
||||||
|
# Push to the inner array the values that will be used to render map
|
||||||
|
innerArray.push
|
||||||
|
count: count
|
||||||
|
date: newDate
|
||||||
|
day: day
|
||||||
|
|
||||||
|
i++
|
||||||
|
|
||||||
|
# Init color functions
|
||||||
|
@color = @initColor()
|
||||||
|
@colorKey = @initColorKey()
|
||||||
|
|
||||||
|
# Init the svg element
|
||||||
|
@renderSvg(group)
|
||||||
|
@renderDays()
|
||||||
|
@renderMonths()
|
||||||
|
@renderDayTitles()
|
||||||
|
@renderKey()
|
||||||
|
|
||||||
|
@initTooltips()
|
||||||
|
|
||||||
|
renderSvg: (group) ->
|
||||||
|
@svg = d3.select '.js-contrib-calendar'
|
||||||
|
.append 'svg'
|
||||||
|
.attr 'width', (group + 1) * @daySizeWithSpace
|
||||||
|
.attr 'height', 167
|
||||||
|
.attr 'class', 'contrib-calendar'
|
||||||
|
|
||||||
|
renderDays: ->
|
||||||
|
@svg.selectAll 'g'
|
||||||
|
.data @timestampsTmp
|
||||||
|
.enter()
|
||||||
|
.append 'g'
|
||||||
|
.attr 'transform', (group, i) =>
|
||||||
|
_.each group, (stamp, a) =>
|
||||||
|
if a is 0 and stamp.day is 0
|
||||||
|
month = stamp.date.getMonth()
|
||||||
|
x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace
|
||||||
|
lastMonth = _.last(@months)
|
||||||
|
if lastMonth?
|
||||||
|
lastMonthX = lastMonth.x
|
||||||
|
|
||||||
|
if !lastMonth?
|
||||||
|
@months.push
|
||||||
|
month: month
|
||||||
|
x: x
|
||||||
|
else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
|
||||||
|
@months.push
|
||||||
|
month: month
|
||||||
|
x: x
|
||||||
|
|
||||||
|
"translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)"
|
||||||
|
.selectAll 'rect'
|
||||||
|
.data (stamp) ->
|
||||||
|
stamp
|
||||||
|
.enter()
|
||||||
|
.append 'rect'
|
||||||
|
.attr 'x', '0'
|
||||||
|
.attr 'y', (stamp, i) =>
|
||||||
|
(@daySizeWithSpace * stamp.day)
|
||||||
|
.attr 'width', @daySize
|
||||||
|
.attr 'height', @daySize
|
||||||
|
.attr 'title', (stamp) =>
|
||||||
|
contribText = 'No contributions'
|
||||||
|
|
||||||
|
if stamp.count > 0
|
||||||
|
contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"
|
||||||
|
|
||||||
|
date = dateFormat(stamp.date, 'mmm d, yyyy')
|
||||||
|
|
||||||
|
"#{contribText}<br />#{date}"
|
||||||
|
.attr 'class', 'user-contrib-cell js-tooltip'
|
||||||
|
.attr 'fill', (stamp) =>
|
||||||
|
if stamp.count isnt 0
|
||||||
|
@color(stamp.count)
|
||||||
|
else
|
||||||
|
'#ededed'
|
||||||
|
.attr 'data-container', 'body'
|
||||||
|
.on 'click', @clickDay
|
||||||
|
|
||||||
|
renderDayTitles: ->
|
||||||
|
days = [{
|
||||||
|
text: 'M'
|
||||||
|
y: 29 + (@daySizeWithSpace * 1)
|
||||||
|
}, {
|
||||||
|
text: 'W'
|
||||||
|
y: 29 + (@daySizeWithSpace * 3)
|
||||||
|
}, {
|
||||||
|
text: 'F'
|
||||||
|
y: 29 + (@daySizeWithSpace * 5)
|
||||||
|
}]
|
||||||
|
@svg.append 'g'
|
||||||
|
.selectAll 'text'
|
||||||
|
.data days
|
||||||
|
.enter()
|
||||||
|
.append 'text'
|
||||||
|
.attr 'text-anchor', 'middle'
|
||||||
|
.attr 'x', 8
|
||||||
|
.attr 'y', (day) ->
|
||||||
|
day.y
|
||||||
|
.text (day) ->
|
||||||
|
day.text
|
||||||
|
.attr 'class', 'user-contrib-text'
|
||||||
|
|
||||||
|
renderMonths: ->
|
||||||
|
@svg.append 'g'
|
||||||
|
.selectAll 'text'
|
||||||
|
.data @months
|
||||||
|
.enter()
|
||||||
|
.append 'text'
|
||||||
|
.attr 'x', (date) ->
|
||||||
|
date.x
|
||||||
|
.attr 'y', 10
|
||||||
|
.attr 'class', 'user-contrib-text'
|
||||||
|
.text (date) =>
|
||||||
|
@monthNames[date.month]
|
||||||
|
|
||||||
|
renderKey: ->
|
||||||
|
keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
|
||||||
|
@svg.append 'g'
|
||||||
|
.attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})"
|
||||||
|
.selectAll 'rect'
|
||||||
|
.data keyColors
|
||||||
|
.enter()
|
||||||
|
.append 'rect'
|
||||||
|
.attr 'width', @daySize
|
||||||
|
.attr 'height', @daySize
|
||||||
|
.attr 'x', (color, i) =>
|
||||||
|
@daySizeWithSpace * i
|
||||||
|
.attr 'y', 0
|
||||||
|
.attr 'fill', (color) ->
|
||||||
|
color
|
||||||
|
|
||||||
|
initColor: ->
|
||||||
|
d3.scale
|
||||||
|
.linear()
|
||||||
|
.range(['#acd5f2', '#254e77'])
|
||||||
|
.domain([0, @highestValue])
|
||||||
|
|
||||||
|
initColorKey: ->
|
||||||
|
d3.scale
|
||||||
|
.linear()
|
||||||
|
.range(['#acd5f2', '#254e77'])
|
||||||
|
.domain([0, 3])
|
||||||
|
|
||||||
|
clickDay: (stamp) =>
|
||||||
|
if @currentSelectedDate isnt stamp.date
|
||||||
|
@currentSelectedDate = stamp.date
|
||||||
|
formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate()
|
||||||
|
|
||||||
|
$.ajax
|
||||||
|
url: @calendar_activities_path
|
||||||
|
data:
|
||||||
|
date: formatted_date
|
||||||
|
cache: false
|
||||||
|
dataType: 'html'
|
||||||
|
beforeSend: ->
|
||||||
|
$('.user-calendar-activities').html '<div class="text-center"><i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i></div>'
|
||||||
|
success: (data) ->
|
||||||
|
$('.user-calendar-activities').html data
|
||||||
|
else
|
||||||
|
$('.user-calendar-activities').html ''
|
||||||
|
|
||||||
|
initTooltips: ->
|
||||||
|
$('.js-contrib-calendar .js-tooltip').tooltip
|
||||||
|
html: true
|
|
@ -31,7 +31,7 @@ class @UsersSelect
|
||||||
assignTo = (selected) ->
|
assignTo = (selected) ->
|
||||||
data = {}
|
data = {}
|
||||||
data[abilityName] = {}
|
data[abilityName] = {}
|
||||||
data[abilityName].assignee_id = selected
|
data[abilityName].assignee_id = if selected? then selected else null
|
||||||
$loading
|
$loading
|
||||||
.fadeIn()
|
.fadeIn()
|
||||||
$dropdown.trigger('loading.gl.dropdown')
|
$dropdown.trigger('loading.gl.dropdown')
|
||||||
|
@ -93,6 +93,8 @@ class @UsersSelect
|
||||||
|
|
||||||
$dropdown.glDropdown(
|
$dropdown.glDropdown(
|
||||||
data: (term, callback) =>
|
data: (term, callback) =>
|
||||||
|
isAuthorFilter = $('.js-author-search')
|
||||||
|
|
||||||
@users term, (users) =>
|
@users term, (users) =>
|
||||||
if term.length is 0
|
if term.length is 0
|
||||||
showDivider = 0
|
showDivider = 0
|
||||||
|
@ -138,7 +140,7 @@ class @UsersSelect
|
||||||
|
|
||||||
toggleLabel: (selected) ->
|
toggleLabel: (selected) ->
|
||||||
if selected && 'id' of selected
|
if selected && 'id' of selected
|
||||||
selected.name
|
if selected.text then selected.text else selected.name
|
||||||
else
|
else
|
||||||
defaultLabel
|
defaultLabel
|
||||||
|
|
||||||
|
@ -147,7 +149,7 @@ class @UsersSelect
|
||||||
hidden: (e) ->
|
hidden: (e) ->
|
||||||
$selectbox.hide()
|
$selectbox.hide()
|
||||||
# display:block overrides the hide-collapse rule
|
# display:block overrides the hide-collapse rule
|
||||||
$value.removeAttr('style')
|
$value.css('display', '')
|
||||||
|
|
||||||
clicked: (user) ->
|
clicked: (user) ->
|
||||||
page = $('body').data 'page'
|
page = $('body').data 'page'
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
*= require select2
|
*= require select2
|
||||||
*= require_self
|
*= require_self
|
||||||
*= require dropzone/basic
|
*= require dropzone/basic
|
||||||
*= require cal-heatmap
|
|
||||||
*= require cropper.css
|
*= require cropper.css
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
&.s32 { font-size: 20px; line-height: 32px; }
|
&.s32 { font-size: 20px; line-height: 32px; }
|
||||||
&.s40 { font-size: 16px; line-height: 40px; }
|
&.s40 { font-size: 16px; line-height: 40px; }
|
||||||
&.s60 { font-size: 32px; line-height: 60px; }
|
&.s60 { font-size: 32px; line-height: 60px; }
|
||||||
|
&.s70 { font-size: 34px; line-height: 70px; }
|
||||||
&.s90 { font-size: 36px; line-height: 90px; }
|
&.s90 { font-size: 36px; line-height: 90px; }
|
||||||
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
|
&.s110 { font-size: 40px; line-height: 112px; font-weight: 300; }
|
||||||
&.s140 { font-size: 72px; line-height: 140px; }
|
&.s140 { font-size: 72px; line-height: 140px; }
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
background-color: $background-color;
|
background-color: $background-color;
|
||||||
padding: $gl-padding;
|
padding: $gl-padding;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
border-top: 1px solid $border-color;
|
border-top: 1px solid $white-dark;
|
||||||
border-bottom: 1px solid $border-color;
|
border-bottom: 1px solid $white-dark;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
|
|
||||||
&.oneline-block {
|
&.oneline-block {
|
||||||
|
@ -61,6 +61,11 @@
|
||||||
margin-bottom: -$gl-padding;
|
margin-bottom: -$gl-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.content-component-block {
|
||||||
|
padding: 11px 0;
|
||||||
|
background-color: $white-light;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
}
|
}
|
||||||
|
@ -110,9 +115,9 @@
|
||||||
.cover-title {
|
.cover-title {
|
||||||
color: $gl-header-color;
|
color: $gl-header-color;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 23px;
|
font-size: 24px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin: 16px 0 5px;
|
margin-bottom: 5px;
|
||||||
color: #4c4e54;
|
color: #4c4e54;
|
||||||
font-size: 23px;
|
font-size: 23px;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
|
@ -137,7 +142,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.cover-desc {
|
.cover-desc {
|
||||||
padding: 0 $gl-padding 3px;
|
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
|
|
||||||
&.username:last-child {
|
&.username:last-child {
|
||||||
|
@ -205,7 +209,7 @@
|
||||||
|
|
||||||
.content-block {
|
.content-block {
|
||||||
padding: $gl-padding 0;
|
padding: $gl-padding 0;
|
||||||
border-bottom: 1px solid $border-color;
|
border-bottom: 1px solid $white-dark;
|
||||||
|
|
||||||
&.oneline-block {
|
&.oneline-block {
|
||||||
line-height: 36px;
|
line-height: 36px;
|
||||||
|
|
|
@ -16,6 +16,19 @@
|
||||||
@include btn-default;
|
@include btn-default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin btn-outline($background, $text, $border, $hover-background, $hover-text, $hover-border) {
|
||||||
|
background-color: $background;
|
||||||
|
color: $text;
|
||||||
|
border-color: $border;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: $hover-background;
|
||||||
|
color: $hover-text;
|
||||||
|
border-color: $hover-border;;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
|
@mixin btn-color($light, $border-light, $normal, $border-normal, $dark, $border-dark, $color) {
|
||||||
background-color: $light;
|
background-color: $light;
|
||||||
border-color: $border-light;
|
border-color: $border-light;
|
||||||
|
@ -66,6 +79,23 @@
|
||||||
@include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-white-dark, $btn-white-active);
|
@include btn-color($white-light, $border-color, $white-normal, $border-white-normal, $white-dark, $border-white-dark, $btn-white-active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin btn-with-margin {
|
||||||
|
margin-left: $btn-side-margin;
|
||||||
|
float: left;
|
||||||
|
|
||||||
|
&.inline {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-sm {
|
||||||
|
margin-left: $btn-sm-side-margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.btn-xs {
|
||||||
|
margin-left: $btn-xs-side-margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
@include btn-default;
|
@include btn-default;
|
||||||
@include btn-white;
|
@include btn-white;
|
||||||
|
@ -106,11 +136,14 @@
|
||||||
@include btn-blue;
|
@include btn-blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-close,
|
|
||||||
&.btn-warning {
|
&.btn-warning {
|
||||||
@include btn-orange;
|
@include btn-orange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.btn-close {
|
||||||
|
@include btn-outline($white-light, $orange-normal, $orange-normal, $orange-light, $white-light, $orange-light);
|
||||||
|
}
|
||||||
|
|
||||||
&.btn-danger,
|
&.btn-danger,
|
||||||
&.btn-remove,
|
&.btn-remove,
|
||||||
&.btn-red {
|
&.btn-red {
|
||||||
|
@ -126,15 +159,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-grouped {
|
&.btn-grouped {
|
||||||
margin-right: 7px;
|
@include btn-with-margin;
|
||||||
float: left;
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
&.btn-xs {
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
}
|
}
|
||||||
|
@ -176,11 +203,7 @@
|
||||||
|
|
||||||
.btn-group {
|
.btn-group {
|
||||||
&.btn-grouped {
|
&.btn-grouped {
|
||||||
margin-right: 7px;
|
@include btn-with-margin;
|
||||||
float: left;
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,70 +1,44 @@
|
||||||
.calender-block {
|
.calender-block {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
|
||||||
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
|
@media (min-width: $screen-sm-min) and (max-width: $screen-lg-min) {
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-calendar-activities {
|
.user-calendar-activities {
|
||||||
.calendar_onclick_hr {
|
|
||||||
padding: 0;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.str-truncated {
|
.str-truncated {
|
||||||
max-width: 70%;
|
max-width: 70%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-expander {
|
.user-calendar-activities-loading {
|
||||||
background: #eee;
|
font-size: 24px;
|
||||||
color: #555;
|
}
|
||||||
padding: 0 5px;
|
}
|
||||||
cursor: pointer;
|
|
||||||
margin-left: 4px;
|
.user-calendar {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.calendar {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-contrib-cell {
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #ddd;
|
cursor: pointer;
|
||||||
}
|
stroke: #000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
.user-contrib-text {
|
||||||
* This overwrites the default values of the cal-heatmap gem
|
font-size: 12px;
|
||||||
*/
|
fill: #959494;
|
||||||
.calendar {
|
}
|
||||||
.qi {
|
|
||||||
fill: #fff;
|
.calendar-hint {
|
||||||
}
|
margin-top: -23px;
|
||||||
|
float: right;
|
||||||
.q1 {
|
font-size: 12px;
|
||||||
fill: #ededed !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q2 {
|
|
||||||
fill: #acd5f2 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q3 {
|
|
||||||
fill: #7fa8d1 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q4 {
|
|
||||||
fill: #49729b !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q5 {
|
|
||||||
fill: #254e77 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.future {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.domain-background {
|
|
||||||
fill: none;
|
|
||||||
shape-rendering: crispedges;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ch-tooltip {
|
|
||||||
padding: 3px;
|
|
||||||
font-weight: 550;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,10 +122,9 @@
|
||||||
a {
|
a {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-left: 10px;
|
padding: 5px 10px;
|
||||||
padding-right: 10px;
|
|
||||||
color: $dropdown-link-color;
|
color: $dropdown-link-color;
|
||||||
line-height: 34px;
|
line-height: initial;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -154,7 +153,7 @@
|
||||||
color: $dropdown-header-color;
|
color: $dropdown-header-color;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
padding: 0 10px 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.separator + .dropdown-header {
|
.separator + .dropdown-header {
|
||||||
|
@ -162,6 +161,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-menu-large {
|
||||||
|
width: 340px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu-no-wrap {
|
||||||
|
a {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu-full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-menu-paging {
|
.dropdown-menu-paging {
|
||||||
.dropdown-page-two,
|
.dropdown-page-two,
|
||||||
.dropdown-menu-back {
|
.dropdown-menu-back {
|
||||||
|
@ -228,13 +241,11 @@
|
||||||
a {
|
a {
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
|
|
||||||
&.is-active {
|
&.is-indeterminate, &.is-active {
|
||||||
&::before {
|
&::before {
|
||||||
content: "\f00c";
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 5px;
|
left: 5px;
|
||||||
top: 50%;
|
top: 8px;
|
||||||
margin-top: -7px;
|
|
||||||
font: normal normal normal 14px/1 FontAwesome;
|
font: normal normal normal 14px/1 FontAwesome;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
text-rendering: auto;
|
text-rendering: auto;
|
||||||
|
@ -242,6 +253,14 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-indeterminate::before {
|
||||||
|
content: "\f068";
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-active::before {
|
||||||
|
content: "\f00c";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,3 +540,14 @@
|
||||||
background-color: $calendar-unselectable-bg;
|
background-color: $calendar-unselectable-bg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dropdown-menu-inner-title {
|
||||||
|
display: block;
|
||||||
|
color: $gl-title-color;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu-inner-content {
|
||||||
|
display: block;
|
||||||
|
color: $gl-placeholder-color;
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
.file-holder {
|
.file-holder {
|
||||||
border: 1px solid $border-color;
|
border: 1px solid $border-color;
|
||||||
|
|
||||||
|
&.file-holder-no-border {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&.readme-holder {
|
&.readme-holder {
|
||||||
margin: $gl-padding-top 0;
|
margin: $gl-padding-top 0;
|
||||||
}
|
}
|
||||||
|
@ -23,8 +27,17 @@
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
border-radius: 3px 3px 0 0;
|
border-radius: 3px 3px 0 0;
|
||||||
|
|
||||||
|
&.file-title-clear {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
.file-actions {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.file-actions {
|
.file-actions {
|
||||||
float: right;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
right: 15px;
|
right: 15px;
|
||||||
|
|
|
@ -28,10 +28,6 @@ input[type='text'].danger {
|
||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
&.control-label {
|
|
||||||
@extend .col-sm-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.inline-label {
|
&.inline-label {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
@ -41,6 +37,10 @@ label {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.control-label {
|
||||||
|
@extend .col-sm-2;
|
||||||
|
}
|
||||||
|
|
||||||
.inline-input-group {
|
.inline-input-group {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ label {
|
||||||
.form-control {
|
.form-control {
|
||||||
@include box-shadow(none);
|
@include box-shadow(none);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
padding: $gl-vert-padding $gl-input-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
.select-wrapper {
|
.select-wrapper {
|
||||||
|
|
|
@ -8,32 +8,14 @@
|
||||||
*/
|
*/
|
||||||
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
|
@mixin gitlab-theme($color-light, $color, $color-darker, $color-dark) {
|
||||||
.page-with-sidebar {
|
.page-with-sidebar {
|
||||||
.header-logo {
|
|
||||||
background: $color-darker;
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: $color-light;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
color: $color-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $color-dark;
|
|
||||||
a {
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapse-nav a {
|
.collapse-nav a {
|
||||||
color: #fff;
|
color: $color-light;
|
||||||
background: $color;
|
background: $color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $white-light;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
|
@ -45,7 +27,7 @@
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $color-dark;
|
background-color: $color-dark;
|
||||||
color: #fff;
|
color: $white-light;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,10 +45,20 @@
|
||||||
color: $color-light;
|
color: $color-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path,
|
||||||
|
polygon {
|
||||||
|
fill: $color-light;
|
||||||
|
}
|
||||||
|
|
||||||
.count {
|
.count {
|
||||||
color: $color-light;
|
color: $color-light;
|
||||||
background: $color-dark;
|
background: $color-dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
position: relative;
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.separate-item {
|
&.separate-item {
|
||||||
|
@ -74,7 +66,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active a {
|
&.active a {
|
||||||
color: #fff;
|
color: $white-light;
|
||||||
background: $color-dark;
|
background: $color-dark;
|
||||||
|
|
||||||
&.no-highlight {
|
&.no-highlight {
|
||||||
|
@ -82,15 +74,23 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
color: #fff
|
color: $white-light
|
||||||
|
}
|
||||||
|
|
||||||
|
path,
|
||||||
|
polygon {
|
||||||
|
fill: $white-light;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$theme-blue: #2980b9;
|
|
||||||
$theme-charcoal: #3d454d;
|
$theme-charcoal: #3d454d;
|
||||||
|
$theme-charcoal-dark: #383f45;
|
||||||
|
$theme-charcoal-text: #b9bbbe;
|
||||||
|
|
||||||
|
$theme-blue: #2980b9;
|
||||||
$theme-graphite: #666;
|
$theme-graphite: #666;
|
||||||
$theme-gray: #373737;
|
$theme-gray: #373737;
|
||||||
$theme-green: #019875;
|
$theme-green: #019875;
|
||||||
|
@ -102,7 +102,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ui_charcoal {
|
&.ui_charcoal {
|
||||||
@include gitlab-theme(#d6d7d9, #485157, $theme-charcoal, #353b41);
|
@include gitlab-theme($theme-charcoal-text, #485157, $theme-charcoal, $theme-charcoal-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ui_graphite {
|
&.ui_graphite {
|
||||||
|
|
|
@ -79,6 +79,10 @@ header {
|
||||||
|
|
||||||
&.header-collapsed {
|
&.header-collapsed {
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
|
|
||||||
|
.side-nav-toggle {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.side-nav-toggle {
|
.side-nav-toggle {
|
||||||
|
@ -86,6 +90,7 @@ header {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -10px;
|
left: -10px;
|
||||||
margin: 6px 0;
|
margin: 6px 0;
|
||||||
|
font-size: 18px;
|
||||||
padding: 6px 10px;
|
padding: 6px 10px;
|
||||||
border: none;
|
border: none;
|
||||||
background-color: $background-color;
|
background-color: $background-color;
|
||||||
|
@ -97,10 +102,6 @@ header {
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,10 +109,8 @@ header {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: $header-height;
|
height: $header-height;
|
||||||
padding-right: 40px;
|
padding-right: 40px;
|
||||||
|
padding-left: 30px;
|
||||||
@media (max-width: $screen-xs-min) {
|
transition-duration: .3s;
|
||||||
padding-left: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: $screen-sm-min) {
|
@media (min-width: $screen-sm-min) {
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
|
@ -121,9 +120,29 @@ header {
|
||||||
margin-top: -5px;
|
margin-top: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-logo {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -18px;
|
||||||
|
top: 7px;
|
||||||
|
transition-duration: .3s;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: $screen-xs-max) {
|
||||||
|
right: 25px;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
|
max-width: 400px;
|
||||||
|
display: inline-block;
|
||||||
line-height: $header-height;
|
line-height: $header-height;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
|
@ -132,6 +151,10 @@ header {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
@media (max-width: $screen-sm-max) {
|
||||||
|
max-width: 190px;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -159,6 +182,10 @@ header {
|
||||||
.navbar-collapse {
|
.navbar-collapse {
|
||||||
float: right;
|
float: right;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
|
|
||||||
|
@media (max-width: $screen-xs-max) {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,31 +198,24 @@ header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin collapsed-header {
|
|
||||||
margin-left: $sidebar_collapsed_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-collapsed {
|
.header-collapsed {
|
||||||
margin-left: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (min-width: $screen-md-min) {
|
|
||||||
@include collapsed-header;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm-max) {
|
||||||
|
padding-left: 30px;
|
||||||
|
transition-duration: .3s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-expanded {
|
.tanuki-shape {
|
||||||
margin-left: $sidebar_collapsed_width;
|
transition: all 0.8s;
|
||||||
|
|
||||||
@media (min-width: $screen-md-min) {
|
&:hover, &.highlight {
|
||||||
margin-left: $sidebar_width;
|
fill: rgb(255, 255, 255);
|
||||||
}
|
transition: all 0.1s;
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
font-family: $regular_font;
|
font-family: $regular_font;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
|
|
||||||
|
&.ui-datepicker,
|
||||||
&.ui-datepicker-inline {
|
&.ui-datepicker-inline {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
@ -10,6 +11,25 @@
|
||||||
.ui-datepicker-header {
|
.ui-datepicker-header {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: #ddd;
|
border-color: #ddd;
|
||||||
|
|
||||||
|
.ui-datepicker-prev,
|
||||||
|
.ui-datepicker-next {
|
||||||
|
top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-datepicker-prev {
|
||||||
|
left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-datepicker-next {
|
||||||
|
right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-state-hover {
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-datepicker-calendar td a {
|
.ui-datepicker-calendar td a {
|
||||||
|
@ -36,21 +56,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-state-highlight {
|
.ui-state-highlight {
|
||||||
border: 1px solid #eee;
|
border: 0;
|
||||||
background: #eee;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-state-active {
|
.ui-datepicker-calendar {
|
||||||
|
.ui-state-active,
|
||||||
|
.ui-state-hover,
|
||||||
|
.ui-state-focus {
|
||||||
border: 1px solid $gl-primary;
|
border: 1px solid $gl-primary;
|
||||||
background: $gl-primary;
|
background: $gl-primary;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-state-hover,
|
|
||||||
.ui-state-focus {
|
|
||||||
border: 1px solid $row-hover;
|
|
||||||
background: $row-hover;
|
|
||||||
color: #333;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,11 +137,31 @@ ul.content-list {
|
||||||
padding-top: 1px;
|
padding-top: 1px;
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
.btn {
|
> .btn,
|
||||||
padding: 10px 14px;
|
> .btn-group {
|
||||||
|
margin-right: $gl-padding-top;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When dragging a list item
|
||||||
|
&.ui-sortable-helper {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.list-placeholder {
|
||||||
|
background-color: $gray-light;
|
||||||
|
border: dotted 1px $gray-dark;
|
||||||
|
margin: 1px 0;
|
||||||
|
min-height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel > .content-list > li {
|
.panel > .content-list > li {
|
||||||
|
|
|
@ -2,18 +2,10 @@
|
||||||
* Generic mixins
|
* Generic mixins
|
||||||
*/
|
*/
|
||||||
@mixin box-shadow($shadow) {
|
@mixin box-shadow($shadow) {
|
||||||
-webkit-box-shadow: $shadow;
|
|
||||||
-moz-box-shadow: $shadow;
|
|
||||||
-ms-box-shadow: $shadow;
|
|
||||||
-o-box-shadow: $shadow;
|
|
||||||
box-shadow: $shadow;
|
box-shadow: $shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin border-radius($radius) {
|
@mixin border-radius($radius) {
|
||||||
-webkit-border-radius: $radius;
|
|
||||||
-moz-border-radius: $radius;
|
|
||||||
-ms-border-radius: $radius;
|
|
||||||
-o-border-radius: $radius;
|
|
||||||
border-radius: $radius;
|
border-radius: $radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,6 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-home-desc {
|
|
||||||
font-size: 21px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-repo-buttons,
|
.project-repo-buttons,
|
||||||
.git-clone-holder {
|
.git-clone-holder {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -70,10 +66,6 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
%ul.notes .note-role, .note-actions {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-links, .nav-links {
|
.nav-links, .nav-links {
|
||||||
li a {
|
li a {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
|
@ -1,3 +1,35 @@
|
||||||
|
@mixin fade($gradient-direction, $rgba, $gradient-color) {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
z-index: 2;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 12px;
|
||||||
|
width: 43px;
|
||||||
|
height: 30px;
|
||||||
|
transition-duration: .3s;
|
||||||
|
-webkit-transform: translateZ(0);
|
||||||
|
background: -webkit-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
|
||||||
|
background: -o-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
|
||||||
|
background: -moz-linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
|
||||||
|
background: linear-gradient($gradient-direction, $rgba, $gradient-color 45%);
|
||||||
|
|
||||||
|
&.end-scroll {
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
transition-duration: .3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin scrolling-links() {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -10,8 +42,7 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 14px;
|
padding: $gl-btn-padding;
|
||||||
padding-top: $gl-padding;
|
|
||||||
padding-bottom: 11px;
|
padding-bottom: 11px;
|
||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
@ -36,6 +67,29 @@
|
||||||
color: #78a;
|
color: #78a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.sub-nav {
|
||||||
|
text-align: center;
|
||||||
|
background-color: $background-color;
|
||||||
|
|
||||||
|
.container-fluid {
|
||||||
|
background-color: $background-color;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin: 0;
|
||||||
|
padding: 11px 10px 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active a {
|
||||||
|
border-bottom: none;
|
||||||
|
color: $link-underline-blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-area {
|
.top-area {
|
||||||
|
@ -50,6 +104,10 @@
|
||||||
width: 50%;
|
width: 50%;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
|
|
||||||
|
&.wiki-page {
|
||||||
|
padding: 16px 10px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Small devices (phones, tablets, 768px and lower) */
|
/* Small devices (phones, tablets, 768px and lower) */
|
||||||
@media (max-width: $screen-sm-min) {
|
@media (max-width: $screen-sm-min) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -73,6 +131,10 @@
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
|
|
||||||
|
li a {
|
||||||
|
padding: 16px 10px 11px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Small devices (phones, tablets, 768px and lower) */
|
/* Small devices (phones, tablets, 768px and lower) */
|
||||||
@media (max-width: $screen-sm-max) {
|
@media (max-width: $screen-sm-max) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -119,7 +181,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
height: 34px;
|
height: 35px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
|
@ -148,7 +210,7 @@
|
||||||
|
|
||||||
@media (max-width: $screen-xs-max) {
|
@media (max-width: $screen-xs-max) {
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
width: 100%;
|
||||||
.btn, form, .dropdown, .dropdown-menu-toggle, .form-control {
|
.btn, form, .dropdown, .dropdown-menu-toggle, .form-control {
|
||||||
margin: 0 0 10px;
|
margin: 0 0 10px;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -179,16 +241,6 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Small devices (tablets, 768px and lower) */
|
|
||||||
@media (max-width: $screen-sm-max) {
|
|
||||||
width: 100%;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,10 +248,11 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: $header-height;
|
top: $header-height;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 1;
|
z-index: 11;
|
||||||
background: $background-color;
|
background: $background-color;
|
||||||
border-bottom: 1px solid $border-color;
|
border-bottom: 1px solid $border-color;
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -209,13 +262,8 @@
|
||||||
float: right;
|
float: right;
|
||||||
padding: 7px 0 0;
|
padding: 7px 0 0;
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
@media (max-width: $screen-xs-max) {
|
||||||
float: none;
|
display: none;
|
||||||
padding: 0 9px;
|
|
||||||
|
|
||||||
.dropdown-new {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
|
@ -233,19 +281,44 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown {
|
.dropdown {
|
||||||
margin-left: 7px;
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
right: 15px;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
li.active {
|
||||||
margin-left: 0;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-links {
|
.nav-links {
|
||||||
|
@include scrolling-links();
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
height: 51px;
|
height: 51px;
|
||||||
white-space: nowrap;
|
|
||||||
overflow-x: auto;
|
svg {
|
||||||
|
position: relative;
|
||||||
|
top: 2px;
|
||||||
|
margin-right: 2px;
|
||||||
|
height: 15px;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
|
path,
|
||||||
|
polygon {
|
||||||
|
fill: $layout-link-gray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-right {
|
||||||
|
@include fade(left, rgba(250, 250, 250, 0.4), $background-color);
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-left {
|
||||||
|
@include fade(right, rgba(250, 250, 250, 0.4), $background-color);
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
|
||||||
|
@ -258,9 +331,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
|
|
||||||
a, i {
|
a, i {
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
path,
|
||||||
|
polygon {
|
||||||
|
fill: $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
|
@ -269,14 +350,80 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav-control {
|
||||||
|
|
||||||
|
.fade-right {
|
||||||
|
@media (min-width: $screen-xs-max) {
|
||||||
|
right: 68px;
|
||||||
|
}
|
||||||
|
@media (max-width: $screen-xs-min) {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrolling-tabs-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
@include scrolling-links();
|
||||||
|
|
||||||
|
.fade-right {
|
||||||
|
@include fade(left, rgba(255, 255, 255, 0.4), $background-color);
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-left {
|
||||||
|
@include fade(right, rgba(255, 255, 255, 0.4), $background-color);
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-block {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
@include scrolling-links();
|
||||||
|
|
||||||
|
.fade-right {
|
||||||
|
@include fade(left, rgba(255, 255, 255, 0.4), $white-light);
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-left {
|
||||||
|
@include fade(right, rgba(255, 255, 255, 0.4), $white-light);
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.event-filter {
|
||||||
|
.fade-right {
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
@media (max-width: $screen-xs-max) {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-with-layout-nav {
|
.page-with-layout-nav {
|
||||||
margin-top: 50px;
|
margin-top: $header-height + 2;
|
||||||
|
|
||||||
&.controls-dropdown-visible {
|
.right-sidebar {
|
||||||
@media (max-width: $screen-xs-min) {
|
top: ($header-height * 2) + 2;
|
||||||
margin-top: 96px;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.activities {
|
||||||
|
|
||||||
|
.nav-block {
|
||||||
|
border-bottom: 1px solid $border-color;
|
||||||
|
|
||||||
|
.nav-links {
|
||||||
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-color: $input-border;
|
border-color: $input-border;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
padding: $gl-vert-padding $gl-btn-padding;
|
padding: $gl-vert-padding $gl-input-padding;
|
||||||
font-size: $gl-font-size;
|
font-size: $gl-font-size;
|
||||||
line-height: 1.42857143;
|
line-height: 1.42857143;
|
||||||
border-radius: $border-radius-base;
|
border-radius: $border-radius-base;
|
||||||
|
|
|
@ -1,11 +1,3 @@
|
||||||
#logo {
|
|
||||||
z-index: 2;
|
|
||||||
position: absolute;
|
|
||||||
width: 58px;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page-with-sidebar {
|
.page-with-sidebar {
|
||||||
padding-top: $header-height;
|
padding-top: $header-height;
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
|
@ -20,12 +12,6 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gitlab-text-container-link {
|
|
||||||
z-index: 1;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
|
@ -49,58 +35,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
.header-logo {
|
|
||||||
border-bottom: 1px solid transparent;
|
|
||||||
float: left;
|
|
||||||
height: $header-height;
|
|
||||||
width: $sidebar_width;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 999;
|
|
||||||
overflow: hidden;
|
|
||||||
transition-duration: .3s;
|
|
||||||
|
|
||||||
a {
|
|
||||||
float: left;
|
|
||||||
height: $header-height;
|
|
||||||
width: 100%;
|
|
||||||
padding-left: 22px;
|
|
||||||
overflow: hidden;
|
|
||||||
outline: none;
|
|
||||||
transition-duration: .3s;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tanuki-logo, img {
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gitlab-text-container {
|
|
||||||
width: 230px;
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
width: 158px;
|
|
||||||
float: left;
|
|
||||||
margin: 0;
|
|
||||||
margin-left: 50px;
|
|
||||||
font-size: 19px;
|
|
||||||
line-height: 50px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-user {
|
.sidebar-user {
|
||||||
padding: 7px 22px;
|
padding: 15px 22px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 40px;
|
bottom: 0;
|
||||||
width: $sidebar_width;
|
width: $sidebar_width;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
|
@ -126,8 +65,8 @@
|
||||||
|
|
||||||
|
|
||||||
.nav-sidebar {
|
.nav-sidebar {
|
||||||
margin-top: 14 + $header-height;
|
margin-top: 22 + $header-height;
|
||||||
margin-bottom: 100px;
|
margin-bottom: 116px;
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -144,14 +83,19 @@
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-container {
|
||||||
|
width: 34px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
padding: 7px 15px;
|
width: $sidebar_width;
|
||||||
|
padding: 7px 15px 7px 23px;
|
||||||
font-size: $gl-font-size;
|
font-size: $gl-font-size;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
color: $gray;
|
|
||||||
display: block;
|
display: block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding-left: 23px;
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|
||||||
|
@ -164,16 +108,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
width: 16px;
|
font-size: 16px;
|
||||||
color: $gray-light;
|
|
||||||
margin-right: 13px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.count {
|
i,
|
||||||
float: right;
|
svg {
|
||||||
background: #eee;
|
margin-right: 13px;
|
||||||
padding: 0 8px;
|
|
||||||
@include border-radius(6px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.back-link i {
|
&.back-link i {
|
||||||
|
@ -181,6 +121,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.count {
|
||||||
|
float: right;
|
||||||
|
padding: 0 8px;
|
||||||
|
@include border-radius(6px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-subnav {
|
.sidebar-subnav {
|
||||||
|
@ -195,11 +141,12 @@
|
||||||
.collapse-nav a {
|
.collapse-nav a {
|
||||||
width: $sidebar_width;
|
width: $sidebar_width;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
font-size: 13px;
|
padding: 5px 0;
|
||||||
|
font-size: 18px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
height: 40px;
|
height: 50px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
transition-duration: .3s;
|
transition-duration: .3s;
|
||||||
|
@ -217,37 +164,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-sidebar-collapsed {
|
.page-sidebar-collapsed {
|
||||||
padding-left: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-wrapper {
|
.sidebar-wrapper {
|
||||||
width: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.header-logo {
|
|
||||||
width: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding-left: ($sidebar_collapsed_width - 36) / 2;
|
|
||||||
|
|
||||||
.gitlab-text-container {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-sidebar {
|
.nav-sidebar {
|
||||||
width: $sidebar_collapsed_width;
|
width: 0;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
@ -261,46 +184,28 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapse-nav a {
|
.collapse-nav a {
|
||||||
width: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
width: 0;
|
width: 0;
|
||||||
|
|
||||||
|
i {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-user {
|
.sidebar-user {
|
||||||
padding-left: ($sidebar_collapsed_width - 36) / 2;
|
|
||||||
width: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
width: 0;
|
width: 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-nav {
|
|
||||||
padding-right: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
padding-right: 0;;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-sidebar-expanded {
|
.page-sidebar-expanded {
|
||||||
padding-left: $sidebar_collapsed_width;
|
|
||||||
|
|
||||||
@media (min-width: $screen-md-min) {
|
@media (max-width: $screen-sm-max) {
|
||||||
padding-left: $sidebar_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,20 +226,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.layout-nav {
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
padding-right: 0;;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: $screen-xs-min) and (max-width: $screen-md-min) {
|
|
||||||
padding-right: 62px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: $screen-md-min) {
|
|
||||||
padding-right: $sidebar_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-sidebar-collapsed {
|
.right-sidebar-collapsed {
|
||||||
|
@ -353,8 +244,10 @@
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
|
|
||||||
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
|
@media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) {
|
||||||
|
&:not(.build-sidebar) {
|
||||||
padding-right: $sidebar_collapsed_width;
|
padding-right: $sidebar_collapsed_width;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: $screen-md-min) {
|
@media (min-width: $screen-md-min) {
|
||||||
padding-right: $gutter_width;
|
padding-right: $gutter_width;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.timeline-entry {
|
.timeline-entry {
|
||||||
padding: $gl-padding $gl-btn-padding;
|
padding: $gl-padding $gl-btn-padding 11px;
|
||||||
border-color: $table-border-color;
|
border-color: $table-border-color;
|
||||||
color: $gl-gray;
|
color: $gl-gray;
|
||||||
border-bottom: 1px solid $border-white-light;
|
border-bottom: 1px solid $border-white-light;
|
||||||
|
|
|
@ -192,3 +192,8 @@
|
||||||
.text-info:hover {
|
.text-info:hover {
|
||||||
color: $brand-info;
|
color: $brand-info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prevent datetimes on tooltips to break into two lines
|
||||||
|
.local-timeago {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
|
@ -57,13 +57,15 @@ $code_line_height: 1.5;
|
||||||
*/
|
*/
|
||||||
$gl-padding: 16px;
|
$gl-padding: 16px;
|
||||||
$gl-btn-padding: 10px;
|
$gl-btn-padding: 10px;
|
||||||
|
$gl-input-padding: 10px;
|
||||||
$gl-vert-padding: 6px;
|
$gl-vert-padding: 6px;
|
||||||
$gl-padding-top: 10px;
|
$gl-padding-top: 10px;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Misc
|
* Misc
|
||||||
*/
|
*/
|
||||||
$row-hover: #f4f8fe;
|
$row-hover: #f7faff;
|
||||||
|
$row-hover-border: #b2d7ff;
|
||||||
$progress-color: #c0392b;
|
$progress-color: #c0392b;
|
||||||
$avatar_radius: 50%;
|
$avatar_radius: 50%;
|
||||||
$header-height: 50px;
|
$header-height: 50px;
|
||||||
|
@ -78,6 +80,9 @@ $provider-btn-not-active-color: #4688f1;
|
||||||
$link-underline-blue: #4a8bee;
|
$link-underline-blue: #4a8bee;
|
||||||
$layout-link-gray: #7e7c7c;
|
$layout-link-gray: #7e7c7c;
|
||||||
$todo-alert-blue: #428bca;
|
$todo-alert-blue: #428bca;
|
||||||
|
$btn-side-margin: 10px;
|
||||||
|
$btn-sm-side-margin: 7px;
|
||||||
|
$btn-xs-side-margin: 5px;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Color schema
|
* Color schema
|
||||||
|
@ -104,7 +109,7 @@ $blue-medium-light: #3498cb;
|
||||||
$blue-medium: #2f8ebf;
|
$blue-medium: #2f8ebf;
|
||||||
$blue-medium-dark: #2d86b4;
|
$blue-medium-dark: #2d86b4;
|
||||||
|
|
||||||
$orange-light: rgba(252, 109, 38, 0.80);
|
$orange-light: #fc8a51;
|
||||||
$orange-normal: #e75e40;
|
$orange-normal: #e75e40;
|
||||||
$orange-dark: #ce5237;
|
$orange-dark: #ce5237;
|
||||||
|
|
||||||
|
@ -119,8 +124,8 @@ $border-white-light: #f1f2f4;
|
||||||
$border-white-normal: #d6dae2;
|
$border-white-normal: #d6dae2;
|
||||||
$border-white-dark: #c6cacf;
|
$border-white-dark: #c6cacf;
|
||||||
|
|
||||||
$border-gray-light: rgba(0, 0, 0, 0.06);
|
$border-gray-light: #dcdcdc;
|
||||||
$border-gray-normal: rgba(0, 0, 0, 0.10);;
|
$border-gray-normal: #d7d7d7;
|
||||||
$border-gray-dark: #c6cacf;
|
$border-gray-dark: #c6cacf;
|
||||||
|
|
||||||
$border-green-light: #2faa60;
|
$border-green-light: #2faa60;
|
||||||
|
@ -255,3 +260,6 @@ $calendar-header-color: #b8b8b8;
|
||||||
$calendar-hover-bg: #ecf3fe;
|
$calendar-hover-bg: #ecf3fe;
|
||||||
$calendar-border-color: rgba(#000, .1);
|
$calendar-border-color: rgba(#000, .1);
|
||||||
$calendar-unselectable-bg: #faf9f9;
|
$calendar-unselectable-bg: #faf9f9;
|
||||||
|
|
||||||
|
$ci-output-bg: #1d1f21;
|
||||||
|
$ci-text-color: #c5c8c6;
|
||||||
|
|
134
app/assets/stylesheets/mailers/devise.scss
Normal file
134
app/assets/stylesheets/mailers/devise.scss
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
// NOTE: This stylesheet is for the exclusive use of the `devise_mailer` layout
|
||||||
|
// used for Devise email templates, and _should not_ be included in any
|
||||||
|
// application stylesheets.
|
||||||
|
//
|
||||||
|
// Styles defined here are embedded directly into the resulting email HTML via
|
||||||
|
// the `premailer` gem.
|
||||||
|
|
||||||
|
$body-background-color: #363636;
|
||||||
|
$message-background-color: #fafafa;
|
||||||
|
|
||||||
|
$header-color: #6b4fbb;
|
||||||
|
$body-color: #444;
|
||||||
|
$cta-color: #e14329;
|
||||||
|
$footer-link-color: #7e7e7e;
|
||||||
|
|
||||||
|
$font-family: Helvetica, Arial, sans-serif;
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: $body-background-color;
|
||||||
|
font-family: $font-family;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
-premailer-cellpadding: 0;
|
||||||
|
-premailer-cellspacing: 0;
|
||||||
|
|
||||||
|
border: 0;
|
||||||
|
border-collapse: separate;
|
||||||
|
|
||||||
|
&#wrapper {
|
||||||
|
background-color: $body-background-color;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&#header {
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: left;
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&#body {
|
||||||
|
background-color: $message-background-color;
|
||||||
|
border: 1px solid #000;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&#footer {
|
||||||
|
color: $footer-link-color;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
&#body-container {
|
||||||
|
padding: 20px 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#logo {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
min-height: 88px;
|
||||||
|
width: 134px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
h2 {
|
||||||
|
color: $header-color;
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 34px;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: $body-color;
|
||||||
|
font-size: 17px;
|
||||||
|
line-height: 24px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cta {
|
||||||
|
border: 1px solid $cta-color;
|
||||||
|
border-radius: 3px;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 12px 24px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: $message-background-color;
|
||||||
|
color: $cta-color;
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#tanuki {
|
||||||
|
padding: 40px 0 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
width: 37px;
|
||||||
|
min-height: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#tagline {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 100;
|
||||||
|
padding: 4px 0 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#social {
|
||||||
|
padding: 0 10px 20px;
|
||||||
|
width: 600px;
|
||||||
|
word-spacing: 20px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $footer-link-color;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,15 @@
|
||||||
@import "framework/variables";
|
@import "framework/variables";
|
||||||
|
|
||||||
|
// This file is largely copied from `highlight/white.scss`, but modified to
|
||||||
|
// avoid all descendant selectors (`table td`). This is because the CSS inlining
|
||||||
|
// we use performs dramatically worse on descendant selectors than the
|
||||||
|
// alternatives.
|
||||||
|
// <https://gitlab.com/gitlab-org/gitlab-ee/issues/490#note_12283632>
|
||||||
|
//
|
||||||
|
// DO NOT ADD ANY DESCENDANT SELECTORS TO THIS FILE. Instead, use (in order of
|
||||||
|
// preference): plain class selectors, type (element name) selectors, or
|
||||||
|
// explicit child selectors.
|
||||||
|
|
||||||
table.code {
|
table.code {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
@ -11,33 +21,162 @@ table.code {
|
||||||
-premailer-cellspacing: 0;
|
-premailer-cellspacing: 0;
|
||||||
-premailer-width: 100%;
|
-premailer-width: 100%;
|
||||||
|
|
||||||
td {
|
> tr > td {
|
||||||
line-height: $code_line_height;
|
line-height: $code_line_height;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: $code_font_size;
|
font-size: $code_font_size;
|
||||||
}
|
|
||||||
|
|
||||||
td.diff-line-num {
|
&.diff-line-num {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: none;
|
border: none;
|
||||||
background: $background-color;
|
|
||||||
color: rgba(0, 0, 0, 0.3);
|
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
border-right: 1px solid $border-color;
|
border-right: 1px solid;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
min-width: 35px;
|
min-width: 35px;
|
||||||
max-width: 50px;
|
max-width: 50px;
|
||||||
width: 35px;
|
width: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.line_content {
|
&.line_content {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
border: none;
|
border: none;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "highlight/white";
|
.line-numbers, .diff-line-num {
|
||||||
|
background-color: $background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-line-num, .diff-line-num a {
|
||||||
|
color: $black-transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.code, .diff-line-num {
|
||||||
|
border-color: $table-border-gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code.white, pre.code, .line_content {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diff-line-num {
|
||||||
|
&.old {
|
||||||
|
background-color: $line-number-old;
|
||||||
|
border-color: $line-removed-dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.new {
|
||||||
|
background-color: $line-number-new;
|
||||||
|
border-color: $line-added-dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hll:not(.empty-cell) {
|
||||||
|
background-color: $line-number-select;
|
||||||
|
border-color: $line-select-yellow-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line_content {
|
||||||
|
&.old {
|
||||||
|
background-color: $line-removed;
|
||||||
|
|
||||||
|
> .line > span.idiff, > .line > span > span.idiff {
|
||||||
|
background-color: $line-removed-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.new {
|
||||||
|
background-color: $line-added;
|
||||||
|
|
||||||
|
> .line > span.idiff, > .line > span > span.idiff {
|
||||||
|
background-color: $line-added-dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.match {
|
||||||
|
color: $black-transparent;
|
||||||
|
background-color: $match-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hll:not(.empty-cell) {
|
||||||
|
background-color: $line-select-yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > .hll {
|
||||||
|
background-color: #f8eec7 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.highlight_word {
|
||||||
|
background-color: #fafe3d !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hll { background-color: #f8f8f8 }
|
||||||
|
.c { color: #998; font-style: italic; }
|
||||||
|
.err { color: #a61717; background-color: #e3d2d2; }
|
||||||
|
.k { font-weight: bold; }
|
||||||
|
.o { font-weight: bold; }
|
||||||
|
.cm { color: #998; font-style: italic; }
|
||||||
|
.cp { color: #999; font-weight: bold; }
|
||||||
|
.c1 { color: #998; font-style: italic; }
|
||||||
|
.cs { color: #999; font-weight: bold; font-style: italic; }
|
||||||
|
.gd { color: #000; background-color: #fdd; }
|
||||||
|
.gd .x { color: #000; background-color: #faa; }
|
||||||
|
.ge { font-style: italic; }
|
||||||
|
.gr { color: #a00; }
|
||||||
|
.gh { color: #999; }
|
||||||
|
.gi { color: #000; background-color: #dfd; }
|
||||||
|
.gi .x { color: #000; background-color: #afa; }
|
||||||
|
.go { color: #888; }
|
||||||
|
.gp { color: #555; }
|
||||||
|
.gs { font-weight: bold; }
|
||||||
|
.gu { color: #800080; font-weight: bold; }
|
||||||
|
.gt { color: #a00; }
|
||||||
|
.kc { font-weight: bold; }
|
||||||
|
.kd { font-weight: bold; }
|
||||||
|
.kn { font-weight: bold; }
|
||||||
|
.kp { font-weight: bold; }
|
||||||
|
.kr { font-weight: bold; }
|
||||||
|
.kt { color: #458; font-weight: bold; }
|
||||||
|
.m { color: #099; }
|
||||||
|
.s { color: #d14; }
|
||||||
|
.n { color: #333; }
|
||||||
|
.na { color: teal; }
|
||||||
|
.nb { color: #0086b3; }
|
||||||
|
.nc { color: #458; font-weight: bold; }
|
||||||
|
.no { color: teal; }
|
||||||
|
.ni { color: purple; }
|
||||||
|
.ne { color: #900; font-weight: bold; }
|
||||||
|
.nf { color: #900; font-weight: bold; }
|
||||||
|
.nn { color: #555; }
|
||||||
|
.nt { color: navy; }
|
||||||
|
.nv { color: teal; }
|
||||||
|
.ow { font-weight: bold; }
|
||||||
|
.w { color: #bbb; }
|
||||||
|
.mf { color: #099; }
|
||||||
|
.mh { color: #099; }
|
||||||
|
.mi { color: #099; }
|
||||||
|
.mo { color: #099; }
|
||||||
|
.sb { color: #d14; }
|
||||||
|
.sc { color: #d14; }
|
||||||
|
.sd { color: #d14; }
|
||||||
|
.s2 { color: #d14; }
|
||||||
|
.se { color: #d14; }
|
||||||
|
.sh { color: #d14; }
|
||||||
|
.si { color: #d14; }
|
||||||
|
.sx { color: #d14; }
|
||||||
|
.sr { color: #009926; }
|
||||||
|
.s1 { color: #d14; }
|
||||||
|
.ss { color: #990073; }
|
||||||
|
.bp { color: #999; }
|
||||||
|
.vc { color: teal; }
|
||||||
|
.vg { color: teal; }
|
||||||
|
.vi { color: teal; }
|
||||||
|
.il { color: #099; }
|
||||||
|
.gc { color: #999; background-color: #eaf2f5; }
|
||||||
|
|
|
@ -6,19 +6,19 @@ p.details {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: #777
|
color: #777
|
||||||
}
|
}
|
||||||
.footer p {
|
.footer > p {
|
||||||
font-size: small;
|
font-size: small;
|
||||||
color: #777
|
color: #777
|
||||||
}
|
}
|
||||||
pre.commit-message {
|
pre.commit-message {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
.file-stats a {
|
.file-stats > a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
> .new-file {
|
||||||
.file-stats .new-file {
|
|
||||||
color: #090;
|
color: #090;
|
||||||
}
|
}
|
||||||
.file-stats .deleted-file {
|
> .deleted-file {
|
||||||
color: #b00;
|
color: #b00;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
.awards {
|
.awards {
|
||||||
line-height: 34px;
|
|
||||||
|
|
||||||
.emoji-icon {
|
.emoji-icon {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
@ -9,8 +7,6 @@
|
||||||
|
|
||||||
.emoji-menu {
|
.emoji-menu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
|
@ -23,7 +19,12 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scale(.2);
|
transform: scale(.2);
|
||||||
transform-origin: 0 -45px;
|
transform-origin: 0 -45px;
|
||||||
transition: all .3s cubic-bezier(.87,-.41,.19,1.44);
|
transition: .3s cubic-bezier(.87,-.41,.19,1.44);
|
||||||
|
transition-property: transform, opacity;
|
||||||
|
|
||||||
|
&.is-aligned-right {
|
||||||
|
transform-origin: 100% -45px;
|
||||||
|
}
|
||||||
|
|
||||||
&.is-visible {
|
&.is-visible {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
@ -94,20 +95,30 @@
|
||||||
|
|
||||||
.award-control {
|
.award-control {
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
&.active,
|
&.active,
|
||||||
&:active {
|
&:active {
|
||||||
background-color: $white-dark;
|
background-color: $row-hover;
|
||||||
|
border-color: $row-hover-border;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.btn {
|
||||||
|
&:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.is-loading {
|
&.is-loading {
|
||||||
.award-control-icon {
|
.award-control-icon-normal,
|
||||||
|
.emoji-icon {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,7 @@
|
||||||
background: #111;
|
background: #111;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-family: $monospace_font;
|
font-family: $monospace_font;
|
||||||
white-space: pre;
|
white-space: pre-wrap;
|
||||||
white-space: pre-wrap; /* css-3 */
|
|
||||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
|
||||||
white-space: -pre-wrap; /* Opera 4-6 */
|
|
||||||
white-space: -o-pre-wrap; /* Opera 7 */
|
|
||||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -58,37 +53,92 @@
|
||||||
left: 70px;
|
left: 70px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.build-widget {
|
.build-header {
|
||||||
padding: 10px;
|
position: relative;
|
||||||
background: $background-color;
|
padding-right: 40px;
|
||||||
margin-bottom: 20px;
|
|
||||||
border-radius: 4px;
|
|
||||||
|
|
||||||
.title {
|
@media (min-width: $screen-sm-min) {
|
||||||
margin-top: 0;
|
padding-right: 0;
|
||||||
color: #666;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
}
|
||||||
.attr-name {
|
|
||||||
color: #777;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-disabled {
|
|
||||||
background: $background-color;
|
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: #3084bb !important;
|
color: $gl-gray;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $gl-link-color;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: $code-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
float: none;
|
||||||
|
margin-right: 2px;
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table.builds {
|
table.builds {
|
||||||
|
|
||||||
.build-link {
|
.build-link {
|
||||||
a {
|
a {
|
||||||
color: $gl-dark-link-color;
|
color: $gl-dark-link-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.build-trace {
|
||||||
|
background: $ci-output-bg;
|
||||||
|
color: $ci-text-color;
|
||||||
|
white-space: pre;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
.fa-refresh {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bash {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-sidebar.build-sidebar {
|
||||||
|
padding-top: $gl-padding;
|
||||||
|
padding-bottom: $gl-padding;
|
||||||
|
|
||||||
|
&.right-sidebar-collapsed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.build-sidebar-header {
|
||||||
|
padding-top: 0;
|
||||||
|
|
||||||
|
.gutter-toggle {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.build-detail-row {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.build-light-text {
|
||||||
|
color: $gl-placeholder-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.build-gutter-toggle {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
margin-top: -17px;
|
||||||
|
}
|
||||||
|
|
|
@ -26,8 +26,28 @@
|
||||||
|
|
||||||
.commit-info-row {
|
.commit-info-row {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&.commit-info-row-header {
|
||||||
|
line-height: 34px;
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm-min) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.commit-options-dropdown-caret {
|
||||||
|
@media (max-width: $screen-sm) {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
@extend .avatar-inline;
|
@extend .avatar-inline;
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm-min) {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.commit-committer-link,
|
.commit-committer-link,
|
||||||
.commit-author-link {
|
.commit-author-link {
|
||||||
|
@ -35,10 +55,6 @@
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time_ago {
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fa-clipboard {
|
.fa-clipboard {
|
||||||
color: $dropdown-title-btn-color;
|
color: $dropdown-title-btn-color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,21 @@
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
|
|
||||||
> h1 {
|
> h1, h2, h3, h4, h5, h6 {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
.lead {
|
.lead {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.confirmation-content {
|
.confirmation-content {
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
|
|
||||||
p {
|
p {
|
||||||
overflow-x: auto;
|
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
5
app/assets/stylesheets/pages/environments.scss
Normal file
5
app/assets/stylesheets/pages/environments.scss
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
.environments {
|
||||||
|
.commit-title {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,3 +39,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.groups-cover-block {
|
||||||
|
|
||||||
|
.container-fluid {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.access-request-button {
|
||||||
|
@include btn-gray;
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
bottom: 32px;
|
||||||
|
padding: 3px 10px;
|
||||||
|
text-transform: none;
|
||||||
|
background-color: $background-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,11 +29,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.issuable-sidebar {
|
.right-sidebar {
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.issuable-header-text {
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
@include clearfix;
|
@include clearfix;
|
||||||
padding: $gl-padding 0;
|
padding: $gl-padding 0;
|
||||||
|
@ -60,10 +64,6 @@
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.issuable-count {
|
|
||||||
margin-top: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gutter-toggle {
|
.gutter-toggle {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
|
@ -74,6 +74,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.block-first {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
@ -246,7 +250,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.issuable-pager {
|
.issuable-header-btn {
|
||||||
background: $gray-normal;
|
background: $gray-normal;
|
||||||
border: 1px solid $border-gray-normal;
|
border: 1px solid $border-gray-normal;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -259,7 +263,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a:not(.issuable-pager) {
|
a {
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $md-link-color;
|
color: $md-link-color;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
|
@ -40,11 +40,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.issue-search-form {
|
|
||||||
margin: 0;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
form.edit-issue {
|
form.edit-issue {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
@ -96,8 +91,3 @@ form.edit-issue {
|
||||||
.issue-form .select2-container {
|
.issue-form .select2-container {
|
||||||
width: 250px !important;
|
width: 250px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.issue-closed-by-widget {
|
|
||||||
color: $gl-text-color;
|
|
||||||
margin-left: 52px;
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,11 +50,26 @@
|
||||||
|
|
||||||
.label-row {
|
.label-row {
|
||||||
.label-name {
|
.label-name {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm-min) {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
.label-description {
|
||||||
display: block;
|
display: block;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm-min) {
|
||||||
|
display: inline-block;
|
||||||
|
width: 40%;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +83,6 @@
|
||||||
padding: 3px 4px;
|
padding: 3px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.label-subscription {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-labels-error {
|
.dropdown-labels-error {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
@ -79,62 +90,95 @@
|
||||||
color: $white-light;
|
color: $white-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin labels-mobile {
|
.manage-labels-list {
|
||||||
@media (max-width: $screen-xs-min) {
|
.btn-action {
|
||||||
display: block;
|
color: $gl-dark-link-color;
|
||||||
width: 100%;
|
|
||||||
margin-left: 0;
|
.fa {
|
||||||
padding: 10px 0;
|
font-size: 18px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $gl-link-color;
|
||||||
|
|
||||||
|
&.remove-row {
|
||||||
|
color: $gl-danger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown {
|
||||||
|
@media (min-width: $screen-sm-min) {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prioritized-labels {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
|
||||||
.manage-labels-list {
|
.add-priority {
|
||||||
|
display: none;
|
||||||
|
color: $gray-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.prepend-left-10, .prepend-description-left {
|
.other-labels {
|
||||||
|
.remove-priority {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-priority {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 40%;
|
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
@include labels-mobile;
|
button {
|
||||||
}
|
|
||||||
|
|
||||||
.prepend-description-left {
|
|
||||||
width: 57%;
|
|
||||||
|
|
||||||
@include labels-mobile;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pull-info-right {
|
|
||||||
float: right;
|
|
||||||
|
|
||||||
@media (max-width: $screen-xs-min) {
|
|
||||||
float: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
padding: 6px;
|
padding: 5px 8px;
|
||||||
color: $gl-text-color;
|
vertical-align: top;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
&.label-subscribe-button {
|
&:hover {
|
||||||
padding-left: 0;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
i {
|
|
||||||
color: $gl-text-color;
|
.filtered-labels {
|
||||||
}
|
.label-row {
|
||||||
|
&:not(:last-child) {
|
||||||
.append-right-20 {
|
margin-right: 5px;
|
||||||
a {
|
}
|
||||||
color: $gl-text-color;
|
}
|
||||||
}
|
|
||||||
|
.label-remove {
|
||||||
@media (max-width: $screen-xs-min) {
|
border-left: 1px solid rgba(0, 0, 0, .1);
|
||||||
display: block;
|
z-index: 3;
|
||||||
margin-bottom: 10px;
|
}
|
||||||
}
|
|
||||||
|
.btn {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-options-toggle {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-subscribe-button {
|
||||||
|
.label-subscribe-button-loading {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
.label-subscribe-button-icon {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-subscribe-button-loading {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
padding-top: 12px;
|
padding-top: 8px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
|
|
||||||
&.right {
|
&.right {
|
||||||
|
@ -79,11 +79,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.ci-failed,
|
&.ci-failed,
|
||||||
&.ci-canceled,
|
|
||||||
&.ci-error {
|
&.ci-error {
|
||||||
color: $gl-danger;
|
color: $gl-danger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.ci-canceled {
|
||||||
|
color: $gl-gray;
|
||||||
|
}
|
||||||
|
|
||||||
a.monospace {
|
a.monospace {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
@ -105,11 +108,39 @@
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
color: $gl-gray-dark;
|
color: $gl-gray-dark;
|
||||||
|
|
||||||
|
&.has-conflicts .fa-exclamation-triangle {
|
||||||
|
color: $gl-warning;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p:last-child {
|
p:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: $screen-sm-max) {
|
||||||
|
h4 {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn,
|
||||||
|
.btn-group,
|
||||||
|
.accept-action {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accept-control {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr-widget-footer {
|
.mr-widget-footer {
|
||||||
|
@ -280,11 +311,15 @@
|
||||||
background-color: $white-light;
|
background-color: $white-light;
|
||||||
color: $gl-placeholder-color;
|
color: $gl-placeholder-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.merged-buttons {
|
||||||
|
.btn {
|
||||||
|
float: left;
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue