New upstream version 9.5.4+dfsg
This commit is contained in:
parent
b03c211899
commit
574775de31
5149 changed files with 159847 additions and 65503 deletions
47
.codeclimate.yml
Normal file
47
.codeclimate.yml
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
---
|
||||||
|
engines:
|
||||||
|
brakeman:
|
||||||
|
enabled: true
|
||||||
|
bundler-audit:
|
||||||
|
enabled: true
|
||||||
|
duplication:
|
||||||
|
enabled: true
|
||||||
|
config:
|
||||||
|
languages:
|
||||||
|
- ruby
|
||||||
|
- javascript
|
||||||
|
exclude_paths:
|
||||||
|
- "lib/api/v3/*"
|
||||||
|
eslint:
|
||||||
|
enabled: true
|
||||||
|
rubocop:
|
||||||
|
enabled: true
|
||||||
|
ratings:
|
||||||
|
paths:
|
||||||
|
- Gemfile.lock
|
||||||
|
- "**.erb"
|
||||||
|
- "**.haml"
|
||||||
|
- "**.rb"
|
||||||
|
- "**.rhtml"
|
||||||
|
- "**.slim"
|
||||||
|
- "**.inc"
|
||||||
|
- "**.js"
|
||||||
|
- "**.jsx"
|
||||||
|
- "**.module"
|
||||||
|
exclude_paths:
|
||||||
|
- config/
|
||||||
|
- db/
|
||||||
|
- features/
|
||||||
|
- node_modules/
|
||||||
|
- spec/
|
||||||
|
- vendor/
|
||||||
|
- .yarn-cache/
|
||||||
|
- tmp/
|
||||||
|
- builds/
|
||||||
|
- coverage/
|
||||||
|
- public/
|
||||||
|
- shared/
|
||||||
|
- webpack-report/
|
||||||
|
- log/
|
||||||
|
- backups/
|
||||||
|
- coverage-javascript/
|
|
@ -11,6 +11,7 @@
|
||||||
"gon": false,
|
"gon": false,
|
||||||
"localStorage": false
|
"localStorage": false
|
||||||
},
|
},
|
||||||
|
"parser": "babel-eslint",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"filenames",
|
"filenames",
|
||||||
"import",
|
"import",
|
||||||
|
@ -27,7 +28,9 @@
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"filenames/match-regex": [2, "^[a-z0-9_]+$"],
|
"filenames/match-regex": [2, "^[a-z0-9_]+$"],
|
||||||
|
"import/no-commonjs": "error",
|
||||||
"no-multiple-empty-lines": ["error", { "max": 1 }],
|
"no-multiple-empty-lines": ["error", { "max": 1 }],
|
||||||
"promise/catch-or-return": "error"
|
"promise/catch-or-return": "error",
|
||||||
|
"no-underscore-dangle": ["error", { "allow": ["__"]}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,3 +3,5 @@ lib/gitlab/sanitizers/svg/whitelist.rb
|
||||||
lib/gitlab/diff/position_tracer.rb
|
lib/gitlab/diff/position_tracer.rb
|
||||||
app/policies/project_policy.rb
|
app/policies/project_policy.rb
|
||||||
app/models/concerns/relative_positioning.rb
|
app/models/concerns/relative_positioning.rb
|
||||||
|
app/workers/stuck_merge_jobs_worker.rb
|
||||||
|
lib/gitlab/redis/*.rb
|
||||||
|
|
7
.gitignore
vendored
7
.gitignore
vendored
|
@ -18,8 +18,10 @@ eslint-report.html
|
||||||
.sass-cache/
|
.sass-cache/
|
||||||
/.secret
|
/.secret
|
||||||
/.vagrant
|
/.vagrant
|
||||||
|
/.yarn-cache
|
||||||
/.byebug_history
|
/.byebug_history
|
||||||
/Vagrantfile
|
/Vagrantfile
|
||||||
|
/app/assets/javascripts/locale/**/app.js
|
||||||
/backups/*
|
/backups/*
|
||||||
/config/aws.yml
|
/config/aws.yml
|
||||||
/config/database.yml
|
/config/database.yml
|
||||||
|
@ -29,6 +31,9 @@ eslint-report.html
|
||||||
/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/redis.cache.yml
|
||||||
|
/config/redis.queues.yml
|
||||||
|
/config/redis.shared_state.yml
|
||||||
/config/unicorn.rb
|
/config/unicorn.rb
|
||||||
/config/secrets.yml
|
/config/secrets.yml
|
||||||
/config/sidekiq.yml
|
/config/sidekiq.yml
|
||||||
|
@ -48,6 +53,7 @@ eslint-report.html
|
||||||
/public/uploads/
|
/public/uploads/
|
||||||
/shared/artifacts/
|
/shared/artifacts/
|
||||||
/spec/javascripts/fixtures/blob/pdf/
|
/spec/javascripts/fixtures/blob/pdf/
|
||||||
|
/spec/javascripts/fixtures/blob/balsamiq/
|
||||||
/rails_best_practices_output.html
|
/rails_best_practices_output.html
|
||||||
/tags
|
/tags
|
||||||
/tmp/*
|
/tmp/*
|
||||||
|
@ -57,3 +63,4 @@ eslint-report.html
|
||||||
/.gitlab_workhorse_secret
|
/.gitlab_workhorse_secret
|
||||||
/webpack-report/
|
/webpack-report/
|
||||||
/locale/**/LC_MESSAGES
|
/locale/**/LC_MESSAGES
|
||||||
|
/.rspec
|
||||||
|
|
397
.gitlab-ci.yml
397
.gitlab-ci.yml
|
@ -1,9 +1,20 @@
|
||||||
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-phantomjs-2.1-node-7.1-postgresql-9.6"
|
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-phantomjs-2.1-node-7.1-postgresql-9.6"
|
||||||
|
|
||||||
cache:
|
.default-cache: &default-cache
|
||||||
key: "ruby-233"
|
key: "ruby-233-with-yarn"
|
||||||
paths:
|
paths:
|
||||||
- vendor/ruby
|
- vendor/ruby
|
||||||
|
- .yarn-cache/
|
||||||
|
|
||||||
|
.push-cache: &push-cache
|
||||||
|
cache:
|
||||||
|
<<: *default-cache
|
||||||
|
policy: push
|
||||||
|
|
||||||
|
.pull-cache: &pull-cache
|
||||||
|
cache:
|
||||||
|
<<: *default-cache
|
||||||
|
policy: pull
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
|
MYSQL_ALLOW_EMPTY_PASSWORD: "1"
|
||||||
|
@ -23,11 +34,11 @@ before_script:
|
||||||
- source scripts/prepare_build.sh
|
- source scripts/prepare_build.sh
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- prepare
|
- prepare
|
||||||
- test
|
- test
|
||||||
- post-test
|
- post-test
|
||||||
- pages
|
- pages
|
||||||
|
|
||||||
# Predefined scopes
|
# Predefined scopes
|
||||||
.dedicated-runner: &dedicated-runner
|
.dedicated-runner: &dedicated-runner
|
||||||
|
@ -40,10 +51,6 @@ stages:
|
||||||
SETUP_DB: "false"
|
SETUP_DB: "false"
|
||||||
USE_BUNDLE_INSTALL: "false"
|
USE_BUNDLE_INSTALL: "false"
|
||||||
KNAPSACK_S3_BUCKET: "gitlab-ce-cache"
|
KNAPSACK_S3_BUCKET: "gitlab-ce-cache"
|
||||||
cache:
|
|
||||||
key: "knapsack"
|
|
||||||
paths:
|
|
||||||
- knapsack/
|
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 31d
|
expire_in: 31d
|
||||||
paths:
|
paths:
|
||||||
|
@ -59,34 +66,39 @@ stages:
|
||||||
- mysql:latest
|
- mysql:latest
|
||||||
- redis:alpine
|
- redis:alpine
|
||||||
|
|
||||||
.only-master-and-ee-or-mysql: &only-master-and-ee-or-mysql
|
.only-if-want-mysql: &only-if-want-mysql
|
||||||
only:
|
only:
|
||||||
- /mysql/
|
- /mysql/
|
||||||
|
- /-stable/
|
||||||
- master@gitlab-org/gitlab-ce
|
- master@gitlab-org/gitlab-ce
|
||||||
|
- master@gitlab-org/gitlab-ee
|
||||||
- master@gitlab/gitlabhq
|
- master@gitlab/gitlabhq
|
||||||
|
- master@gitlab/gitlab-ee
|
||||||
- tags@gitlab-org/gitlab-ce
|
- tags@gitlab-org/gitlab-ce
|
||||||
|
- tags@gitlab-org/gitlab-ee
|
||||||
- tags@gitlab/gitlabhq
|
- tags@gitlab/gitlabhq
|
||||||
- //@gitlab-org/gitlab-ee
|
- tags@gitlab/gitlab-ee
|
||||||
- //@gitlab/gitlab-ee
|
|
||||||
|
|
||||||
# Skip all jobs except the ones that begin with 'docs/'.
|
# Skip all jobs except the ones that begin with 'docs/'.
|
||||||
# Used for commits including ONLY documentation changes.
|
# Used for commits including ONLY documentation changes.
|
||||||
# https://docs.gitlab.com/ce/development/writing_documentation.html#testing
|
# https://docs.gitlab.com/ce/development/writing_documentation.html#testing
|
||||||
.except-docs: &except-docs
|
.except-docs: &except-docs
|
||||||
except:
|
except:
|
||||||
- /^docs\/.*/
|
- /(^docs[\/-].*|.*-docs$)/
|
||||||
|
|
||||||
.rspec-knapsack: &rspec-knapsack
|
.rspec-knapsack: &rspec-knapsack
|
||||||
stage: test
|
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
|
<<: *pull-cache
|
||||||
|
stage: test
|
||||||
script:
|
script:
|
||||||
- JOB_NAME=( $CI_JOB_NAME )
|
- JOB_NAME=( $CI_JOB_NAME )
|
||||||
- export CI_NODE_INDEX=${JOB_NAME[-2]}
|
- export CI_NODE_INDEX=${JOB_NAME[-2]}
|
||||||
- export CI_NODE_TOTAL=${JOB_NAME[-1]}
|
- export CI_NODE_TOTAL=${JOB_NAME[-1]}
|
||||||
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_${JOB_NAME[1]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
|
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
|
||||||
- export KNAPSACK_GENERATE_REPORT=true
|
- export KNAPSACK_GENERATE_REPORT=true
|
||||||
- export CACHE_CLASSES=true
|
- export CACHE_CLASSES=true
|
||||||
- cp ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
|
- cp ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
|
||||||
|
- scripts/gitaly-test-spawn
|
||||||
- knapsack rspec "--color --format documentation"
|
- knapsack rspec "--color --format documentation"
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 31d
|
expire_in: 31d
|
||||||
|
@ -104,17 +116,18 @@ stages:
|
||||||
.rspec-knapsack-mysql: &rspec-knapsack-mysql
|
.rspec-knapsack-mysql: &rspec-knapsack-mysql
|
||||||
<<: *rspec-knapsack
|
<<: *rspec-knapsack
|
||||||
<<: *use-mysql
|
<<: *use-mysql
|
||||||
<<: *only-master-and-ee-or-mysql
|
<<: *only-if-want-mysql
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
|
||||||
.spinach-knapsack: &spinach-knapsack
|
.spinach-knapsack: &spinach-knapsack
|
||||||
stage: test
|
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
|
<<: *pull-cache
|
||||||
|
stage: test
|
||||||
script:
|
script:
|
||||||
- JOB_NAME=( $CI_JOB_NAME )
|
- JOB_NAME=( $CI_JOB_NAME )
|
||||||
- export CI_NODE_INDEX=${JOB_NAME[-2]}
|
- export CI_NODE_INDEX=${JOB_NAME[-2]}
|
||||||
- export CI_NODE_TOTAL=${JOB_NAME[-1]}
|
- export CI_NODE_TOTAL=${JOB_NAME[-1]}
|
||||||
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_${JOB_NAME[1]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
|
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
|
||||||
- export KNAPSACK_GENERATE_REPORT=true
|
- export KNAPSACK_GENERATE_REPORT=true
|
||||||
- export CACHE_CLASSES=true
|
- export CACHE_CLASSES=true
|
||||||
- cp ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
|
- cp ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
|
||||||
|
@ -135,30 +148,33 @@ stages:
|
||||||
.spinach-knapsack-mysql: &spinach-knapsack-mysql
|
.spinach-knapsack-mysql: &spinach-knapsack-mysql
|
||||||
<<: *spinach-knapsack
|
<<: *spinach-knapsack
|
||||||
<<: *use-mysql
|
<<: *use-mysql
|
||||||
<<: *only-master-and-ee-or-mysql
|
<<: *only-if-want-mysql
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
|
||||||
|
.only-canonical-masters: &only-canonical-masters
|
||||||
|
only:
|
||||||
|
- master@gitlab-org/gitlab-ce
|
||||||
|
- master@gitlab-org/gitlab-ee
|
||||||
|
- master@gitlab/gitlabhq
|
||||||
|
- master@gitlab/gitlab-ee
|
||||||
|
|
||||||
# Trigger a package build on omnibus-gitlab repository
|
# Trigger a package build on omnibus-gitlab repository
|
||||||
|
|
||||||
build-package:
|
build-package:
|
||||||
|
image: ruby:2.3-alpine
|
||||||
|
before_script: []
|
||||||
services: []
|
services: []
|
||||||
variables:
|
variables:
|
||||||
SETUP_DB: "false"
|
SETUP_DB: "false"
|
||||||
USE_BUNDLE_INSTALL: "false"
|
USE_BUNDLE_INSTALL: "false"
|
||||||
stage: build
|
stage: build
|
||||||
|
cache: {}
|
||||||
when: manual
|
when: manual
|
||||||
script:
|
script:
|
||||||
# If no branch in omnibus is specified, trigger pipeline against master
|
- scripts/trigger-build
|
||||||
- if [ -z "$OMNIBUS_BRANCH" ] ; then export OMNIBUS_BRANCH=master ;fi
|
only:
|
||||||
- echo "token=${BUILD_TRIGGER_TOKEN}" > version_details
|
- //@gitlab-org/gitlab-ce
|
||||||
- echo "ref=${OMNIBUS_BRANCH}" >> version_details
|
- //@gitlab-org/gitlab-ee
|
||||||
- echo "variables[ALTERNATIVE_SOURCES]=true" >> version_details
|
|
||||||
- echo "variables[GITLAB_VERSION]=${CI_COMMIT_SHA}" >> version_details
|
|
||||||
# Collect version details of all components
|
|
||||||
- for f in *_VERSION; do echo "variables[$f]=$(cat $f)" >> version_details; done
|
|
||||||
# Trigger the API and pass values collected above as parameters to it
|
|
||||||
- cat version_details | tr '\n' '&' | curl -X POST https://gitlab.com/api/v4/projects/20699/trigger/pipeline --data-binary @-
|
|
||||||
- rm version_details
|
|
||||||
|
|
||||||
# Prepare and merge knapsack tests
|
# Prepare and merge knapsack tests
|
||||||
knapsack:
|
knapsack:
|
||||||
|
@ -166,6 +182,11 @@ knapsack:
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
stage: prepare
|
stage: prepare
|
||||||
|
cache:
|
||||||
|
key: knapsack
|
||||||
|
paths:
|
||||||
|
- knapsack/
|
||||||
|
policy: pull
|
||||||
script:
|
script:
|
||||||
- mkdir -p knapsack/${CI_PROJECT_NAME}/
|
- mkdir -p knapsack/${CI_PROJECT_NAME}/
|
||||||
- wget -O $KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${KNAPSACK_S3_BUCKET}.s3.amazonaws.com/$KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $KNAPSACK_RSPEC_SUITE_REPORT_PATH
|
- wget -O $KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${KNAPSACK_S3_BUCKET}.s3.amazonaws.com/$KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $KNAPSACK_RSPEC_SUITE_REPORT_PATH
|
||||||
|
@ -176,28 +197,34 @@ knapsack:
|
||||||
update-knapsack:
|
update-knapsack:
|
||||||
<<: *knapsack-state
|
<<: *knapsack-state
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
|
<<: *only-canonical-masters
|
||||||
stage: post-test
|
stage: post-test
|
||||||
|
cache:
|
||||||
|
key: knapsack
|
||||||
|
paths:
|
||||||
|
- knapsack/
|
||||||
|
policy: push
|
||||||
script:
|
script:
|
||||||
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_pg_node_*.json
|
- retry gem install fog-aws mime-types
|
||||||
- scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach_pg_node_*.json
|
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
|
||||||
|
- scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach-pg_node_*.json
|
||||||
- '[[ -z ${KNAPSACK_S3_BUCKET} ]] || scripts/sync-reports put $KNAPSACK_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH'
|
- '[[ -z ${KNAPSACK_S3_BUCKET} ]] || scripts/sync-reports put $KNAPSACK_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH'
|
||||||
- rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
|
- rm -f knapsack/${CI_PROJECT_NAME}/*_node_*.json
|
||||||
only:
|
|
||||||
- master@gitlab-org/gitlab-ce
|
|
||||||
- master@gitlab-org/gitlab-ee
|
|
||||||
- master@gitlab/gitlabhq
|
|
||||||
- master@gitlab/gitlab-ee
|
|
||||||
|
|
||||||
setup-test-env:
|
setup-test-env:
|
||||||
<<: *use-pg
|
<<: *use-pg
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
stage: prepare
|
stage: prepare
|
||||||
|
cache:
|
||||||
|
<<: *default-cache
|
||||||
script:
|
script:
|
||||||
- node --version
|
- node --version
|
||||||
- yarn install --pure-lockfile
|
- yarn install --pure-lockfile --cache-folder .yarn-cache
|
||||||
|
- bundle exec rake gettext:po_to_json
|
||||||
- bundle exec rake gitlab:assets:compile
|
- bundle exec rake gitlab:assets:compile
|
||||||
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
|
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
|
||||||
|
- scripts/gitaly-test-build # Do not use 'bundle exec' here
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 7d
|
expire_in: 7d
|
||||||
paths:
|
paths:
|
||||||
|
@ -205,81 +232,82 @@ setup-test-env:
|
||||||
- public/assets
|
- public/assets
|
||||||
- tmp/tests
|
- tmp/tests
|
||||||
|
|
||||||
rspec pg 0 20: *rspec-knapsack-pg
|
rspec-pg 0 25: *rspec-knapsack-pg
|
||||||
rspec pg 1 20: *rspec-knapsack-pg
|
rspec-pg 1 25: *rspec-knapsack-pg
|
||||||
rspec pg 2 20: *rspec-knapsack-pg
|
rspec-pg 2 25: *rspec-knapsack-pg
|
||||||
rspec pg 3 20: *rspec-knapsack-pg
|
rspec-pg 3 25: *rspec-knapsack-pg
|
||||||
rspec pg 4 20: *rspec-knapsack-pg
|
rspec-pg 4 25: *rspec-knapsack-pg
|
||||||
rspec pg 5 20: *rspec-knapsack-pg
|
rspec-pg 5 25: *rspec-knapsack-pg
|
||||||
rspec pg 6 20: *rspec-knapsack-pg
|
rspec-pg 6 25: *rspec-knapsack-pg
|
||||||
rspec pg 7 20: *rspec-knapsack-pg
|
rspec-pg 7 25: *rspec-knapsack-pg
|
||||||
rspec pg 8 20: *rspec-knapsack-pg
|
rspec-pg 8 25: *rspec-knapsack-pg
|
||||||
rspec pg 9 20: *rspec-knapsack-pg
|
rspec-pg 9 25: *rspec-knapsack-pg
|
||||||
rspec pg 10 20: *rspec-knapsack-pg
|
rspec-pg 10 25: *rspec-knapsack-pg
|
||||||
rspec pg 11 20: *rspec-knapsack-pg
|
rspec-pg 11 25: *rspec-knapsack-pg
|
||||||
rspec pg 12 20: *rspec-knapsack-pg
|
rspec-pg 12 25: *rspec-knapsack-pg
|
||||||
rspec pg 13 20: *rspec-knapsack-pg
|
rspec-pg 13 25: *rspec-knapsack-pg
|
||||||
rspec pg 14 20: *rspec-knapsack-pg
|
rspec-pg 14 25: *rspec-knapsack-pg
|
||||||
rspec pg 15 20: *rspec-knapsack-pg
|
rspec-pg 15 25: *rspec-knapsack-pg
|
||||||
rspec pg 16 20: *rspec-knapsack-pg
|
rspec-pg 16 25: *rspec-knapsack-pg
|
||||||
rspec pg 17 20: *rspec-knapsack-pg
|
rspec-pg 17 25: *rspec-knapsack-pg
|
||||||
rspec pg 18 20: *rspec-knapsack-pg
|
rspec-pg 18 25: *rspec-knapsack-pg
|
||||||
rspec pg 19 20: *rspec-knapsack-pg
|
rspec-pg 19 25: *rspec-knapsack-pg
|
||||||
|
rspec-pg 20 25: *rspec-knapsack-pg
|
||||||
|
rspec-pg 21 25: *rspec-knapsack-pg
|
||||||
|
rspec-pg 22 25: *rspec-knapsack-pg
|
||||||
|
rspec-pg 23 25: *rspec-knapsack-pg
|
||||||
|
rspec-pg 24 25: *rspec-knapsack-pg
|
||||||
|
|
||||||
rspec mysql 0 20: *rspec-knapsack-mysql
|
rspec-mysql 0 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 1 20: *rspec-knapsack-mysql
|
rspec-mysql 1 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 2 20: *rspec-knapsack-mysql
|
rspec-mysql 2 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 3 20: *rspec-knapsack-mysql
|
rspec-mysql 3 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 4 20: *rspec-knapsack-mysql
|
rspec-mysql 4 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 5 20: *rspec-knapsack-mysql
|
rspec-mysql 5 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 6 20: *rspec-knapsack-mysql
|
rspec-mysql 6 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 7 20: *rspec-knapsack-mysql
|
rspec-mysql 7 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 8 20: *rspec-knapsack-mysql
|
rspec-mysql 8 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 9 20: *rspec-knapsack-mysql
|
rspec-mysql 9 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 10 20: *rspec-knapsack-mysql
|
rspec-mysql 10 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 11 20: *rspec-knapsack-mysql
|
rspec-mysql 11 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 12 20: *rspec-knapsack-mysql
|
rspec-mysql 12 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 13 20: *rspec-knapsack-mysql
|
rspec-mysql 13 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 14 20: *rspec-knapsack-mysql
|
rspec-mysql 14 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 15 20: *rspec-knapsack-mysql
|
rspec-mysql 15 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 16 20: *rspec-knapsack-mysql
|
rspec-mysql 16 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 17 20: *rspec-knapsack-mysql
|
rspec-mysql 17 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 18 20: *rspec-knapsack-mysql
|
rspec-mysql 18 25: *rspec-knapsack-mysql
|
||||||
rspec mysql 19 20: *rspec-knapsack-mysql
|
rspec-mysql 19 25: *rspec-knapsack-mysql
|
||||||
|
rspec-mysql 20 25: *rspec-knapsack-mysql
|
||||||
|
rspec-mysql 21 25: *rspec-knapsack-mysql
|
||||||
|
rspec-mysql 22 25: *rspec-knapsack-mysql
|
||||||
|
rspec-mysql 23 25: *rspec-knapsack-mysql
|
||||||
|
rspec-mysql 24 25: *rspec-knapsack-mysql
|
||||||
|
|
||||||
spinach pg 0 10: *spinach-knapsack-pg
|
spinach-pg 0 5: *spinach-knapsack-pg
|
||||||
spinach pg 1 10: *spinach-knapsack-pg
|
spinach-pg 1 5: *spinach-knapsack-pg
|
||||||
spinach pg 2 10: *spinach-knapsack-pg
|
spinach-pg 2 5: *spinach-knapsack-pg
|
||||||
spinach pg 3 10: *spinach-knapsack-pg
|
spinach-pg 3 5: *spinach-knapsack-pg
|
||||||
spinach pg 4 10: *spinach-knapsack-pg
|
spinach-pg 4 5: *spinach-knapsack-pg
|
||||||
spinach pg 5 10: *spinach-knapsack-pg
|
|
||||||
spinach pg 6 10: *spinach-knapsack-pg
|
|
||||||
spinach pg 7 10: *spinach-knapsack-pg
|
|
||||||
spinach pg 8 10: *spinach-knapsack-pg
|
|
||||||
spinach pg 9 10: *spinach-knapsack-pg
|
|
||||||
|
|
||||||
spinach mysql 0 10: *spinach-knapsack-mysql
|
spinach-mysql 0 5: *spinach-knapsack-mysql
|
||||||
spinach mysql 1 10: *spinach-knapsack-mysql
|
spinach-mysql 1 5: *spinach-knapsack-mysql
|
||||||
spinach mysql 2 10: *spinach-knapsack-mysql
|
spinach-mysql 2 5: *spinach-knapsack-mysql
|
||||||
spinach mysql 3 10: *spinach-knapsack-mysql
|
spinach-mysql 3 5: *spinach-knapsack-mysql
|
||||||
spinach mysql 4 10: *spinach-knapsack-mysql
|
spinach-mysql 4 5: *spinach-knapsack-mysql
|
||||||
spinach mysql 5 10: *spinach-knapsack-mysql
|
|
||||||
spinach mysql 6 10: *spinach-knapsack-mysql
|
|
||||||
spinach mysql 7 10: *spinach-knapsack-mysql
|
|
||||||
spinach mysql 8 10: *spinach-knapsack-mysql
|
|
||||||
spinach mysql 9 10: *spinach-knapsack-mysql
|
|
||||||
|
|
||||||
# Other generic tests
|
# Static analysis jobs
|
||||||
.ruby-static-analysis: &ruby-static-analysis
|
.ruby-static-analysis: &ruby-static-analysis
|
||||||
|
<<: *pull-cache
|
||||||
variables:
|
variables:
|
||||||
SIMPLECOV: "false"
|
SIMPLECOV: "false"
|
||||||
SETUP_DB: "false"
|
SETUP_DB: "false"
|
||||||
USE_BUNDLE_INSTALL: "true"
|
|
||||||
|
|
||||||
.rake-exec: &rake-exec
|
.rake-exec: &rake-exec
|
||||||
<<: *ruby-static-analysis
|
<<: *ruby-static-analysis
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- bundle exec rake $CI_JOB_NAME
|
- bundle exec rake $CI_JOB_NAME
|
||||||
|
@ -290,17 +318,15 @@ static-analysis:
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- rm -r node_modules
|
|
||||||
- yarn install --pure-lockfile
|
|
||||||
- scripts/static-analysis
|
- scripts/static-analysis
|
||||||
|
|
||||||
# Documentation checks:
|
# Documentation checks:
|
||||||
# - Check validity of relative links
|
# - Check validity of relative links
|
||||||
# - Make sure cURL examples in API docs use the full switches
|
# - Make sure cURL examples in API docs use the full switches
|
||||||
docs lint:
|
docs lint:
|
||||||
|
<<: *dedicated-runner
|
||||||
image: "registry.gitlab.com/gitlab-org/gitlab-build-images:nanoc-bootstrap-ruby-2.4-alpine"
|
image: "registry.gitlab.com/gitlab-org/gitlab-build-images:nanoc-bootstrap-ruby-2.4-alpine"
|
||||||
stage: test
|
stage: test
|
||||||
<<: *dedicated-runner
|
|
||||||
cache: {}
|
cache: {}
|
||||||
dependencies: []
|
dependencies: []
|
||||||
before_script: []
|
before_script: []
|
||||||
|
@ -319,7 +345,7 @@ downtime_check:
|
||||||
- master
|
- master
|
||||||
- tags
|
- tags
|
||||||
- /^[\d-]+-stable(-ee)?$/
|
- /^[\d-]+-stable(-ee)?$/
|
||||||
- /^docs\/*/
|
- /(^docs[\/-].*|.*-docs$)/
|
||||||
|
|
||||||
ee_compat_check:
|
ee_compat_check:
|
||||||
<<: *rake-exec
|
<<: *rake-exec
|
||||||
|
@ -328,7 +354,7 @@ ee_compat_check:
|
||||||
except:
|
except:
|
||||||
- master
|
- master
|
||||||
- tags
|
- tags
|
||||||
- /^[\d-]+-stable(-ee)?$/
|
- /^[\d-]+-stable(-ee)?/
|
||||||
allow_failure: yes
|
allow_failure: yes
|
||||||
cache:
|
cache:
|
||||||
key: "ee_compat_check_repo"
|
key: "ee_compat_check_repo"
|
||||||
|
@ -341,67 +367,96 @@ ee_compat_check:
|
||||||
paths:
|
paths:
|
||||||
- ee_compat_check/patches/*.patch
|
- ee_compat_check/patches/*.patch
|
||||||
|
|
||||||
|
# DB migration, rollback, and seed jobs
|
||||||
.db-migrate-reset: &db-migrate-reset
|
.db-migrate-reset: &db-migrate-reset
|
||||||
stage: test
|
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
|
stage: test
|
||||||
script:
|
script:
|
||||||
- bundle exec rake db:migrate:reset
|
- bundle exec rake db:migrate:reset
|
||||||
|
|
||||||
rake pg db:migrate:reset:
|
db:migrate:reset-pg:
|
||||||
<<: *db-migrate-reset
|
<<: *db-migrate-reset
|
||||||
<<: *use-pg
|
<<: *use-pg
|
||||||
|
|
||||||
rake mysql db:migrate:reset:
|
db:migrate:reset-mysql:
|
||||||
<<: *db-migrate-reset
|
<<: *db-migrate-reset
|
||||||
<<: *use-mysql
|
<<: *use-mysql
|
||||||
|
|
||||||
.db-rollback: &db-rollback
|
.migration-paths: &migration-paths
|
||||||
|
<<: *dedicated-runner
|
||||||
|
<<: *only-canonical-masters
|
||||||
|
<<: *pull-cache
|
||||||
stage: test
|
stage: test
|
||||||
|
variables:
|
||||||
|
SETUP_DB: "false"
|
||||||
|
script:
|
||||||
|
- git fetch origin v8.14.10
|
||||||
|
- git checkout -f FETCH_HEAD
|
||||||
|
- bundle install $BUNDLE_INSTALL_FLAGS
|
||||||
|
- cp config/gitlab.yml.example config/gitlab.yml
|
||||||
|
- bundle exec rake db:drop db:create db:schema:load db:seed_fu
|
||||||
|
- git checkout $CI_COMMIT_SHA
|
||||||
|
- bundle install $BUNDLE_INSTALL_FLAGS
|
||||||
|
- . scripts/prepare_build.sh
|
||||||
|
- bundle exec rake db:migrate
|
||||||
|
|
||||||
|
migration:path-pg:
|
||||||
|
<<: *migration-paths
|
||||||
|
<<: *use-pg
|
||||||
|
|
||||||
|
migration:path-mysql:
|
||||||
|
<<: *migration-paths
|
||||||
|
<<: *use-mysql
|
||||||
|
|
||||||
|
.db-rollback: &db-rollback
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
|
stage: test
|
||||||
script:
|
script:
|
||||||
- bundle exec rake db:rollback STEP=120
|
- bundle exec rake db:rollback STEP=120
|
||||||
- bundle exec rake db:migrate
|
- bundle exec rake db:migrate
|
||||||
|
|
||||||
rake pg db:rollback:
|
db:rollback-pg:
|
||||||
<<: *db-rollback
|
<<: *db-rollback
|
||||||
<<: *use-pg
|
<<: *use-pg
|
||||||
|
|
||||||
rake mysql db:rollback:
|
db:rollback-mysql:
|
||||||
<<: *db-rollback
|
<<: *db-rollback
|
||||||
<<: *use-mysql
|
<<: *use-mysql
|
||||||
|
|
||||||
.db-seed_fu: &db-seed_fu
|
.db-seed_fu: &db-seed_fu
|
||||||
stage: test
|
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
|
stage: test
|
||||||
variables:
|
variables:
|
||||||
SIZE: "1"
|
SIZE: "1"
|
||||||
SETUP_DB: "false"
|
|
||||||
RAILS_ENV: "development"
|
|
||||||
script:
|
script:
|
||||||
- git clone https://gitlab.com/gitlab-org/gitlab-test.git
|
- cp -R db/fixtures/development db/fixtures/test
|
||||||
/home/git/repositories/gitlab-org/gitlab-test.git
|
- bundle exec rake db:seed_fu
|
||||||
- bundle exec rake db:setup db:seed_fu
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: on_failure
|
when: on_failure
|
||||||
expire_in: 1d
|
expire_in: 1d
|
||||||
paths:
|
paths:
|
||||||
- log/development.log
|
- log/development.log
|
||||||
|
|
||||||
rake pg db:seed_fu:
|
db:seed_fu-pg:
|
||||||
<<: *db-seed_fu
|
<<: *db-seed_fu
|
||||||
<<: *use-pg
|
<<: *use-pg
|
||||||
|
|
||||||
rake mysql db:seed_fu:
|
db:seed_fu-mysql:
|
||||||
<<: *db-seed_fu
|
<<: *db-seed_fu
|
||||||
<<: *use-mysql
|
<<: *use-mysql
|
||||||
|
|
||||||
rake gitlab:assets:compile:
|
# Frontend-related jobs
|
||||||
stage: test
|
gitlab:assets:compile:
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
|
stage: test
|
||||||
dependencies: []
|
dependencies: []
|
||||||
variables:
|
variables:
|
||||||
NODE_ENV: "production"
|
NODE_ENV: "production"
|
||||||
|
@ -410,65 +465,63 @@ rake gitlab:assets:compile:
|
||||||
USE_DB: "false"
|
USE_DB: "false"
|
||||||
SKIP_STORAGE_VALIDATION: "true"
|
SKIP_STORAGE_VALIDATION: "true"
|
||||||
WEBPACK_REPORT: "true"
|
WEBPACK_REPORT: "true"
|
||||||
|
NO_COMPRESSION: "true"
|
||||||
script:
|
script:
|
||||||
- bundle exec rake yarn:install gitlab:assets:compile
|
- yarn install --pure-lockfile --production --cache-folder .yarn-cache
|
||||||
|
- bundle exec rake gettext:po_to_json
|
||||||
|
- bundle exec rake gitlab:assets:compile
|
||||||
artifacts:
|
artifacts:
|
||||||
name: webpack-report
|
name: webpack-report
|
||||||
expire_in: 31d
|
expire_in: 31d
|
||||||
paths:
|
paths:
|
||||||
- webpack-report/
|
- webpack-report/
|
||||||
|
|
||||||
rake karma:
|
karma:
|
||||||
stage: test
|
|
||||||
<<: *use-pg
|
<<: *use-pg
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
|
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-chrome-59.0-node-7.1-postgresql-9.6"
|
||||||
|
stage: test
|
||||||
variables:
|
variables:
|
||||||
BABEL_ENV: "coverage"
|
BABEL_ENV: "coverage"
|
||||||
|
CHROME_LOG_FILE: "chrome_debug.log"
|
||||||
script:
|
script:
|
||||||
- rm -r node_modules
|
- scripts/gitaly-test-spawn
|
||||||
- yarn install --pure-lockfile
|
- bundle exec rake gettext:po_to_json
|
||||||
- bundle exec rake karma
|
- bundle exec rake karma
|
||||||
coverage: '/^Statements *: (\d+\.\d+%)/'
|
coverage: '/^Statements *: (\d+\.\d+%)/'
|
||||||
artifacts:
|
artifacts:
|
||||||
name: coverage-javascript
|
name: coverage-javascript
|
||||||
expire_in: 31d
|
expire_in: 31d
|
||||||
|
when: always
|
||||||
paths:
|
paths:
|
||||||
|
- chrome_debug.log
|
||||||
- coverage-javascript/
|
- coverage-javascript/
|
||||||
|
|
||||||
.migration-paths: &migration-paths
|
codeclimate:
|
||||||
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
|
before_script: []
|
||||||
|
image: docker:latest
|
||||||
stage: test
|
stage: test
|
||||||
<<: *dedicated-runner
|
|
||||||
variables:
|
variables:
|
||||||
SETUP_DB: "false"
|
SETUP_DB: "false"
|
||||||
only:
|
DOCKER_DRIVER: overlay
|
||||||
- master@gitlab-org/gitlab-ce
|
services:
|
||||||
- master@gitlab-org/gitlab-ee
|
- docker:dind
|
||||||
- master@gitlab/gitlabhq
|
|
||||||
- master@gitlab/gitlab-ee
|
|
||||||
script:
|
script:
|
||||||
- git fetch origin v8.14.10
|
- docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate analyze -f json > raw_codeclimate.json
|
||||||
- git checkout -f FETCH_HEAD
|
- cat raw_codeclimate.json | docker run -i stedolan/jq -c 'map({check_name,fingerprint,location})' > codeclimate.json
|
||||||
- bundle install $BUNDLE_INSTALL_FLAGS
|
artifacts:
|
||||||
- bundle exec rake db:drop db:create db:schema:load db:seed_fu
|
paths: [codeclimate.json]
|
||||||
- git checkout $CI_COMMIT_SHA
|
|
||||||
- bundle install $BUNDLE_INSTALL_FLAGS
|
|
||||||
- . scripts/prepare_build.sh
|
|
||||||
- bundle exec rake db:migrate
|
|
||||||
|
|
||||||
migration pg paths:
|
|
||||||
<<: *migration-paths
|
|
||||||
<<: *use-pg
|
|
||||||
|
|
||||||
migration mysql paths:
|
|
||||||
<<: *migration-paths
|
|
||||||
<<: *use-mysql
|
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
stage: post-test
|
|
||||||
services: []
|
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
|
stage: post-test
|
||||||
|
services: []
|
||||||
variables:
|
variables:
|
||||||
SETUP_DB: "false"
|
SETUP_DB: "false"
|
||||||
USE_BUNDLE_INSTALL: "true"
|
USE_BUNDLE_INSTALL: "true"
|
||||||
|
@ -485,7 +538,10 @@ coverage:
|
||||||
lint:javascript:report:
|
lint:javascript:report:
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
<<: *except-docs
|
<<: *except-docs
|
||||||
|
<<: *pull-cache
|
||||||
stage: post-test
|
stage: post-test
|
||||||
|
dependencies:
|
||||||
|
- setup-test-env
|
||||||
before_script: []
|
before_script: []
|
||||||
script:
|
script:
|
||||||
- find app/ spec/ -name '*.js' -exec sed --in-place 's|/\* eslint-disable .*\*/||' {} \; # run report over all files
|
- find app/ spec/ -name '*.js' -exec sed --in-place 's|/\* eslint-disable .*\*/||' {} \; # run report over all files
|
||||||
|
@ -496,33 +552,15 @@ lint:javascript:report:
|
||||||
paths:
|
paths:
|
||||||
- eslint-report.html
|
- eslint-report.html
|
||||||
|
|
||||||
# Trigger docs build
|
|
||||||
# https://gitlab.com/gitlab-com/doc-gitlab-com/blob/master/README.md#deployment-process
|
|
||||||
trigger_docs:
|
|
||||||
stage: post-test
|
|
||||||
image: "alpine"
|
|
||||||
<<: *dedicated-runner
|
|
||||||
before_script:
|
|
||||||
- apk update && apk add curl
|
|
||||||
variables:
|
|
||||||
GIT_STRATEGY: "none"
|
|
||||||
cache: {}
|
|
||||||
artifacts: {}
|
|
||||||
script:
|
|
||||||
- "HTTP_STATUS=$(curl -X POST -F token=${DOCS_TRIGGER_TOKEN} -F ref=master -F variables[PROJECT]=${CI_PROJECT_NAME} --silent --output curl.log --write-out '%{http_code}' https://gitlab.com/api/v3/projects/1794617/trigger/builds)"
|
|
||||||
- if [ "${HTTP_STATUS}" -ne "201" ]; then echo "Error ${HTTP_STATUS}"; cat curl.log; echo; exit 1; fi
|
|
||||||
only:
|
|
||||||
- master@gitlab-org/gitlab-ce
|
|
||||||
- master@gitlab-org/gitlab-ee
|
|
||||||
|
|
||||||
pages:
|
pages:
|
||||||
|
<<: *dedicated-runner
|
||||||
|
<<: *pull-cache
|
||||||
before_script: []
|
before_script: []
|
||||||
stage: pages
|
stage: pages
|
||||||
<<: *dedicated-runner
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- coverage
|
- coverage
|
||||||
- rake karma
|
- karma
|
||||||
- rake gitlab:assets:compile
|
- gitlab:assets:compile
|
||||||
- lint:javascript:report
|
- lint:javascript:report
|
||||||
script:
|
script:
|
||||||
- mv public/ .public/
|
- mv public/ .public/
|
||||||
|
@ -542,6 +580,7 @@ pages:
|
||||||
# rubygems.org in the future.
|
# rubygems.org in the future.
|
||||||
cache gems:
|
cache gems:
|
||||||
<<: *dedicated-runner
|
<<: *dedicated-runner
|
||||||
|
<<: *pull-cache
|
||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
variables:
|
variables:
|
||||||
|
@ -554,3 +593,11 @@ cache gems:
|
||||||
only:
|
only:
|
||||||
- master@gitlab-org/gitlab-ce
|
- master@gitlab-org/gitlab-ce
|
||||||
- master@gitlab-org/gitlab-ee
|
- master@gitlab-org/gitlab-ee
|
||||||
|
|
||||||
|
gitlab_git_test:
|
||||||
|
<<: *pull-cache
|
||||||
|
<<: *except-docs
|
||||||
|
variables:
|
||||||
|
SETUP_DB: "false"
|
||||||
|
script:
|
||||||
|
- spec/support/prepare-gitlab-git-test-for-commit --check-for-changes
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
Please read this!
|
Please read this!
|
||||||
|
|
||||||
Before opening a new issue, make sure to search for keywords in the issues
|
Before opening a new issue, make sure to search for keywords in the issues
|
||||||
filtered by the "regression" or "bug" label:
|
filtered by the "regression" or "bug" label.
|
||||||
|
|
||||||
|
For the Community Edition issue tracker:
|
||||||
|
|
||||||
- https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=regression
|
- https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=regression
|
||||||
- https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=bug
|
- https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=bug
|
||||||
|
|
||||||
|
For the Enterprise Edition issue tracker:
|
||||||
|
|
||||||
|
- https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name%5B%5D=regression
|
||||||
|
- https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name%5B%5D=bug
|
||||||
|
|
||||||
and verify the issue you're about to submit isn't a duplicate.
|
and verify the issue you're about to submit isn't a duplicate.
|
||||||
|
|
||||||
Please remove this notice if you're confident your issue isn't a duplicate.
|
Please remove this notice if you're confident your issue isn't a duplicate.
|
||||||
|
@ -20,6 +27,12 @@ Please remove this notice if you're confident your issue isn't a duplicate.
|
||||||
|
|
||||||
(How one can reproduce the issue - this is very important)
|
(How one can reproduce the issue - this is very important)
|
||||||
|
|
||||||
|
### Example Project
|
||||||
|
|
||||||
|
(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report)
|
||||||
|
|
||||||
|
(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version)
|
||||||
|
|
||||||
### What is the current *bug* behavior?
|
### What is the current *bug* behavior?
|
||||||
|
|
||||||
(What actually happens)
|
(What actually happens)
|
||||||
|
@ -40,6 +53,7 @@ logs, and code as it's very hard to read otherwise.)
|
||||||
#### Results of GitLab environment info
|
#### Results of GitLab environment info
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
<summary>Expand for output related to GitLab environment info</summary>
|
||||||
<pre>
|
<pre>
|
||||||
|
|
||||||
(For installations with omnibus-gitlab package run and paste the output of:
|
(For installations with omnibus-gitlab package run and paste the output of:
|
||||||
|
@ -54,6 +68,7 @@ logs, and code as it's very hard to read otherwise.)
|
||||||
#### Results of GitLab application Check
|
#### Results of GitLab application Check
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
<summary>Expand for output related to the GitLab application check</summary>
|
||||||
<pre>
|
<pre>
|
||||||
|
|
||||||
(For installations with omnibus-gitlab package run and paste the output of:
|
(For installations with omnibus-gitlab package run and paste the output of:
|
||||||
|
|
|
@ -3,8 +3,14 @@ Please read this!
|
||||||
Before opening a new issue, make sure to search for keywords in the issues
|
Before opening a new issue, make sure to search for keywords in the issues
|
||||||
filtered by the "feature proposal" label:
|
filtered by the "feature proposal" label:
|
||||||
|
|
||||||
|
For the Community Edition issue tracker:
|
||||||
|
|
||||||
- https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=feature+proposal
|
- https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=feature+proposal
|
||||||
|
|
||||||
|
For the Enterprise Edition issue tracker:
|
||||||
|
|
||||||
|
- https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name%5B%5D=feature+proposal
|
||||||
|
|
||||||
and verify the issue you're about to submit isn't a duplicate.
|
and verify the issue you're about to submit isn't a duplicate.
|
||||||
|
|
||||||
Please remove this notice if you're confident your issue isn't a duplicate.
|
Please remove this notice if you're confident your issue isn't a duplicate.
|
||||||
|
@ -21,12 +27,24 @@ Please remove this notice if you're confident your issue isn't a duplicate.
|
||||||
|
|
||||||
### Documentation blurb
|
### Documentation blurb
|
||||||
|
|
||||||
(Write the start of the documentation of this feature here, include:
|
#### Overview
|
||||||
|
|
||||||
1. Why should someone use it; what's the underlying problem.
|
What is it?
|
||||||
2. What is the solution.
|
Why should someone use this feature?
|
||||||
3. How does someone use this
|
What is the underlying (business) problem?
|
||||||
|
How do you use this feature?
|
||||||
|
|
||||||
During implementation, this can then be copied and used as a starter for the documentation.)
|
#### Use cases
|
||||||
|
|
||||||
|
Who is this for? Provide one or more use cases.
|
||||||
|
|
||||||
|
### Feature checklist
|
||||||
|
|
||||||
|
Make sure these are completed before closing the issue,
|
||||||
|
with a link to the relevant commit.
|
||||||
|
|
||||||
|
- [ ] [Feature assurance](https://about.gitlab.com/handbook/product/#feature-assurance)
|
||||||
|
- [ ] Documentation
|
||||||
|
- [ ] Added to [features.yml](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml)
|
||||||
|
|
||||||
/label ~"feature proposal"
|
/label ~"feature proposal"
|
|
@ -35,9 +35,21 @@ linters:
|
||||||
HtmlAttributes:
|
HtmlAttributes:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
IdNames:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
ImplicitDiv:
|
ImplicitDiv:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
InlineJavaScript:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
InlineStyles:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
InstanceVariables:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
LeadingCommentSpace:
|
LeadingCommentSpace:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
@ -54,6 +66,9 @@ linters:
|
||||||
ObjectReferenceAttributes:
|
ObjectReferenceAttributes:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
RepeatedId:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
RuboCop:
|
RuboCop:
|
||||||
enabled: false
|
enabled: false
|
||||||
# These cops are incredibly noisy when it comes to HAML templates, so we
|
# These cops are incredibly noisy when it comes to HAML templates, so we
|
||||||
|
@ -101,3 +116,6 @@ linters:
|
||||||
|
|
||||||
UnnecessaryStringOutput:
|
UnnecessaryStringOutput:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
|
ViewLength:
|
||||||
|
enabled: false
|
||||||
|
|
1
.nvmrc
Normal file
1
.nvmrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
7.5
|
2
.rspec
2
.rspec
|
@ -1,2 +0,0 @@
|
||||||
--color
|
|
||||||
--format Fuubar
|
|
498
.rubocop.yml
498
.rubocop.yml
|
@ -6,6 +6,7 @@ inherit_from: .rubocop_todo.yml
|
||||||
|
|
||||||
AllCops:
|
AllCops:
|
||||||
TargetRubyVersion: 2.3
|
TargetRubyVersion: 2.3
|
||||||
|
TargetRailsVersion: 4.2
|
||||||
# Cop names are not d§splayed in offense messages by default. Change behavior
|
# Cop names are not d§splayed in offense messages by default. Change behavior
|
||||||
# by overriding DisplayCopNames, or by giving the -D/--display-cop-names
|
# by overriding DisplayCopNames, or by giving the -D/--display-cop-names
|
||||||
# option.
|
# option.
|
||||||
|
@ -29,12 +30,221 @@ AllCops:
|
||||||
Bundler/OrderedGems:
|
Bundler/OrderedGems:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Style #######################################################################
|
# Layout ######################################################################
|
||||||
|
|
||||||
# Check indentation of private/protected visibility modifiers.
|
# Check indentation of private/protected visibility modifiers.
|
||||||
Style/AccessModifierIndentation:
|
Layout/AccessModifierIndentation:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Align the elements of an array literal if they span more than one line.
|
||||||
|
Layout/AlignArray:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Align the elements of a hash literal if they span more than one line.
|
||||||
|
Layout/AlignHash:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Here we check if the parameters on a multi-line method call or
|
||||||
|
# definition are aligned.
|
||||||
|
Layout/AlignParameters:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Put end statement of multiline block on its own line.
|
||||||
|
Layout/BlockEndNewline:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Indentation of when in a case/when/[else/]end.
|
||||||
|
Layout/CaseIndentation:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Indentation of comments.
|
||||||
|
Layout/CommentIndentation:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Multi-line method chaining should be done with leading dots.
|
||||||
|
Layout/DotPosition:
|
||||||
|
Enabled: true
|
||||||
|
EnforcedStyle: leading
|
||||||
|
|
||||||
|
# Align elses and elsifs correctly.
|
||||||
|
Layout/ElseAlignment:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Add an empty line after magic comments to separate them from code.
|
||||||
|
Layout/EmptyLineAfterMagicComment:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Use empty lines between defs.
|
||||||
|
Layout/EmptyLineBetweenDefs:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Don't use several empty lines in a row.
|
||||||
|
Layout/EmptyLines:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Keep blank lines around access modifiers.
|
||||||
|
Layout/EmptyLinesAroundAccessModifier:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Keeps track of empty lines around block bodies.
|
||||||
|
Layout/EmptyLinesAroundBlockBody:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Keeps track of empty lines around class bodies.
|
||||||
|
Layout/EmptyLinesAroundClassBody:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Keeps track of empty lines around exception handling keywords.
|
||||||
|
Layout/EmptyLinesAroundExceptionHandlingKeywords:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Keeps track of empty lines around method bodies.
|
||||||
|
Layout/EmptyLinesAroundMethodBody:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Keeps track of empty lines around module bodies.
|
||||||
|
Layout/EmptyLinesAroundModuleBody:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use Unix-style line endings.
|
||||||
|
Layout/EndOfLine:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks for a line break before the first parameter in a multi-line method
|
||||||
|
# parameter definition.
|
||||||
|
Layout/FirstMethodParameterLineBreak:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Keep indentation straight.
|
||||||
|
Layout/IndentationConsistency:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use 2 spaces for indentation.
|
||||||
|
Layout/IndentationWidth:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks the indentation of the first line of the right-hand-side of a
|
||||||
|
# multi-line assignment.
|
||||||
|
Layout/IndentAssignment:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# This cops checks the indentation of the here document bodies.
|
||||||
|
Layout/IndentHeredoc:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Comments should start with a space.
|
||||||
|
Layout/LeadingCommentSpace:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks that the closing brace in an array literal is either on the same line
|
||||||
|
# as the last array element, or a new line.
|
||||||
|
Layout/MultilineArrayBraceLayout:
|
||||||
|
Enabled: true
|
||||||
|
EnforcedStyle: symmetrical
|
||||||
|
|
||||||
|
# Ensures newlines after multiline block do statements.
|
||||||
|
Layout/MultilineBlockLayout:
|
||||||
|
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.
|
||||||
|
Layout/MultilineHashBraceLayout:
|
||||||
|
Enabled: true
|
||||||
|
EnforcedStyle: symmetrical
|
||||||
|
|
||||||
|
# Checks that the closing brace in a method call is either on the same line as
|
||||||
|
# the last method argument, or a new line.
|
||||||
|
Layout/MultilineMethodCallBraceLayout:
|
||||||
|
Enabled: false
|
||||||
|
EnforcedStyle: symmetrical
|
||||||
|
|
||||||
|
# Checks indentation of method calls with the dot operator that span more than
|
||||||
|
# one line.
|
||||||
|
Layout/MultilineMethodCallIndentation:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Checks that the closing brace in a method definition is symmetrical with
|
||||||
|
# respect to the opening brace and the method parameters.
|
||||||
|
Layout/MultilineMethodDefinitionBraceLayout:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Checks indentation of binary operations that span more than one line.
|
||||||
|
Layout/MultilineOperationIndentation:
|
||||||
|
Enabled: true
|
||||||
|
EnforcedStyle: indented
|
||||||
|
|
||||||
|
# Use spaces after colons.
|
||||||
|
Layout/SpaceAfterColon:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use spaces after commas.
|
||||||
|
Layout/SpaceAfterComma:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Do not put a space between a method name and the opening parenthesis in a
|
||||||
|
# method definition.
|
||||||
|
Layout/SpaceAfterMethodName:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Tracks redundant space after the ! operator.
|
||||||
|
Layout/SpaceAfterNot:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use spaces after semicolons.
|
||||||
|
Layout/SpaceAfterSemicolon:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use space around equals in parameter default
|
||||||
|
Layout/SpaceAroundEqualsInParameterDefault:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use a space around keywords if appropriate.
|
||||||
|
Layout/SpaceAroundKeyword:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use a single space around operators.
|
||||||
|
Layout/SpaceAroundOperators:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# No spaces before commas.
|
||||||
|
Layout/SpaceBeforeComma:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks for missing space between code and a comment on the same line.
|
||||||
|
Layout/SpaceBeforeComment:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# No spaces before semicolons.
|
||||||
|
Layout/SpaceBeforeSemicolon:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks for spaces inside square brackets.
|
||||||
|
Layout/SpaceInsideBrackets:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Use spaces inside hash literal braces - or don't.
|
||||||
|
Layout/SpaceInsideHashLiteralBraces:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# No spaces inside range literals.
|
||||||
|
Layout/SpaceInsideRangeLiteral:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks for padding/surrounding spaces inside string interpolation.
|
||||||
|
Layout/SpaceInsideStringInterpolation:
|
||||||
|
EnforcedStyle: no_space
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# No hard tabs.
|
||||||
|
Layout/Tab:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks trailing blank lines and final newline.
|
||||||
|
Layout/TrailingBlankLines:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
|
# Style #######################################################################
|
||||||
|
|
||||||
# Check the naming of accessor methods for get_/set_.
|
# Check the naming of accessor methods for get_/set_.
|
||||||
Style/AccessorMethodName:
|
Style/AccessorMethodName:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
@ -44,19 +254,6 @@ Style/Alias:
|
||||||
EnforcedStyle: prefer_alias_method
|
EnforcedStyle: prefer_alias_method
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# Align the elements of an array literal if they span more than one line.
|
|
||||||
Style/AlignArray:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Align the elements of a hash literal if they span more than one line.
|
|
||||||
Style/AlignHash:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Here we check if the parameters on a multi-line method call or
|
|
||||||
# definition are aligned.
|
|
||||||
Style/AlignParameters:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Whether `and` and `or` are banned only in conditionals (conditionals)
|
# Whether `and` and `or` are banned only in conditionals (conditionals)
|
||||||
# or completely (always).
|
# or completely (always).
|
||||||
Style/AndOr:
|
Style/AndOr:
|
||||||
|
@ -91,10 +288,6 @@ Style/BlockComments:
|
||||||
Style/BlockDelimiters:
|
Style/BlockDelimiters:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# Put end statement of multiline block on its own line.
|
|
||||||
Style/BlockEndNewline:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# This cop checks for braces around the last parameter in a method call
|
# This cop checks for braces around the last parameter in a method call
|
||||||
# if the last parameter is a hash.
|
# if the last parameter is a hash.
|
||||||
Style/BracesAroundHashParameters:
|
Style/BracesAroundHashParameters:
|
||||||
|
@ -104,10 +297,6 @@ Style/BracesAroundHashParameters:
|
||||||
Style/CaseEquality:
|
Style/CaseEquality:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Indentation of when in a case/when/[else/]end.
|
|
||||||
Style/CaseIndentation:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Checks for uses of character literals.
|
# Checks for uses of character literals.
|
||||||
Style/CharacterLiteral:
|
Style/CharacterLiteral:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
@ -142,10 +331,6 @@ Style/ColonMethodCall:
|
||||||
Style/CommentAnnotation:
|
Style/CommentAnnotation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Indentation of comments.
|
|
||||||
Style/CommentIndentation:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Check for `if` and `case` statements where each branch is used for
|
# Check for `if` and `case` statements where each branch is used for
|
||||||
# assignment to the same variable when using the return of the
|
# assignment to the same variable when using the return of the
|
||||||
# condition can be used instead.
|
# condition can be used instead.
|
||||||
|
@ -170,46 +355,10 @@ Style/Documentation:
|
||||||
Style/DoubleNegation:
|
Style/DoubleNegation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Align elses and elsifs correctly.
|
|
||||||
Style/ElseAlignment:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use empty lines between defs.
|
|
||||||
Style/EmptyLineBetweenDefs:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Don't use several empty lines in a row.
|
|
||||||
Style/EmptyLines:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Keep blank lines around access modifiers.
|
|
||||||
Style/EmptyLinesAroundAccessModifier:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Keeps track of empty lines around block bodies.
|
|
||||||
Style/EmptyLinesAroundBlockBody:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Keeps track of empty lines around class bodies.
|
|
||||||
Style/EmptyLinesAroundClassBody:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Keeps track of empty lines around method bodies.
|
|
||||||
Style/EmptyLinesAroundMethodBody:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Keeps track of empty lines around module bodies.
|
|
||||||
Style/EmptyLinesAroundModuleBody:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Avoid the use of END blocks.
|
# Avoid the use of END blocks.
|
||||||
Style/EndBlock:
|
Style/EndBlock:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# Use Unix-style line endings.
|
|
||||||
Style/EndOfLine:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Favor the use of Fixnum#even? && Fixnum#odd?
|
# Favor the use of Fixnum#even? && Fixnum#odd?
|
||||||
Style/EvenOdd:
|
Style/EvenOdd:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
@ -218,11 +367,6 @@ Style/EvenOdd:
|
||||||
Style/FileName:
|
Style/FileName:
|
||||||
Enabled: true
|
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: true
|
Enabled: true
|
||||||
|
@ -231,6 +375,10 @@ Style/FlipFlop:
|
||||||
Style/For:
|
Style/For:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Use a consistent style for format string tokens.
|
||||||
|
Style/FormatStringToken:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Checks if there is a magic comment to enforce string literals
|
# Checks if there is a magic comment to enforce string literals
|
||||||
Style/FrozenStringLiteralComment:
|
Style/FrozenStringLiteralComment:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
@ -256,31 +404,19 @@ Style/IdenticalConditionalBranches:
|
||||||
Style/IfWithSemicolon:
|
Style/IfWithSemicolon:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# Checks the indentation of the first line of the right-hand-side of a
|
|
||||||
# multi-line assignment.
|
|
||||||
Style/IndentAssignment:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Keep indentation straight.
|
|
||||||
Style/IndentationConsistency:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use 2 spaces for indentation.
|
|
||||||
Style/IndentationWidth:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use Kernel#loop for infinite loops.
|
# Use Kernel#loop for infinite loops.
|
||||||
Style/InfiniteLoop:
|
Style/InfiniteLoop:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Use the inverse method instead of `!.method`
|
||||||
|
# if an inverse method is defined.
|
||||||
|
Style/InverseMethods:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Use lambda.call(...) instead of lambda.(...).
|
# Use lambda.call(...) instead of lambda.(...).
|
||||||
Style/LambdaCall:
|
Style/LambdaCall:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# Comments should start with a space.
|
|
||||||
Style/LeadingCommentSpace:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# 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: true
|
Enabled: true
|
||||||
|
@ -293,55 +429,23 @@ Style/MethodName:
|
||||||
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: true
|
|
||||||
EnforcedStyle: symmetrical
|
|
||||||
|
|
||||||
# Avoid multi-line chains of blocks.
|
# Avoid multi-line chains of blocks.
|
||||||
Style/MultilineBlockChain:
|
Style/MultilineBlockChain:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# Ensures newlines after multiline block do statements.
|
|
||||||
Style/MultilineBlockLayout:
|
|
||||||
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: true
|
|
||||||
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
|
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
|
|
||||||
EnforcedStyle: symmetrical
|
|
||||||
|
|
||||||
# Checks indentation of method calls with the dot operator that span more than
|
|
||||||
# one line.
|
|
||||||
Style/MultilineMethodCallIndentation:
|
|
||||||
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.
|
|
||||||
Style/MultilineOperationIndentation:
|
|
||||||
Enabled: true
|
|
||||||
EnforcedStyle: indented
|
|
||||||
|
|
||||||
# Avoid multi-line `? :` (the ternary operator), use if/unless instead.
|
# Avoid multi-line `? :` (the ternary operator), use if/unless instead.
|
||||||
Style/MultilineTernaryOperator:
|
Style/MultilineTernaryOperator:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Avoid comparing a variable with multiple items in a conditional,
|
||||||
|
# use Array#include? instead.
|
||||||
|
Style/MultipleComparison:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# This cop checks whether some constant value isn't a
|
# This cop checks whether some constant value isn't a
|
||||||
# mutable literal (e.g. array or hash).
|
# mutable literal (e.g. array or hash).
|
||||||
Style/MutableConstant:
|
Style/MutableConstant:
|
||||||
|
@ -390,6 +494,15 @@ Style/OpMethod:
|
||||||
Style/ParenthesesAroundCondition:
|
Style/ParenthesesAroundCondition:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# This cop (by default) checks for uses of methods Hash#has_key? and
|
||||||
|
# Hash#has_value? where it enforces Hash#key? and Hash#value?
|
||||||
|
# It is configurable to enforce the inverse, using `verbose` method
|
||||||
|
# names also.
|
||||||
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
|
# SupportedStyles: short, verbose
|
||||||
|
Style/PreferredHashMethods:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Checks for an obsolete RuntimeException argument in raise/fail.
|
# Checks for an obsolete RuntimeException argument in raise/fail.
|
||||||
Style/RedundantException:
|
Style/RedundantException:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
@ -407,68 +520,6 @@ Style/SignalException:
|
||||||
EnforcedStyle: only_raise
|
EnforcedStyle: only_raise
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# Use spaces after colons.
|
|
||||||
Style/SpaceAfterColon:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use spaces after commas.
|
|
||||||
Style/SpaceAfterComma:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Do not put a space between a method name and the opening parenthesis in a
|
|
||||||
# method definition.
|
|
||||||
Style/SpaceAfterMethodName:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Tracks redundant space after the ! operator.
|
|
||||||
Style/SpaceAfterNot:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use spaces after semicolons.
|
|
||||||
Style/SpaceAfterSemicolon:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use space around equals in parameter default
|
|
||||||
Style/SpaceAroundEqualsInParameterDefault:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use a space around keywords if appropriate.
|
|
||||||
Style/SpaceAroundKeyword:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use a single space around operators.
|
|
||||||
Style/SpaceAroundOperators:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# No spaces before commas.
|
|
||||||
Style/SpaceBeforeComma:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Checks for missing space between code and a comment on the same line.
|
|
||||||
Style/SpaceBeforeComment:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# No spaces before semicolons.
|
|
||||||
Style/SpaceBeforeSemicolon:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Checks for spaces inside square brackets.
|
|
||||||
Style/SpaceInsideBrackets:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Use spaces inside hash literal braces - or don't.
|
|
||||||
Style/SpaceInsideHashLiteralBraces:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# No spaces inside range literals.
|
|
||||||
Style/SpaceInsideRangeLiteral:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Checks for padding/surrounding spaces inside string interpolation.
|
|
||||||
Style/SpaceInsideStringInterpolation:
|
|
||||||
EnforcedStyle: no_space
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# Check for the usage of parentheses around stabby lambda arguments.
|
# Check for the usage of parentheses around stabby lambda arguments.
|
||||||
Style/StabbyLambdaParentheses:
|
Style/StabbyLambdaParentheses:
|
||||||
EnforcedStyle: require_parentheses
|
EnforcedStyle: require_parentheses
|
||||||
|
@ -484,17 +535,19 @@ Style/StringMethods:
|
||||||
intern: to_sym
|
intern: to_sym
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
# No hard tabs.
|
# Use %i or %I for arrays of symbols.
|
||||||
Style/Tab:
|
Style/SymbolArray:
|
||||||
Enabled: true
|
Enabled: false
|
||||||
|
|
||||||
# Checks trailing blank lines and final newline.
|
|
||||||
Style/TrailingBlankLines:
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
# This cop checks for trailing comma in array and hash literals.
|
# This cop checks for trailing comma in array and hash literals.
|
||||||
Style/TrailingCommaInLiteral:
|
Style/TrailingCommaInLiteral:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
EnforcedStyleForMultiline: no_comma
|
||||||
|
|
||||||
|
# This cop checks for trailing comma in argument lists.
|
||||||
|
Style/TrailingCommaInArguments:
|
||||||
|
Enabled: true
|
||||||
|
EnforcedStyleForMultiline: no_comma
|
||||||
|
|
||||||
# Checks for %W when interpolation is not needed.
|
# Checks for %W when interpolation is not needed.
|
||||||
Style/UnneededCapitalW:
|
Style/UnneededCapitalW:
|
||||||
|
@ -533,6 +586,10 @@ Style/WhileUntilModifier:
|
||||||
Style/WordArray:
|
Style/WordArray:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Do not use literals as the first operand of a comparison.
|
||||||
|
Style/YodaCondition:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Use `proc` instead of `Proc.new`.
|
# Use `proc` instead of `Proc.new`.
|
||||||
Style/Proc:
|
Style/Proc:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
@ -543,7 +600,7 @@ Style/Proc:
|
||||||
# branches, and conditions.
|
# branches, and conditions.
|
||||||
Metrics/AbcSize:
|
Metrics/AbcSize:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Max: 57.08
|
Max: 56.96
|
||||||
|
|
||||||
# This cop checks if the length of a block exceeds some maximum value.
|
# This cop checks if the length of a block exceeds some maximum value.
|
||||||
Metrics/BlockLength:
|
Metrics/BlockLength:
|
||||||
|
@ -588,6 +645,11 @@ Metrics/PerceivedComplexity:
|
||||||
|
|
||||||
# Lint ########################################################################
|
# Lint ########################################################################
|
||||||
|
|
||||||
|
# Checks for ambiguous block association with method when param passed without
|
||||||
|
# parentheses.
|
||||||
|
Lint/AmbiguousBlockAssociation:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# 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:
|
||||||
|
@ -789,6 +851,10 @@ Lint/Void:
|
||||||
|
|
||||||
# Performance #################################################################
|
# Performance #################################################################
|
||||||
|
|
||||||
|
# Use `caller(n..n)` instead of `caller`.
|
||||||
|
Performance/Caller:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Use `casecmp` rather than `downcase ==`.
|
# Use `casecmp` rather than `downcase ==`.
|
||||||
Performance/Casecmp:
|
Performance/Casecmp:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
@ -863,14 +929,23 @@ Rails/ActionFilter:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
EnforcedStyle: action
|
EnforcedStyle: action
|
||||||
|
|
||||||
|
# Check that models subclass ApplicationRecord.
|
||||||
|
Rails/ApplicationRecord:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Enforce using `blank?` and `present?`.
|
||||||
|
Rails/Blank:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Checks the correct usage of date aware methods, such as `Date.today`,
|
# Checks the correct usage of date aware methods, such as `Date.today`,
|
||||||
# `Date.current`, etc.
|
# `Date.current`, etc.
|
||||||
Rails/Date:
|
Rails/Date:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Prefer delegate method for delegations.
|
# Prefer delegate method for delegations.
|
||||||
|
# Disabled per https://gitlab.com/gitlab-org/gitlab-ce/issues/35869
|
||||||
Rails/Delegate:
|
Rails/Delegate:
|
||||||
Enabled: true
|
Enabled: false
|
||||||
|
|
||||||
# This cop checks dynamic `find_by_*` methods.
|
# This cop checks dynamic `find_by_*` methods.
|
||||||
Rails/DynamicFindBy:
|
Rails/DynamicFindBy:
|
||||||
|
@ -919,10 +994,18 @@ Rails/OutputSafety:
|
||||||
Rails/PluralizationGrammar:
|
Rails/PluralizationGrammar:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Enforce using `blank?` and `present?`.
|
||||||
|
Rails/Present:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`.
|
# Checks for `read_attribute(:attr)` and `write_attribute(:attr, val)`.
|
||||||
Rails/ReadWriteAttribute:
|
Rails/ReadWriteAttribute:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# Do not assign relative date to constants.
|
||||||
|
Rails/RelativeDateConstant:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Checks the arguments of ActiveRecord scopes.
|
# Checks the arguments of ActiveRecord scopes.
|
||||||
Rails/ScopeArgs:
|
Rails/ScopeArgs:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
@ -945,6 +1028,10 @@ RSpec/AnyInstance:
|
||||||
RSpec/BeEql:
|
RSpec/BeEql:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# We don't enforce this as we use this technique in a few places.
|
||||||
|
RSpec/BeforeAfterAll:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# Check that the first argument to the top level describe is the tested class or
|
# Check that the first argument to the top level describe is the tested class or
|
||||||
# module.
|
# module.
|
||||||
RSpec/DescribeClass:
|
RSpec/DescribeClass:
|
||||||
|
@ -963,6 +1050,12 @@ RSpec/DescribeSymbol:
|
||||||
RSpec/DescribedClass:
|
RSpec/DescribedClass:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks if an example group does not include any tests.
|
||||||
|
RSpec/EmptyExampleGroup:
|
||||||
|
Enabled: true
|
||||||
|
CustomIncludeMethods:
|
||||||
|
- run_permission_checks
|
||||||
|
|
||||||
# Checks for long example.
|
# Checks for long example.
|
||||||
RSpec/ExampleLength:
|
RSpec/ExampleLength:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
@ -981,6 +1074,10 @@ RSpec/ExampleWording:
|
||||||
RSpec/ExpectActual:
|
RSpec/ExpectActual:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Checks for opportunities to use `expect { … }.to output`.
|
||||||
|
RSpec/ExpectOutput:
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# Checks the file and folder naming of the spec file.
|
# Checks the file and folder naming of the spec file.
|
||||||
RSpec/FilePath:
|
RSpec/FilePath:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
@ -994,6 +1091,12 @@ RSpec/FilePath:
|
||||||
RSpec/Focus:
|
RSpec/Focus:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
|
# SupportedStyles: is_expected, should
|
||||||
|
RSpec/ImplicitExpect:
|
||||||
|
Enabled: true
|
||||||
|
EnforcedStyle: is_expected
|
||||||
|
|
||||||
# Checks for the usage of instance variables.
|
# Checks for the usage of instance variables.
|
||||||
RSpec/InstanceVariable:
|
RSpec/InstanceVariable:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
@ -1039,6 +1142,13 @@ RSpec/NotToNot:
|
||||||
RSpec/RepeatedDescription:
|
RSpec/RepeatedDescription:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# Ensure RSpec hook blocks are always multi-line.
|
||||||
|
RSpec/SingleLineHook:
|
||||||
|
Enabled: true
|
||||||
|
Exclude:
|
||||||
|
- 'spec/factories/*'
|
||||||
|
- 'spec/requests/api/v3/*'
|
||||||
|
|
||||||
# Checks for stubbed test subjects.
|
# Checks for stubbed test subjects.
|
||||||
RSpec/SubjectStub:
|
RSpec/SubjectStub:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
|
@ -1,45 +1,89 @@
|
||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `rubocop --auto-gen-config --exclude-limit 0`
|
# `rubocop --auto-gen-config --exclude-limit 0`
|
||||||
# on 2017-04-07 20:17:35 -0400 using RuboCop version 0.47.1.
|
# on 2017-07-10 01:48:30 +0900 using RuboCop version 0.49.1.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
# versions of RuboCop, may require this file to be generated again.
|
# versions of RuboCop, may require this file to be generated again.
|
||||||
|
|
||||||
# Offense count: 54
|
# Offense count: 181
|
||||||
RSpec/BeforeAfterAll:
|
# Cop supports --auto-correct.
|
||||||
|
# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
|
||||||
|
Layout/ExtraSpacing:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 15
|
# Offense count: 119
|
||||||
# Configuration parameters: CustomIncludeMethods.
|
# Cop supports --auto-correct.
|
||||||
RSpec/EmptyExampleGroup:
|
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||||
|
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
|
||||||
|
Layout/IndentArray:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 233
|
# Offense count: 208
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||||
|
# SupportedStyles: special_inside_parentheses, consistent, align_braces
|
||||||
|
Layout/IndentHash:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 174
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
|
# SupportedStyles: space, no_space
|
||||||
|
Layout/SpaceBeforeBlockBraces:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 8
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
# Configuration parameters: AllowForAlignment.
|
||||||
|
Layout/SpaceBeforeFirstArg:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 64
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
|
# SupportedStyles: require_no_space, require_space
|
||||||
|
Layout/SpaceInLambdaLiteral:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 256
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters.
|
||||||
|
# SupportedStyles: space, no_space
|
||||||
|
# SupportedStylesForEmptyBraces: space, no_space
|
||||||
|
Layout/SpaceInsideBlockBraces:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 135
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
Layout/SpaceInsideParens:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 14
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
Layout/SpaceInsidePercentLiteralDelimiters:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 89
|
||||||
|
# Cop supports --auto-correct.
|
||||||
|
Layout/TrailingWhitespace:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# Offense count: 272
|
||||||
RSpec/EmptyLineAfterFinalLet:
|
RSpec/EmptyLineAfterFinalLet:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 167
|
# Offense count: 181
|
||||||
RSpec/EmptyLineAfterSubject:
|
RSpec/EmptyLineAfterSubject:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 3
|
# Offense count: 78
|
||||||
RSpec/ExpectOutput:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 72
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: implicit, each, example
|
# SupportedStyles: implicit, each, example
|
||||||
RSpec/HookArgument:
|
RSpec/HookArgument:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 12
|
# Offense count: 9
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
||||||
# SupportedStyles: is_expected, should
|
|
||||||
RSpec/ImplicitExpect:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 11
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: it_behaves_like, it_should_behave_like
|
# SupportedStyles: it_behaves_like, it_should_behave_like
|
||||||
RSpec/ItBehavesLike:
|
RSpec/ItBehavesLike:
|
||||||
|
@ -49,19 +93,19 @@ RSpec/ItBehavesLike:
|
||||||
RSpec/IteratedExpectation:
|
RSpec/IteratedExpectation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 3
|
# Offense count: 2
|
||||||
RSpec/OverwritingSetup:
|
RSpec/OverwritingSetup:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 34
|
# Offense count: 36
|
||||||
RSpec/RepeatedExample:
|
RSpec/RepeatedExample:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 43
|
# Offense count: 86
|
||||||
RSpec/ScatteredLet:
|
RSpec/ScatteredLet:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 32
|
# Offense count: 20
|
||||||
RSpec/ScatteredSetup:
|
RSpec/ScatteredSetup:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
@ -69,7 +113,7 @@ RSpec/ScatteredSetup:
|
||||||
RSpec/SharedContext:
|
RSpec/SharedContext:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 150
|
# Offense count: 115
|
||||||
Rails/FilePath:
|
Rails/FilePath:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
@ -79,97 +123,71 @@ Rails/FilePath:
|
||||||
Rails/ReversibleMigration:
|
Rails/ReversibleMigration:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 302
|
# Offense count: 336
|
||||||
# Configuration parameters: Blacklist.
|
# Configuration parameters: Blacklist.
|
||||||
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
|
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
|
||||||
Rails/SkipsModelValidations:
|
Rails/SkipsModelValidations:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 7
|
# Offense count: 11
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Security/YAMLLoad:
|
Security/YAMLLoad:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 59
|
# Offense count: 58
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: percent_q, bare_percent
|
# SupportedStyles: percent_q, bare_percent
|
||||||
Style/BarePercentLiterals:
|
Style/BarePercentLiterals:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 1403
|
# Offense count: 6
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
||||||
# SupportedStyles: leading, trailing
|
|
||||||
Style/DotPosition:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 5
|
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/EachWithObject:
|
Style/EachWithObject:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 28
|
# Offense count: 31
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: empty, nil, both
|
# SupportedStyles: empty, nil, both
|
||||||
Style/EmptyElse:
|
Style/EmptyElse:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 4
|
# Offense count: 9
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/EmptyLiteral:
|
Style/EmptyLiteral:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 59
|
# Offense count: 78
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: compact, expanded
|
# SupportedStyles: compact, expanded
|
||||||
Style/EmptyMethod:
|
Style/EmptyMethod:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 214
|
# Offense count: 23
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
|
|
||||||
Style/ExtraSpacing:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 9
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: format, sprintf, percent
|
# SupportedStyles: format, sprintf, percent
|
||||||
Style/FormatString:
|
Style/FormatString:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 285
|
# Offense count: 301
|
||||||
# Configuration parameters: MinBodyLength.
|
# Configuration parameters: MinBodyLength.
|
||||||
Style/GuardClause:
|
Style/GuardClause:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 16
|
# Offense count: 18
|
||||||
Style/IfInsideElse:
|
Style/IfInsideElse:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 186
|
# Offense count: 182
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: MaxLineLength.
|
# Configuration parameters: MaxLineLength.
|
||||||
Style/IfUnlessModifier:
|
Style/IfUnlessModifier:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 99
|
# Offense count: 52
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
|
||||||
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
|
|
||||||
Style/IndentArray:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 160
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
|
||||||
# SupportedStyles: special_inside_parentheses, consistent, align_braces
|
|
||||||
Style/IndentHash:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 50
|
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: line_count_dependent, lambda, literal
|
# SupportedStyles: line_count_dependent, lambda, literal
|
||||||
|
@ -181,63 +199,63 @@ Style/Lambda:
|
||||||
Style/LineEndConcatenation:
|
Style/LineEndConcatenation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 34
|
# Offense count: 40
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/MethodCallWithoutArgsParentheses:
|
Style/MethodCallWithoutArgsParentheses:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 10
|
# Offense count: 13
|
||||||
Style/MethodMissing:
|
Style/MethodMissing:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 3
|
# Offense count: 6
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/MultilineIfModifier:
|
Style/MultilineIfModifier:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 24
|
# Offense count: 26
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/NestedParenthesizedCalls:
|
Style/NestedParenthesizedCalls:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 18
|
# Offense count: 20
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, MinBodyLength, SupportedStyles.
|
||||||
# SupportedStyles: skip_modifier_ifs, always
|
# SupportedStyles: skip_modifier_ifs, always
|
||||||
Style/Next:
|
Style/Next:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 37
|
# Offense count: 45
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedOctalStyle, SupportedOctalStyles.
|
# Configuration parameters: EnforcedOctalStyle, SupportedOctalStyles.
|
||||||
# SupportedOctalStyles: zero_with_o, zero_only
|
# SupportedOctalStyles: zero_with_o, zero_only
|
||||||
Style/NumericLiteralPrefix:
|
Style/NumericLiteralPrefix:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 88
|
# Offense count: 98
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
|
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: predicate, comparison
|
# SupportedStyles: predicate, comparison
|
||||||
Style/NumericPredicate:
|
Style/NumericPredicate:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 36
|
# Offense count: 42
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/ParallelAssignment:
|
Style/ParallelAssignment:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 570
|
# Offense count: 800
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: PreferredDelimiters.
|
# Configuration parameters: PreferredDelimiters.
|
||||||
Style/PercentLiteralDelimiters:
|
Style/PercentLiteralDelimiters:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 14
|
# Offense count: 15
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/PerlBackrefs:
|
Style/PerlBackrefs:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 83
|
# Offense count: 105
|
||||||
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
|
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
|
||||||
# NamePrefix: is_, has_, have_
|
# NamePrefix: is_, has_, have_
|
||||||
# NamePrefixBlacklist: is_, has_, have_
|
# NamePrefixBlacklist: is_, has_, have_
|
||||||
|
@ -245,54 +263,47 @@ Style/PerlBackrefs:
|
||||||
Style/PredicateName:
|
Style/PredicateName:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 45
|
# Offense count: 58
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
||||||
# SupportedStyles: short, verbose
|
|
||||||
Style/PreferredHashMethods:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 65
|
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: compact, exploded
|
# SupportedStyles: compact, exploded
|
||||||
Style/RaiseArgs:
|
Style/RaiseArgs:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 5
|
# Offense count: 6
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/RedundantBegin:
|
Style/RedundantBegin:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 32
|
# Offense count: 37
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/RedundantFreeze:
|
Style/RedundantFreeze:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 15
|
# Offense count: 14
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: AllowMultipleReturnValues.
|
# Configuration parameters: AllowMultipleReturnValues.
|
||||||
Style/RedundantReturn:
|
Style/RedundantReturn:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 382
|
# Offense count: 406
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/RedundantSelf:
|
Style/RedundantSelf:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 111
|
# Offense count: 115
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
|
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
|
||||||
# SupportedStyles: slashes, percent_r, mixed
|
# SupportedStyles: slashes, percent_r, mixed
|
||||||
Style/RegexpLiteral:
|
Style/RegexpLiteral:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 24
|
# Offense count: 29
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/RescueModifier:
|
Style/RescueModifier:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 7
|
# Offense count: 8
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/SelfAssignment:
|
Style/SelfAssignment:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
@ -303,108 +314,58 @@ Style/SelfAssignment:
|
||||||
Style/SingleLineMethods:
|
Style/SingleLineMethods:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 168
|
# Offense count: 64
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
||||||
# SupportedStyles: space, no_space
|
|
||||||
Style/SpaceBeforeBlockBraces:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 8
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: AllowForAlignment.
|
|
||||||
Style/SpaceBeforeFirstArg:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 46
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
||||||
# SupportedStyles: require_no_space, require_space
|
|
||||||
Style/SpaceInLambdaLiteral:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 229
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters.
|
|
||||||
# SupportedStyles: space, no_space
|
|
||||||
# SupportedStylesForEmptyBraces: space, no_space
|
|
||||||
Style/SpaceInsideBlockBraces:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 116
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/SpaceInsideParens:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 12
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/SpaceInsidePercentLiteralDelimiters:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 57
|
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: SupportedStyles.
|
# Configuration parameters: SupportedStyles.
|
||||||
# SupportedStyles: use_perl_names, use_english_names
|
# SupportedStyles: use_perl_names, use_english_names
|
||||||
Style/SpecialGlobalVars:
|
Style/SpecialGlobalVars:
|
||||||
EnforcedStyle: use_perl_names
|
EnforcedStyle: use_perl_names
|
||||||
|
|
||||||
# Offense count: 42
|
# Offense count: 44
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||||
# SupportedStyles: single_quotes, double_quotes
|
# SupportedStyles: single_quotes, double_quotes
|
||||||
Style/StringLiteralsInInterpolation:
|
Style/StringLiteralsInInterpolation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 64
|
# Offense count: 84
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: IgnoredMethods.
|
# Configuration parameters: IgnoredMethods.
|
||||||
# IgnoredMethods: respond_to, define_method
|
# IgnoredMethods: respond_to, define_method
|
||||||
Style/SymbolProc:
|
Style/SymbolProc:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 6
|
# Offense count: 8
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment.
|
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment.
|
||||||
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
||||||
Style/TernaryParentheses:
|
Style/TernaryParentheses:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 53
|
# Offense count: 17
|
||||||
# Cop supports --auto-correct.
|
|
||||||
# Configuration parameters: EnforcedStyleForMultiline, SupportedStylesForMultiline.
|
|
||||||
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
|
||||||
Style/TrailingCommaInArguments:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 18
|
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: AllowNamedUnderscoreVariables.
|
# Configuration parameters: AllowNamedUnderscoreVariables.
|
||||||
Style/TrailingUnderscoreVariable:
|
Style/TrailingUnderscoreVariable:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 78
|
# Offense count: 4
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Style/TrailingWhitespace:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
# Offense count: 3
|
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
|
# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
|
||||||
# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym
|
# Whitelist: to_ary, to_a, to_c, to_enum, to_h, to_hash, to_i, to_int, to_io, to_open, to_path, to_proc, to_r, to_regexp, to_str, to_s, to_sym
|
||||||
Style/TrivialAccessors:
|
Style/TrivialAccessors:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 6
|
# Offense count: 5
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/UnlessElse:
|
Style/UnlessElse:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 24
|
# Offense count: 28
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/UnneededInterpolation:
|
Style/UnneededInterpolation:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
# Offense count: 8
|
# Offense count: 11
|
||||||
# Cop supports --auto-correct.
|
# Cop supports --auto-correct.
|
||||||
Style/ZeroLengthPredicate:
|
Style/ZeroLengthPredicate:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
|
@ -10,7 +10,7 @@ linters:
|
||||||
# Reports when you use improper spacing around ! (the "bang") in !default,
|
# Reports when you use improper spacing around ! (the "bang") in !default,
|
||||||
# !global, !important, and !optional flags.
|
# !global, !important, and !optional flags.
|
||||||
BangFormat:
|
BangFormat:
|
||||||
enabled: false
|
enabled: true
|
||||||
|
|
||||||
# Whether or not to prefer `border: 0` over `border: none`.
|
# Whether or not to prefer `border: 0` over `border: none`.
|
||||||
BorderZero:
|
BorderZero:
|
||||||
|
@ -43,10 +43,11 @@ linters:
|
||||||
# Rule sets should be ordered as follows:
|
# Rule sets should be ordered as follows:
|
||||||
# - @extend declarations
|
# - @extend declarations
|
||||||
# - @include declarations without inner @content
|
# - @include declarations without inner @content
|
||||||
# - properties, @include declarations with inner @content
|
# - properties
|
||||||
|
# - @include declarations with inner @content
|
||||||
# - nested rule sets.
|
# - nested rule sets.
|
||||||
DeclarationOrder:
|
DeclarationOrder:
|
||||||
enabled: false
|
enabled: true
|
||||||
|
|
||||||
# `scss-lint:disable` control comments should be preceded by a comment
|
# `scss-lint:disable` control comments should be preceded by a comment
|
||||||
# explaining why these linters are being disabled for this file.
|
# explaining why these linters are being disabled for this file.
|
||||||
|
@ -57,7 +58,7 @@ linters:
|
||||||
|
|
||||||
# Reports when you define the same property twice in a single rule set.
|
# Reports when you define the same property twice in a single rule set.
|
||||||
DuplicateProperty:
|
DuplicateProperty:
|
||||||
enabled: false
|
enabled: true
|
||||||
|
|
||||||
# Separate rule, function, and mixin declarations with empty lines.
|
# Separate rule, function, and mixin declarations with empty lines.
|
||||||
EmptyLineBetweenBlocks:
|
EmptyLineBetweenBlocks:
|
||||||
|
@ -75,7 +76,7 @@ linters:
|
||||||
# when adding lines to the file, since SCM systems such as git won't
|
# when adding lines to the file, since SCM systems such as git won't
|
||||||
# think that you touched the last line.
|
# think that you touched the last line.
|
||||||
FinalNewline:
|
FinalNewline:
|
||||||
enabled: false
|
enabled: true
|
||||||
|
|
||||||
# HEX colors should use three-character values where possible.
|
# HEX colors should use three-character values where possible.
|
||||||
HexLength:
|
HexLength:
|
||||||
|
@ -93,7 +94,7 @@ linters:
|
||||||
# The basenames of @imported SCSS partials should not begin with an
|
# The basenames of @imported SCSS partials should not begin with an
|
||||||
# underscore and should not include the filename extension.
|
# underscore and should not include the filename extension.
|
||||||
ImportPath:
|
ImportPath:
|
||||||
enabled: false
|
enabled: true
|
||||||
|
|
||||||
# Avoid using !important in properties. It is usually indicative of a
|
# Avoid using !important in properties. It is usually indicative of a
|
||||||
# misunderstanding of CSS specificity and can lead to brittle code.
|
# misunderstanding of CSS specificity and can lead to brittle code.
|
||||||
|
@ -133,7 +134,7 @@ linters:
|
||||||
# Reports when you use an unknown or disabled CSS property
|
# Reports when you use an unknown or disabled CSS property
|
||||||
# (ignoring vendor-prefixed properties).
|
# (ignoring vendor-prefixed properties).
|
||||||
PropertySpelling:
|
PropertySpelling:
|
||||||
enabled: false
|
enabled: true
|
||||||
|
|
||||||
# Configure which units are allowed for property values.
|
# Configure which units are allowed for property values.
|
||||||
PropertyUnits:
|
PropertyUnits:
|
||||||
|
@ -176,6 +177,10 @@ linters:
|
||||||
|
|
||||||
# Commas in lists should be followed by a space.
|
# Commas in lists should be followed by a space.
|
||||||
SpaceAfterComma:
|
SpaceAfterComma:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Comment literals should be followed by a space.
|
||||||
|
SpaceAfterComment:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
# Properties should be formatted with a single space separating the colon
|
# Properties should be formatted with a single space separating the colon
|
||||||
|
@ -240,7 +245,7 @@ linters:
|
||||||
# Do not use parent selector references (&) when they would otherwise
|
# Do not use parent selector references (&) when they would otherwise
|
||||||
# be unnecessary.
|
# be unnecessary.
|
||||||
UnnecessaryParentReference:
|
UnnecessaryParentReference:
|
||||||
enabled: false
|
enabled: true
|
||||||
|
|
||||||
# URLs should be valid and not contain protocols or domain names.
|
# URLs should be valid and not contain protocols or domain names.
|
||||||
UrlFormat:
|
UrlFormat:
|
||||||
|
|
796
CHANGELOG.md
796
CHANGELOG.md
|
@ -2,10 +2,712 @@
|
||||||
documentation](doc/development/changelog.md) for instructions on adding your own
|
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||||
entry.
|
entry.
|
||||||
|
|
||||||
## 9.2.10 (2017-08-09)
|
## 9.5.4 (2017-09-06)
|
||||||
|
|
||||||
|
- [SECURITY] Upgrade mail and nokogiri gems due to security issues. !13662 (Markus Koller)
|
||||||
|
- [SECURITY] Prevent a persistent XSS in the commit author block.
|
||||||
|
- Fix XSS issue in go-get handling.
|
||||||
|
- Resolve CSRF token leakage via pathname manipulation on environments page.
|
||||||
|
- Fixes race condition in project uploads.
|
||||||
|
- Disallow arbitrary properties in `th` and `td` `style` attributes.
|
||||||
|
- Disallow the `name` attribute on all user-provided markup.
|
||||||
|
|
||||||
|
## 9.5.3 (2017-09-03)
|
||||||
|
|
||||||
|
- [SECURITY] Filter additional secrets from Rails logs.
|
||||||
|
- [FIXED] Make username update fail if the namespace update fails. !13642
|
||||||
|
- [FIXED] Fix failure when issue is authored by a deleted user. !13807
|
||||||
|
- [FIXED] Reverts changes made to signin_enabled. !13956
|
||||||
|
- [FIXED] Fix Merge when pipeline succeeds button dropdown caret icon horizontal alignment.
|
||||||
|
- [FIXED] Fixed diff changes bar buttons from showing/hiding whilst scrolling.
|
||||||
|
- [FIXED] Fix events error importing GitLab projects.
|
||||||
|
- [FIXED] Fix pipeline trigger via API fails with 500 Internal Server Error in 9.5.
|
||||||
|
- [FIXED] Fixed fly-out nav flashing in & out.
|
||||||
|
- [FIXED] Remove closing external issues by reference error.
|
||||||
|
- [FIXED] Re-allow appearances.description_html to be NULL.
|
||||||
|
- [CHANGED] Update and fix resolvable note icons for easier recognition.
|
||||||
|
- [OTHER] Eager load head pipeline projects for MRs index.
|
||||||
|
- [OTHER] Instrument MergeRequest#fetch_ref.
|
||||||
|
- [OTHER] Instrument MergeRequest#ensure_ref_fetched.
|
||||||
|
|
||||||
|
## 9.5.2 (2017-08-28)
|
||||||
|
|
||||||
|
- [FIXED] Fix signing in using LDAP when attribute mapping uses simple strings instead of arrays.
|
||||||
|
- [FIXED] Show un-highlighted text diffs when we do not have references to the correct blobs.
|
||||||
|
- [FIXED] Fix display of push events for removed refs.
|
||||||
|
- [FIXED] Testing of some integrations were broken due to missing ServiceHook record.
|
||||||
|
- [FIXED] Fire system hooks when a user is created via LDAP.
|
||||||
|
- [FIXED] Fix new project form not resetting the template value.
|
||||||
|
|
||||||
|
## 9.5.1 (2017-08-23)
|
||||||
|
|
||||||
|
- [FIXED] Fix merge request pipeline status when pipeline has errors. !13664
|
||||||
|
- [FIXED] Commit rows would occasionally render with the wrong language.
|
||||||
|
- [FIXED] Fix caching of future broadcast messages.
|
||||||
|
- [FIXED] Only require Sidekiq throttling library when enabled, to reduce cache misses.
|
||||||
|
- Raise Housekeeping timeout to 24 hours. !13719
|
||||||
|
|
||||||
|
## 9.5.0 (2017-08-22)
|
||||||
|
|
||||||
|
- [FIXED] Fix timeouts when creating projects in groups with many members. !13508
|
||||||
|
- [FIXED] Improve API pagination headers when no record found. !13629 (Jordan Patterson)
|
||||||
|
- [FIXED] Fix deleting GitLab Pages files when a project is removed. !13631
|
||||||
|
- [FIXED] Fix commit list not loading the correct page when scrolling.
|
||||||
|
- [OTHER] Cache the number of forks of a project. !13535
|
||||||
|
- GPG signed commits integration. !9546 (Alexis Reigel)
|
||||||
|
- Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes. !9707 (Hiroyuki Sato)
|
||||||
|
- Add custom linter for inline JavaScript to haml_lint. !9742 (winniehell)
|
||||||
|
- Add /shrug and /tableflip commands. !10068 (Alex Ives)
|
||||||
|
- Allow wiki pages to be renamed in the UI. !10069 (wendy0402)
|
||||||
|
- Insert user name directly without encoding. !10085 (Nathan Neulinger <nneul@neulinger.org>)
|
||||||
|
- Avoid plucking Todo ids in TodoService. !10845
|
||||||
|
- Handle errors while a project is being deleted asynchronously. !11088
|
||||||
|
- Decrease ABC threshold to 56.96. !11227 (Maxim Rydkin)
|
||||||
|
- Remove Mattermost team when deleting a group. !11362
|
||||||
|
- Block access to failing repository storage. !11449
|
||||||
|
- Add coordinator url to admin area runner page. !11603
|
||||||
|
- Allow testing any events for project hooks and system hooks. !11728 (Alexander Randa (@randaalex))
|
||||||
|
- Disallow running the pipeline if ref is protected and user cannot merge the branch or create the tag. !11910
|
||||||
|
- Remove project_key from the Jira configuration. !12050
|
||||||
|
- Add CSRF token verification to API. !12154 (Vitaliy @blackst0ne Klachkov)
|
||||||
|
- Fixes needed when GitLab sign-in is not enabled. !12491 (Robin Bobbitt)
|
||||||
|
- Lazy load images for better Frontend performance. !12503
|
||||||
|
- Replaces dashboard/event_filters.feature spinach with rspec. !12651 (Alexander Randa (@randaalex))
|
||||||
|
- Toggle import description with import_sources_enabled. !12691 (Brianna Kicia)
|
||||||
|
- Bump scss-lint to 0.54.0. !12733 (Takuya Noguchi)
|
||||||
|
- Enable SpaceAfterComma in scss-lint. !12734 (Takuya Noguchi)
|
||||||
|
- Remove CSS for nprogress removed. !12737 (Takuya Noguchi)
|
||||||
|
- Enable UnnecessaryParentReference in scss-lint. !12738 (Takuya Noguchi)
|
||||||
|
- Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper. !12742 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Enable ImportPath in scss-lint. !12749 (Takuya Noguchi)
|
||||||
|
- Enable PropertySpelling in scss-lint. !12752 (Takuya Noguchi)
|
||||||
|
- Add API for protected branches to allow for wildcard matching and no access restrictions. !12756 (Eric Yu)
|
||||||
|
- refactor initializations in dropzone_input.js. !12768 (Brandon Everett)
|
||||||
|
- Improve CSS for global nav dropdown UI. !12772 (Takuya Noguchi)
|
||||||
|
- Remove public/ci/favicon.ico. !12803 (Takuya Noguchi)
|
||||||
|
- Enable DeclarationOrder in scss-lint. !12805 (Takuya Noguchi)
|
||||||
|
- Increase width of dropdown menus automatically. !12809 (Thomas Wucher)
|
||||||
|
- Enable BangFormat in scss-lint [ci skip]. !12815 (Takuya Noguchi)
|
||||||
|
- Added /duplicate quick action to close a duplicate issue. !12845 (Ryan Scott)
|
||||||
|
- Make all application-settings accessible through the API. !12851
|
||||||
|
- Remove Inactive Personal Access Tokens list from Access Tokens page. !12866
|
||||||
|
- Replaces dashboard/dashboard.feature spinach with rspec. !12876 (Alexander Randa (@randaalex))
|
||||||
|
- Reduce memory usage of the GitHub importer. !12886
|
||||||
|
- Bump fog-core to 1.44.3 and fog providers' plugins to latest. !12897 (Takuya Noguchi)
|
||||||
|
- Use only CSS to truncate commit message in blame. !12900 (Takuya Noguchi)
|
||||||
|
- Protect manual actions against protected tag too. !12908
|
||||||
|
- Allow to configure automatic retry of a failed CI/CD job. !12909
|
||||||
|
- Remove help message about prioritized labels for non-members. !12912 (Takuya Noguchi)
|
||||||
|
- Add link to doc/api/ci/lint.md. !12914 (Takuya Noguchi)
|
||||||
|
- Add RequestCache which makes caching with RequestStore easier. !12920
|
||||||
|
- Free up some top level words, reject top level groups named like files in the public folder. !12932
|
||||||
|
- Extend API for Group Secret Variable. !12936
|
||||||
|
- Hide description about protected branches to non-member. !12945 (Takuya Noguchi)
|
||||||
|
- Support custom directory in gitlab:backup:create task. !12984 (Markus Koller)
|
||||||
|
- Raise guessed encoding confidence threshold to 50. !12990
|
||||||
|
- Add author_id & assignee_id param to /issues API. !13004
|
||||||
|
- Fix today day highlight in calendar. !13048
|
||||||
|
- Prevent LDAP login callback from being called with a GET request. !13059
|
||||||
|
- Add top-level merge_requests API endpoint. !13060
|
||||||
|
- Handle maximum pages artifacts size correctly. !13072
|
||||||
|
- Enable gitaly_post_upload_pack by default. !13078
|
||||||
|
- Add Prometheus metrics exporter to Sidekiq. !13082
|
||||||
|
- Fix improperly skipped backups of wikis. !13096
|
||||||
|
- Projects can be created from templates. !13108
|
||||||
|
- Fix the /projects/:id/repository/branches endpoint to handle dots in the branch name when the project full path contains a `/`. !13115
|
||||||
|
- Fix project logos that are not centered vertically on list pages. !13124 (Florian Lemaitre)
|
||||||
|
- Derive project path from import URL. !13131
|
||||||
|
- Fix deletion of deploy keys linked to other projects. !13162
|
||||||
|
- repository archive download url now ends with selected file extension. !13178 (haseebeqx)
|
||||||
|
- Show auto-generated avatars for Groups without avatars. !13188
|
||||||
|
- Allow any logged in users to read_users_list even if it's restricted. !13201
|
||||||
|
- Unlock stuck merge request and set the proper state. !13207
|
||||||
|
- Fix timezone inconsistencies in user contribution graph. !13208
|
||||||
|
- Fix Issue board when using Ruby 2.4. !13220
|
||||||
|
- Don't rename namespace called system when upgrading from 9.1.x to 9.5. !13228
|
||||||
|
- Fix encoding error for WebHook logging. !13230 (Alexander Randa (@randaalex))
|
||||||
|
- Uniquify reserved word usernames on OAuth user creation. !13244 (Robin Bobbitt)
|
||||||
|
- Expose target_iid in Events API. !13247 (sue445)
|
||||||
|
- Add star for action scope, in order to delete image from registry. !13248 (jean)
|
||||||
|
- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
|
||||||
|
- Fix an order of operations for CI connection error message in merge request widget. !13252
|
||||||
|
- Don't send rejection mails for all auto-generated mails. !13254
|
||||||
|
- Expose noteable_iid in Note. !13265 (sue445)
|
||||||
|
- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
|
||||||
|
- Move some code from services to workers in order to improve performance. !13326
|
||||||
|
- Fix destroy of case-insensitive conflicting redirects. !13357
|
||||||
|
- Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name when the project full path contains a `/`. !13368
|
||||||
|
- Fix the /projects/:id/repository/commits endpoint to handle dots in the ref name when the project full path contains a `/`. !13370
|
||||||
|
- Project pending delete no longer return 500 error in admins projects view. !13389
|
||||||
|
- Use full path of user's avatar in webhooks. !13401 (Vitaliy @blackst0ne Klachkov)
|
||||||
|
- Make GPGME temporary directory handling thread safe. !13481 (Alexis Reigel)
|
||||||
|
- Add support for kube_namespace in Metrics queries. !16169
|
||||||
|
- Fix bar chart does not display label at 0 hour. !35136 (Jason Dai)
|
||||||
|
- Use project_ref_path to create the link to a branch to fix links that 404.
|
||||||
|
- Declare related resources into V4 API entities.
|
||||||
|
- Add Slack and JIRA services counts to Usage Data.
|
||||||
|
- Prevent web hook and project service background jobs from going to the dead jobs queue.
|
||||||
|
- Display specific error message when JIRA test fails.
|
||||||
|
- clean up merge request widget UI.
|
||||||
|
- Associate Issues tab only with internal issues tracker.
|
||||||
|
- Remove events column from notification settings table.
|
||||||
|
- Clarifies and rearranges the input variables on the kubernetes integration page and adjusts the docs slightly to meet the same order.
|
||||||
|
- Respect blockquote line breaks in markdown.
|
||||||
|
- Update confidential issue UI - add confidential visibility and settings to sidebar.
|
||||||
|
- Add icons to contextual sidebars.
|
||||||
|
- Make contextual sidebar collapsible.
|
||||||
|
- Update Pipeline's badge count in Merge Request and Commits view to match real-time content.
|
||||||
|
- Added link to the MR widget that directs to the monitoring dashboard.
|
||||||
|
- Use jQuery to control scroll behavior in job log for cross browser consistency.
|
||||||
|
- move edit comment button outside of dropdown.
|
||||||
|
- Updates vue resource and code according to breaking changes.
|
||||||
|
- Add GitHub imported projects count to usage data.
|
||||||
|
- Rename about to overview for group and project page.
|
||||||
|
- Prevent disabled pagination button to be clicked.
|
||||||
|
- Remove coffee-rails gem. (Takuya Noguchi)
|
||||||
|
- Remove net-ssh gem. (Takuya Noguchi)
|
||||||
|
- Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1. (Takuya Noguchi)
|
||||||
|
- improve file upload/replace experience.
|
||||||
|
- allow closing Cycle Analytics intro box in firefox.
|
||||||
|
- Fix label creation from new list for subgroup projects.
|
||||||
|
- fix transient js error in rspec tests.
|
||||||
|
- fix jump to next discussion button.
|
||||||
|
- Fix translations for Star/Unstar in JS file.
|
||||||
|
- Improve mobile sidebar.
|
||||||
|
- Rename Pipelines tab to CI / CD in new navigation.
|
||||||
|
- Fix display of new diff comments after changing b between diff views.
|
||||||
|
- Store & use ConvDev percentages returned by the Version app.
|
||||||
|
- Fixes new issue button for failed job returning 404.
|
||||||
|
- Align OR separator to center in new project page.
|
||||||
|
- Add filtered search to group issue dashboard.
|
||||||
|
- Cache Appearance instances in Redis.
|
||||||
|
- Fixed breadcrumbs title aggressively collapsing.
|
||||||
|
- Better caching and indexing of broadcast messages.
|
||||||
|
- Moved diff changed files into a dropdown.
|
||||||
|
- Improve performance of large (initial) push into default branch.
|
||||||
|
- Improve performance of checking for projects on the projects dashboard.
|
||||||
|
- Eager load project creators for project dashboards.
|
||||||
|
- Modify if condition to be more readable.
|
||||||
|
- Fix links to group milestones from issue and merge request sidebar.
|
||||||
- Remove hidden symlinks from project import files.
|
- Remove hidden symlinks from project import files.
|
||||||
|
- Fixed sign-in restrictions buttons not toggling active state.
|
||||||
|
- Fix replying to commit comments on merge requests created from forks.
|
||||||
|
- Support Markdown references, autocomplete, and quick actions for group milestones.
|
||||||
|
- Cache recent projects for group-level new resource creation.
|
||||||
|
- Fix API responses when dealing with txt files.
|
||||||
|
- Fix project milestones import when projects belongs to a group.
|
||||||
|
- Fix Mattermost integration.
|
||||||
|
- Memoize the number of personal projects a user has to reduce COUNT queries.
|
||||||
|
- Merge issuable "reopened" state into "opened".
|
||||||
|
- Migrate events into a new format to reduce the storage necessary and improve performance.
|
||||||
|
- MR branch link now links to tree instead of commits.
|
||||||
|
- Use Prev/Next pagination for exploring projects.
|
||||||
|
- Pass before_script and script as-is preserving arrays.
|
||||||
|
- Change project FK migration to skip existing FKs.
|
||||||
|
- Remove redundant query when retrieving the most recent push of a user.
|
||||||
|
- Re-organise "issues" indexes for faster ordering.
|
||||||
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
|
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
|
||||||
|
- Fix search box losing focus when typing.
|
||||||
|
- Add structured logging for Rails processes.
|
||||||
|
- Skip oAuth authorization for trusted applications.
|
||||||
|
- Use a specialized class for querying events to improve performance.
|
||||||
|
- Update build badges to be pipeline badges and display passing instead of success.
|
||||||
|
|
||||||
|
## 9.4.3 (2017-07-31)
|
||||||
|
|
||||||
|
- Fix Prometheus client PID reuse bug. !13130
|
||||||
|
- Improve deploy environment chatops slash command. !13150
|
||||||
|
- Fix asynchronous javascript paths when GitLab is installed under a relative URL. !13165
|
||||||
|
- Fix LDAP authentication to Git repository or container registry.
|
||||||
|
- Fixed new navigation breadcrumb title on help pages.
|
||||||
|
- Ensure filesystem metrics test files are deleted.
|
||||||
|
- Properly affixes nav bar in job view in microsoft edge.
|
||||||
|
|
||||||
|
## 9.4.2 (2017-07-28)
|
||||||
|
|
||||||
|
- Fix job merge request link to a forked source project. !12965
|
||||||
|
- Improve redirect route query performance. !13062
|
||||||
|
- Allow admin to read_users_list even if it's restricted. !13066
|
||||||
|
- Fixes 500 error caused by pending delete projects in admin dashboard. !13067
|
||||||
|
- Add instrumentation to MarkupHelper#link_to_gfm. !13069
|
||||||
|
- Pending delete projects should not show in deploy keys. !13088
|
||||||
|
- Fix sizing of custom header logo in new navigation.
|
||||||
|
- Fix crash on /help/ui.
|
||||||
|
- Fix creating merge request diffs when diff contains bytes that are invalid in UTF-8.
|
||||||
|
- fix vertical alignment of New Project button.
|
||||||
|
- Add LDAP SSL certificate verification option.
|
||||||
|
- Fix vertical alignment in firefox and safari for pipeline mini graph.
|
||||||
|
|
||||||
|
## 9.4.1 (2017-07-25)
|
||||||
|
|
||||||
|
- Fix pipeline_schedules pages throwing error 500 (when ref is empty). !12983
|
||||||
|
- Fix editing project with container images present. !13028
|
||||||
|
- Fix some invalid entries in PO files. !13032
|
||||||
|
- Fix cross site request protection when logging in as a regular user when LDAP is enabled. !13049
|
||||||
|
- Fix bug causing metrics files to be truncated. !35420
|
||||||
|
- Fix anonymous access to public projects in groups with pending invites.
|
||||||
|
- Fixed issue boards sidebar close icon size.
|
||||||
|
- Fixed duplicate new milestone buttons when new navigation is turned on.
|
||||||
|
- Fix margins in the mini graph for pipeline in commits box.
|
||||||
|
|
||||||
|
## 9.4.0 (2017-07-22)
|
||||||
|
|
||||||
|
- Add blame view age mapping. !7198 (Jeff Stubler)
|
||||||
|
- Add support for image and services configuration in .gitlab-ci.yml. !8578
|
||||||
|
- Fix an email parsing bug where brackets would be inserted in emails from some Outlook clients. !9045 (jneen)
|
||||||
|
- Use fa-chevron-down on dropdown arrows for consistency. !9659 (TM Lee)
|
||||||
|
- Update the devise mail templates to match the design of the pipeline emails. !10483 (Alexis Reigel)
|
||||||
|
- Handle renamed submodules in repository browser. !10798 (David Turner)
|
||||||
|
- Display all current broadcast messages, not just the last one. !11113 (rickettm)
|
||||||
|
- Fix CI/CD status in case there are only allowed to failed jobs in the pipeline. !11166
|
||||||
|
- Omit trailing / leading hyphens in CI_COMMIT_REF_SLUG variable to make it usable as a hostname. !11218 (Stefan Hanreich)
|
||||||
|
- Moved "Members in a project" menu entry and path locations. !11560
|
||||||
|
- Additional Prometheus metrics support. !11712
|
||||||
|
- Rename all reserved paths that could have been created. !11713
|
||||||
|
- Move uploads from `uploads/system` to `uploads/-/system` to free up `system` as a group name. !11713
|
||||||
|
- Fix offline runner detection. !11751 (Alessio Caiazza)
|
||||||
|
- Use authorize_update_pipeline_schedule in PipelineSchedulesController. !11846
|
||||||
|
- Rollback project repo move if there is an error in Projects::TransferService. !11877
|
||||||
|
- Help landing page customizations. !11878 (Robin Bobbitt)
|
||||||
|
- Fixes "sign in / Register" active state underline misalignment. !11890 (Frank Sierra)
|
||||||
|
- Honor the "Remember me" parameter for OAuth-based login. !11963
|
||||||
|
- Instruct user to use personal access token for Git over HTTP. !11986 (Robin Bobbitt)
|
||||||
|
- Accept image for avatar in project API. !11988 (Ivan Chernov)
|
||||||
|
- Supplement Simplified Chinese translation of Project Page & Repository Page. !11994 (Huang Tao)
|
||||||
|
- Supplement Traditional Chinese in Hong Kong translation of Project Page & Repository Page. !11995 (Huang Tao)
|
||||||
|
- Make the revision on the `/help` page clickable. !12016
|
||||||
|
- Display issue state in issue links section of merge request widget. !12021
|
||||||
|
- Enable support for webpack code-splitting by dynamically setting publicPath at runtime. !12032
|
||||||
|
- Replace PhantomJS with headless Chrome for karma test suite. !12036
|
||||||
|
- Prevent description change notes when toggling tasks. !12057 (Jared Deckard <jared.deckard@gmail.com>)
|
||||||
|
- Update QA Dockerfile to lock Chrome browser version. !12071
|
||||||
|
- Fix FIDO U2F for Opera browser. !12082 (Jakub Kramarz and Jonas Kalderstam)
|
||||||
|
- Supplement Bulgarian translation of Project Page & Repository Page. !12083 (Lyubomir Vasilev)
|
||||||
|
- Removes deleted_at and pending_delete occurrences in Project related queries. !12091
|
||||||
|
- Provide hint to create a personal access token for Git over HTTP. !12105 (Robin Bobbitt)
|
||||||
|
- Display own user id in account settings page. !12141 (Riccardo Padovani)
|
||||||
|
- Accept image for avatar in user API. !12143 (Ivan Chernov)
|
||||||
|
- Disable fork button on project limit. !12145 (Ivan Chernov)
|
||||||
|
- Added "created_after" and "created_before" params to issuables. !12151 (Kyle Bishop @kybishop)
|
||||||
|
- Supplement Portuguese Brazil translation of Project Page & Repository Page. !12156 (Huang Tao)
|
||||||
|
- Add review apps to usage metrics. !12185
|
||||||
|
- Adding French translations. !12200 (Erwan "Dremor" Georget)
|
||||||
|
- Ensures default user limits when external user is unchecked. !12218
|
||||||
|
- Provide KUBECONFIG from KubernetesService for runners. !12223
|
||||||
|
- Filter archived project in API v3 only if param present. !12245 (Ivan Chernov)
|
||||||
|
- Add explicit message when no runners on admin. !12266 (Takuya Noguchi)
|
||||||
|
- Split pipelines as internal and external in the usage data. !12277
|
||||||
|
- Fix API Scoping. !12300
|
||||||
|
- Remove registry image delete button if user cant delete it. !12317 (Ivan Chernov)
|
||||||
|
- Allow the feature flags to be enabled/disabled with more granularity. !12357
|
||||||
|
- Allow to enable the performance bar per user or Feature group. !12362
|
||||||
|
- Rename duplicated variables with the same key for projects. Add environment_scope column to variables and add unique constraint to make sure that no variables could be created with the same key within a project. !12363
|
||||||
|
- Add variables to pipelines schedules. !12372
|
||||||
|
- Add User#full_private_access? to check if user has access to all private groups & projects. !12373
|
||||||
|
- Change milestone endpoint for groups. !12374 (Takuya Noguchi)
|
||||||
|
- Improve performance of the pipeline charts page. !12378
|
||||||
|
- Add option to run Gitaly on a remote server. !12381
|
||||||
|
- #20628 Enable implicit grant in GitLab as OAuth Provider. !12384 (Mateusz Pytel)
|
||||||
|
- Replace 'snippets/snippets.feature' spinach with rspec. !12385 (Alexander Randa @randaalex)
|
||||||
|
- Add Simplified Chinese translations of Commits Page. !12405 (Huang Tao)
|
||||||
|
- Add Traditional Chinese in HongKong translations of Commits Page. !12406 (Huang Tao)
|
||||||
|
- Add Traditional Chinese in Taiwan translations of Commits Page. !12407 (Huang Tao)
|
||||||
|
- Add Portuguese Brazil translations of Commits Page. !12408 (Huang Tao)
|
||||||
|
- Add French translations of Commits Page. !12409 (Huang Tao)
|
||||||
|
- Add Esperanto translations of Commits Page. !12410 (Huang Tao)
|
||||||
|
- Add Bulgarian translations of Commits Page. !12411 (Huang Tao)
|
||||||
|
- Remove bin/ci/upgrade.rb as not working all. !12414 (Takuya Noguchi)
|
||||||
|
- Store merge request ref_fetched status in the database. !12424
|
||||||
|
- Replace 'dashboard/merge_requests' spinach with rspec. !12440 (Alexander Randa (@randaalex))
|
||||||
|
- Add Esperanto translations for Cycle Analytics, Project, and Repository pages. !12442 (Huang Tao)
|
||||||
|
- Allow unauthenticated access to the /api/v4/users API. !12445
|
||||||
|
- Drop GFM support for the title of Milestone/MergeRequest in template. !12451 (Takuya Noguchi)
|
||||||
|
- Replace 'dashboard/todos' spinach with rspec. !12453 (Alexander Randa (@randaalex))
|
||||||
|
- Cache open issue and merge request counts for project tabs to speed up project pages. !12457
|
||||||
|
- Introduce cache policies for CI jobs. !12483
|
||||||
|
- Improve support for external issue references. !12485
|
||||||
|
- Fix errors caused by attempts to report already blocked or deleted users. !12502 (Horacio Bertorello)
|
||||||
|
- Allow customize CI config path. !12509 (Keith Pope)
|
||||||
|
- Supplement Traditional Chinese in Taiwan translation of Project Page & Repository Page. !12514 (Huang Tao)
|
||||||
|
- Closes any open Autocomplete of the markdown editor when the form is closed. !12521
|
||||||
|
- Inserts exact matches of name, username and email to the top of the search list. !12525
|
||||||
|
- Use smaller min-width for dropdown-menu-nav only on mobile. !12528 (Takuya Noguchi)
|
||||||
|
- Hide archived project labels from group issue tracker. !12547 (Horacio Bertorello)
|
||||||
|
- Replace 'dashboard/new-project.feature' spinach with rspec. !12550 (Alexander Randa (@randaalex))
|
||||||
|
- Remove group modal like remove project modal (requires typing + confirmation). !12569 (Diego Souza)
|
||||||
|
- Add Italian translation of Cycle Analytics Page & Project Page & Repository Page. !12578 (Huang Tao)
|
||||||
|
- Add Group secret variables. !12582
|
||||||
|
- Update jobs page output to have a scrollable page. !12587
|
||||||
|
- Add user projects API. !12596 (Ivan Chernov)
|
||||||
|
- Allow creation of files and directories with spaces through Web UI. !12608
|
||||||
|
- Improve members view on mobile. !12619
|
||||||
|
- Fixed the chart legend not being set correctly. !12628
|
||||||
|
- Add Italian translations of Commits Page. !12645 (Huang Tao)
|
||||||
|
- Allow admins to disable all restricted visibility levels. !12649
|
||||||
|
- Allow admins to retrieve user agent details for an issue or snippet. !12655
|
||||||
|
- Update welcome page UX for new users. !12662
|
||||||
|
- N+1 problems on milestone page. !12670 (Takuya Noguchi)
|
||||||
|
- Upgrade GitLab Workhorse to v2.3.0. !12676
|
||||||
|
- Remove option to disable Gitaly. !12677
|
||||||
|
- Improve the performance of the project list API. !12679
|
||||||
|
- Add creation time filters to user search API for admins. !12682
|
||||||
|
- Add Japanese translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12693 (Huang Tao)
|
||||||
|
- Undo adding the /reassign quick action. !12701
|
||||||
|
- Fix dashboard labels dropdown. !12708
|
||||||
|
- Username and password are no longer stripped from import url on mirror update. !12725
|
||||||
|
- Add Russian translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12743 (Huang Tao)
|
||||||
|
- Add Ukrainian translations for Cycle Analytics & Project pages & Repository pages & Commits pages & Pipeline Charts. !12744 (Huang Tao)
|
||||||
|
- Prevent bad data being added to application settings when Redis is unavailable. !12750
|
||||||
|
- Do not show pipeline schedule button for non-member. !12757 (Takuya Noguchi)
|
||||||
|
- Return `is_admin` attribute in the GET /user endpoint for admins. !12811
|
||||||
|
- Recover from renaming project that has container images. !12840
|
||||||
|
- Exact matches of username and email are now on top of the user search. !12868
|
||||||
|
- Use Ghost user for last_edited_by and merge_user when original user is deleted. !12933
|
||||||
|
- Fix docker tag reference routing constraints. !12961
|
||||||
|
- Optimize creation of commit API by using Repository#commit instead of Repository#commits.
|
||||||
|
- Speed up used languages calculation on charts page.
|
||||||
|
- Make loading new merge requests (those created after the 9.4 upgrade) faster.
|
||||||
|
- Ensure participants for issues, merge requests, etc. are calculated correctly when sending notifications.
|
||||||
|
- Handle nameless legacy jobs.
|
||||||
|
- Bump Faraday and dependent OAuth2 gem version to support no_proxy variable.
|
||||||
|
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||||
|
- Render CI statuses with warnings in orange.
|
||||||
|
- Document the Delete Merged Branches functionality.
|
||||||
|
- Add wells to admin dashboard overview to fix spacing problems.
|
||||||
|
- Removes hover style for nodes that are either links or buttons in the pipeline graph.
|
||||||
|
- more visual contrast in pagination widget.
|
||||||
|
- Deprecate Healthcheck Access Token in favor of IP whitelist.
|
||||||
|
- Drop GFM support for issuable title on milestone for consistency and performance. (Takuya Noguchi)
|
||||||
|
- fix left & right padding on sidebar.
|
||||||
|
- Cleanup minor UX issues in the performance dashboard.
|
||||||
|
- Remove two columned layout from project member settings.
|
||||||
|
- Make font size of contextual sub menu items 14px.
|
||||||
|
- Fix vertical space in job details sidebar.
|
||||||
|
- Fix alignment of controls in mr issuable list.
|
||||||
|
- Add wip message to new navigation preference section.
|
||||||
|
- Add group members counting and plan related data on namespaces API.
|
||||||
|
- Fix spacing on runner buttons.
|
||||||
|
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||||
|
- Change order of monospace fonts to fix bug on some linux distros.
|
||||||
|
- Limit commit & snippets comments width.
|
||||||
|
- Fixed dashboard milestone tabs not loading.
|
||||||
|
- Detect if file that appears to be text in the first 1024 bytes is actually binary afer loading all data.
|
||||||
|
- Fix inconsistent display of the "Browse files" button in the commit list.
|
||||||
|
- Implement diff viewers.
|
||||||
|
- Fix 'New merge request' button for users who don't have push access to canonical project.
|
||||||
|
- Fix issues with non-UTF8 filenames by always fixing the encoding of tree and blob paths.
|
||||||
|
- Show group name instead of path on group page.
|
||||||
|
- Don't check if MailRoom is running on Omnibus.
|
||||||
|
- Limit OpenGraph image size to 64x64.
|
||||||
|
- Don't show auxiliary blob viewer for README when there is no wiki.
|
||||||
|
- Strip trailing whitespace in relative submodule URL.
|
||||||
|
- Update /target_branch slash command description to be more consistent.
|
||||||
|
- Remove unnecessary top padding on group MR index.
|
||||||
|
- Added printing_merge_requst_link_enabled to the API. (David Turner <dturner@twosigma.com>)
|
||||||
|
- Re-enable realtime for environments table.
|
||||||
|
- Create responsive mobile view for pipelines table.
|
||||||
|
- Adds realtime feature to job show view header and sidebar info. Updates UX.
|
||||||
|
- Use color inputs for broadcast messages.
|
||||||
|
- Center dropdown for mini graph.
|
||||||
|
- Users can subscribe to group labels on the group labels page.
|
||||||
|
- Add issuable-list class to shared mr/issue lists to fix new responsive layout design.
|
||||||
|
- Rename "Slash commands" to "Quick actions" and deprecate "chat commands" in favor of "slash commands".
|
||||||
|
- Don't mark empty MRs as merged on push to the target branch.
|
||||||
|
- Improve issue rendering performance with lots of notes from other users.
|
||||||
|
- Fixed overflow on mobile screens for the slash commands.
|
||||||
|
- Fix an infinite loop when handling user-supplied regular expressions.
|
||||||
|
- Fixed sidebar not collapsing on merge requests in mobile screens.
|
||||||
|
- Speed up project removals by adding foreign keys with cascading deletes to various tables.
|
||||||
|
- Fix mobile view of files view buttons.
|
||||||
|
- Fixed dropdown filter input not focusing after transition.
|
||||||
|
- Fixed GFM references not being included when updating issues inline.
|
||||||
|
- Remove issues/merge requests drag n drop and sorting from milestone view.
|
||||||
|
- Add native group milestones.
|
||||||
|
- Fix API bug accepting wrong parameter to create merge request.
|
||||||
|
- Clean up UI of issuable lists and make more responsive.
|
||||||
|
- Improve the overall UX for the new monitoring dashboard.
|
||||||
|
- Fixed the y_label not setting correctly for each graph on the monitoring dashboard.
|
||||||
|
- Changed utilities imports from ~ to relative paths.
|
||||||
|
- Remove unused space in sidebar todo toggle when not signed in.
|
||||||
|
- Limit the width of the projects README text.
|
||||||
|
- Add a simple mode to merge request API.
|
||||||
|
- Make Project#ensure_repository force create a repo.
|
||||||
|
- Use uploads/system directory for personal snippets.
|
||||||
|
- Defer project destroys within a namespace in Groups::DestroyService#async_execute.
|
||||||
|
- Log rescued exceptions to Sentry.
|
||||||
|
- Remove remaining N+1 queries in merge requests API with emojis and labels.
|
||||||
|
|
||||||
|
## 9.3.9 (2017-07-20)
|
||||||
|
|
||||||
|
- Fix an infinite loop when handling user-supplied regular expressions.
|
||||||
|
|
||||||
|
## 9.3.8 (2017-07-19)
|
||||||
|
|
||||||
|
- Improve support for external issue references. !12485
|
||||||
|
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||||
|
- Use uploads/system directory for personal snippets.
|
||||||
|
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||||
|
|
||||||
|
## 9.3.7 (2017-07-18)
|
||||||
|
|
||||||
|
- Prevent bad data being added to application settings when Redis is unavailable. !12750
|
||||||
|
- Return `is_admin` attribute in the GET /user endpoint for admins. !12811
|
||||||
|
|
||||||
|
## 9.3.6 (2017-07-12)
|
||||||
|
|
||||||
|
- Fix API Scoping. !12300
|
||||||
|
- Username and password are no longer stripped from import url on mirror update. !12725
|
||||||
|
- Fix issues with non-UTF8 filenames by always fixing the encoding of tree and blob paths.
|
||||||
|
- Fixed GFM references not being included when updating issues inline.
|
||||||
|
|
||||||
|
## 9.3.5 (2017-07-05)
|
||||||
|
|
||||||
|
- Remove "Remove from board" button from backlog and closed list. !12430
|
||||||
|
- Do not delete protected branches when deleting all merged branches. !12624
|
||||||
|
- Set default for Remove source branch to false.
|
||||||
|
- Prevent accidental deletion of protected MR source branch by repeating checks before actual deletion.
|
||||||
|
- Expires full_path cache after a repository is renamed/transferred.
|
||||||
|
|
||||||
|
## 9.3.4 (2017-07-03)
|
||||||
|
|
||||||
|
- Update gitlab-shell to 5.1.1 !12615
|
||||||
|
|
||||||
|
## 9.3.3 (2017-06-30)
|
||||||
|
|
||||||
|
- Fix head pipeline stored in merge request for external pipelines. !12478
|
||||||
|
- Bring back branches badge to main project page. !12548
|
||||||
|
- Fix diff of requirements.txt file by not matching newlines as part of package names.
|
||||||
|
- Perform housekeeping only when an import of a fresh project is completed.
|
||||||
|
- Fixed issue boards closed list not showing all closed issues.
|
||||||
|
- Fixed multi-line markdown tooltip buttons in issue edit form.
|
||||||
|
|
||||||
|
## 9.3.2 (2017-06-27)
|
||||||
|
|
||||||
|
- API: Fix optional arugments for POST :id/variables. !12474
|
||||||
|
- Bump premailer-rails gem to 1.9.7 and its dependencies to prevent network retrieval of assets.
|
||||||
|
|
||||||
|
## 9.3.1 (2017-06-26)
|
||||||
|
|
||||||
|
- Fix reversed breadcrumb order for nested groups. !12322
|
||||||
|
- Fix 500 when failing to create private group. !12394
|
||||||
|
- Fix linking to line number on side-by-side diff creating empty discussion box.
|
||||||
|
- Don't match tilde and exclamation mark as part of requirements.txt package name.
|
||||||
|
- Perform project housekeeping after importing projects.
|
||||||
|
- Fixed ctrl+enter not submit issue edit form.
|
||||||
|
|
||||||
|
## 9.3.0 (2017-06-22)
|
||||||
|
|
||||||
|
- Refactored gitlab:app:check into SystemCheck liberary and improve some checks. !9173
|
||||||
|
- Add an ability to cancel attaching file and redesign attaching files UI. !9431 (blackst0ne)
|
||||||
|
- Add Aliyun OSS as the backup storage provider. !9721 (Yuanfei Zhu)
|
||||||
|
- Add suport for find_local_branches GRPC from Gitaly. !10059
|
||||||
|
- Allow manual bypass of auto_sign_in_with_provider with a new param. !10187 (Maxime Besson)
|
||||||
|
- Redirect to user's keys index instead of user's index after a key is deleted in the admin. !10227 (Cyril Jouve)
|
||||||
|
- Changed Blame to Annotate in the UI to promote blameless culture. !10378 (Ilya Vassilevsky)
|
||||||
|
- Implement ability to update deploy keys. !10383 (Alexander Randa)
|
||||||
|
- Allow numeric values in gitlab-ci.yml. !10607 (blackst0ne)
|
||||||
|
- Add a feature test for Unicode trace. !10736 (dosuken123)
|
||||||
|
- Notes: Warning message should go away once resolved. !10823 (Jacopo Beschi @jacopo-beschi)
|
||||||
|
- Project authorizations are calculated much faster when using PostgreSQL, and nested groups support for MySQL has been removed
|
||||||
|
. !10885
|
||||||
|
- Fix long urls in the title of commit. !10938 (Alexander Randa)
|
||||||
|
- Update gem sidekiq-cron from 0.4.4 to 0.6.0 and rufus-scheduler from 3.1.10 to 3.4.0. !10976 (dosuken123)
|
||||||
|
- Use relative paths for group/project/user avatars. !11001 (blackst0ne)
|
||||||
|
- Enable cancelling non-HEAD pending pipelines by default for all projects. !11023
|
||||||
|
- Implement web hook logging. !11027 (Alexander Randa)
|
||||||
|
- Add indices for auto_canceled_by_id for ci_pipelines and ci_builds on PostgreSQL. !11034
|
||||||
|
- Add post-deploy migration to clean up projects in `pending_delete` state. !11044
|
||||||
|
- Limit User's trackable attributes, like `current_sign_in_at`, to update at most once/hour. !11053
|
||||||
|
- Disallow multiple selections for Milestone dropdown. !11084
|
||||||
|
- Link to commit author user page from pipelines. !11100
|
||||||
|
- Fix the last coverage in trace log should be extracted. !11128 (dosuken123)
|
||||||
|
- Remove redirect for old issue url containing id instead of iid. !11135 (blackst0ne)
|
||||||
|
- Backported new SystemHook event: `repository_update`. !11140
|
||||||
|
- Keep input data after creating a tag that already exists. !11155
|
||||||
|
- Fix support for external CI services. !11176
|
||||||
|
- Translate backend for Project & Repository pages. !11183
|
||||||
|
- Fix LaTeX formatting for AsciiDoc wiki. !11212
|
||||||
|
- Add foreign key for pipeline schedule owner. !11233
|
||||||
|
- Print Go version in rake gitlab:env:info. !11241
|
||||||
|
- Include the blob content when printing a blob page. !11247
|
||||||
|
- Sync email address from specified omniauth provider. !11268 (Robin Bobbitt)
|
||||||
|
- Disable reference prefixes in notes for Snippets. !11278
|
||||||
|
- Rename build_events to job_events. !11287
|
||||||
|
- Add API support for pipeline schedule. !11307 (dosuken123)
|
||||||
|
- Use route.cache_key for project list cache key. !11325
|
||||||
|
- Make environment table realtime. !11333
|
||||||
|
- Cache npm modules between pipelines with yarn to speed up setup-test-env. !11343
|
||||||
|
- Allow GitLab instance to start when InfluxDB hostname cannot be resolved. !11356
|
||||||
|
- Add ConvDev Index page to admin area. !11377
|
||||||
|
- Fix Git-over-HTTP error statuses and improve error messages. !11398
|
||||||
|
- Renamed users 'Audit Log'' to 'Authentication Log'. !11400
|
||||||
|
- Style people in issuable search bar. !11402
|
||||||
|
- Change /builds in the URL to /-/jobs. Backward URLs were also added. !11407
|
||||||
|
- Update password field label while editing service settings. !11431
|
||||||
|
- Add an optional performance bar to view performance metrics for the current page. !11439
|
||||||
|
- Update task_list to version 2.0.0. !11525 (Jared Deckard <jared.deckard@gmail.com>)
|
||||||
|
- Avoid resource intensive login checks if password is not provided. !11537 (Horatiu Eugen Vlad)
|
||||||
|
- Allow numeric pages domain. !11550
|
||||||
|
- Exclude manual actions when checking if pipeline can be canceled. !11562
|
||||||
|
- Add server uptime to System Info page in admin dashboard. !11590 (Justin Boltz)
|
||||||
|
- Simplify testing and saving service integrations. !11599
|
||||||
|
- Fixed handling of the `can_push` attribute in the v3 deploy_keys api. !11607 (Richard Clamp)
|
||||||
|
- Improve user experience around slash commands in instant comments. !11612
|
||||||
|
- Show current user immediately in issuable filters. !11630
|
||||||
|
- Add extra context-sensitive functionality for the top right menu button. !11632
|
||||||
|
- Reorder Issue action buttons in order of usability. !11642
|
||||||
|
- Expose atom links with an RSS token instead of using the private token. !11647 (Alexis Reigel)
|
||||||
|
- Respect merge, instead of push, permissions for protected actions. !11648
|
||||||
|
- Job details page update real time. !11651
|
||||||
|
- Improve performance of ProjectFinder used in /projects API endpoint. !11666
|
||||||
|
- Remove redundant data-turbolink attributes from links. !11672 (blackst0ne)
|
||||||
|
- Minimum postgresql version is now 9.2. !11677
|
||||||
|
- Add protected variables which would only be passed to protected branches or protected tags. !11688
|
||||||
|
- Introduce optimistic locking support via optional parameter last_commit_sha on File Update API. !11694 (electroma)
|
||||||
|
- Add $CI_ENVIRONMENT_URL to predefined variables for pipelines. !11695
|
||||||
|
- Simplify project repository settings page. !11698
|
||||||
|
- Fix pipeline_schedules pages throwing error 500. !11706 (dosuken123)
|
||||||
|
- Add performance deltas between app deployments on Merge Request widget. !11730
|
||||||
|
- Add feature toggles and API endpoints for admins. !11747
|
||||||
|
- Replace 'starred_projects.feature' spinach test with an rspec analog. !11752 (blackst0ne)
|
||||||
|
- Introduce an Events API. !11755
|
||||||
|
- Display Shared Runner status in Admin Dashboard. !11783 (Ivan Chernov)
|
||||||
|
- Persist pipeline stages in the database. !11790
|
||||||
|
- Revert the feature that would include the current user's username in the HTTP clone URL. !11792
|
||||||
|
- Enable Gitaly by default in installations from source. !11796
|
||||||
|
- Use zopfli compression for frontend assets. !11798
|
||||||
|
- Add tag_list param to project api. !11799 (Ivan Chernov)
|
||||||
|
- Add changelog for improved Registry description. !11816
|
||||||
|
- Automatically adjust project settings to match changes in project visibility. !11831
|
||||||
|
- Add slugify project path to CI enviroment variables. !11838 (Ivan Chernov)
|
||||||
|
- Add all pipeline sources as special keywords to 'only' and 'except'. !11844 (Filip Krakowski)
|
||||||
|
- Allow pulling of container images using personal access tokens. !11845
|
||||||
|
- Expose import_status in Projects API. !11851 (Robin Bobbitt)
|
||||||
|
- Allow admins to delete users from the admin users page. !11852
|
||||||
|
- Allow users to be hard-deleted from the API. !11853
|
||||||
|
- Fix hard-deleting users when they have authored issues. !11855
|
||||||
|
- Fix missing optional path parameter in "Create project for user" API. !11868
|
||||||
|
- Allow users to be hard-deleted from the admin panel. !11874
|
||||||
|
- Add a Rake task to aid in rotating otp_key_base. !11881
|
||||||
|
- Fix submodule link to then project under subgroup. !11906
|
||||||
|
- Fix binary encoding error on MR diffs. !11929
|
||||||
|
- Limit non-administrators to adding 100 members at a time to groups and projects. !11940
|
||||||
|
- add bulgarian translation of cycle analytics page to I18N. !11958 (Lyubomir Vasilev)
|
||||||
|
- Make backup task to continue on corrupt repositories. !11962
|
||||||
|
- Fix incorrect ETag cache key when relative instance URL is used. !11964
|
||||||
|
- Reinstate is_admin flag in users api when authenticated user is an admin. !12211 (rickettm)
|
||||||
|
- Fix edit button for deploy keys available from other projects. !12301 (Alexander Randa)
|
||||||
|
- Fix passing CI_ENVIRONMENT_NAME and CI_ENVIRONMENT_SLUG for CI_ENVIRONMENT_URL. !12344
|
||||||
|
- Disable environment list refresh due to bug https://gitlab.com/gitlab-org/gitlab-ee/issues/2677. !12347
|
||||||
|
- Standardize timeline note margins across different viewport sizes. !12364
|
||||||
|
- Fix Ordered Task List Items. !31483 (Jared Deckard <jared.deckard@gmail.com>)
|
||||||
|
- Upgrade dependency to Go 1.8.3. !31943
|
||||||
|
- Add prometheus metrics on pipeline creation.
|
||||||
|
- Fix etag route not being a match for environments.
|
||||||
|
- Sort folder for environments.
|
||||||
|
- Support descriptions for snippets.
|
||||||
|
- Hide clone panel and file list when user is only a guest. (James Clark)
|
||||||
|
- Don’t create comment on JIRA if it already exists for the entity.
|
||||||
|
- Update Dashboard Groups UI with better support for subgroups.
|
||||||
|
- Confirm Project forking behaviour via the API.
|
||||||
|
- Add prometheus based metrics collection to gitlab webapp.
|
||||||
|
- Fix: Wiki is not searchable with Guest permissions.
|
||||||
|
- Center all empty states.
|
||||||
|
- Remove 'New issue' button when issues search returns no results.
|
||||||
|
- Add API URL to JIRA settings.
|
||||||
|
- animate adding issue to boards.
|
||||||
|
- Update session cookie key name to be unique to instance in development.
|
||||||
|
- Single click on filter to open filtered search dropdown.
|
||||||
|
- Makes header information of pipeline show page realtine.
|
||||||
|
- Creates a mediator for pipeline details vue in order to mount several vue apps with the same data.
|
||||||
|
- Scope issue/merge request recent searches to project.
|
||||||
|
- Increase individual diff collapse limit to 100 KB, and render limit to 200 KB.
|
||||||
|
- Fix Pipelines table empty state - only render empty state if we receive 0 pipelines.
|
||||||
|
- Make New environment empty state btn lowercase.
|
||||||
|
- Removes duplicate environment variable in documentation.
|
||||||
|
- Change links in issuable meta to black.
|
||||||
|
- Fix border-bottom for project activity tab.
|
||||||
|
- Adds new icon for CI skipped status.
|
||||||
|
- Create equal padding for emoji.
|
||||||
|
- Use briefcase icon for company in profile page.
|
||||||
|
- Remove overflow from comment form for confidential issues and vertically aligns confidential issue icon.
|
||||||
|
- Keep trailing newline when resolving conflicts by picking sides.
|
||||||
|
- Fix /unsubscribe slash command creating extra todos when you were already mentioned in an issue.
|
||||||
|
- Fix math rendering on blob pages.
|
||||||
|
- Allow group reporters to manage group labels.
|
||||||
|
- Use pre-wrap for commit messages to keep lists indented.
|
||||||
|
- Count badges depend on translucent color to better adjust to different background colors and permission badges now feature a pill shaped design similar to labels.
|
||||||
|
- Allow reporters to promote project labels to group labels.
|
||||||
|
- Enabled keyboard shortcuts on artifacts pages.
|
||||||
|
- Perform filtered search when state tab is changed.
|
||||||
|
- Remove duplication for sharing projects with groups in project settings.
|
||||||
|
- Change order of commits ahead and behind on divergence graph for branch list view.
|
||||||
|
- Creates CI Header component for Pipelines and Jobs details pages.
|
||||||
|
- Invalidate cache for issue and MR counters more granularly.
|
||||||
|
- disable blocked manual actions.
|
||||||
|
- Load tree readme asynchronously.
|
||||||
|
- Display extra info about files on .gitlab-ci.yml, .gitlab/route-map.yml and LICENSE blob pages.
|
||||||
|
- Fix replying to a commit discussion displayed in the context of an MR.
|
||||||
|
- Consistently use monospace font for commit SHAs and branch and tag names.
|
||||||
|
- Consistently display last push event widget.
|
||||||
|
- Don't copy empty elements that were not selected on purpose as GFM.
|
||||||
|
- Copy as GFM even when parts of other elements are selected.
|
||||||
|
- Autolink package names in Gemfile.
|
||||||
|
- Resolve N+1 query issue with discussions.
|
||||||
|
- Don't match email addresses or foo@bar as user references.
|
||||||
|
- Fix title of discussion jump button at top of page.
|
||||||
|
- Don't return nil for missing objects from parser cache.
|
||||||
|
- Make .gitmodules parsing more resilient to syntax errors.
|
||||||
|
- Add username parameter to gravatar URL.
|
||||||
|
- Autolink package names in more dependency files.
|
||||||
|
- Return nil when looking up config for unknown LDAP provider.
|
||||||
|
- Add system note with link to diff comparison when MR discussion becomes outdated.
|
||||||
|
- Don't wrap pasted code when it's already inside code tags.
|
||||||
|
- Revert 'New file from interface on existing branch'.
|
||||||
|
- Show last commit for current tree on tree page.
|
||||||
|
- Add documentation about adding foreign keys.
|
||||||
|
- add username field to push webhook. (David Turner)
|
||||||
|
- Rename CI/CD Pipelines to Pipelines in the project settings.
|
||||||
|
- Make environment tables responsive.
|
||||||
|
- Expand/collapse backlog & closed lists in issue boards.
|
||||||
|
- Fix GitHub importer performance on branch existence check.
|
||||||
|
- Fix counter cache for acts as taggable.
|
||||||
|
- Github - Fix token interpolation when cloning wiki repository.
|
||||||
|
- Fix token interpolation when setting the Github remote.
|
||||||
|
- Fix N+1 queries for non-members in comment threads.
|
||||||
|
- Fix terminals support for Kubernetes Service.
|
||||||
|
- Fix: A diff comment on a change at last line of a file shows as two comments in discussion.
|
||||||
|
- Instrument MergeRequestDiff#load_commits.
|
||||||
|
- Introduce source to Pipeline entity.
|
||||||
|
- Fixed create new label form in issue form not working for sub-group projects.
|
||||||
|
- Fixed style on unsubscribe page. (Gustav Ernberg)
|
||||||
|
- Enables inline editing for an issues title & description.
|
||||||
|
- Ask for an example project for bug reports.
|
||||||
|
- Add summary lines for collapsed details in the bug report template.
|
||||||
|
- Prevent commits from upstream repositories to be re-processed by forks.
|
||||||
|
- Avoid repeated queries for pipeline builds on merge requests.
|
||||||
|
- Preloads head pipeline for merge request collection.
|
||||||
|
- Handle head pipeline when creating merge requests.
|
||||||
|
- Migrate artifacts to a new path.
|
||||||
|
- Rescue OpenSSL::SSL::SSLError in JiraService & IssueTrackerService.
|
||||||
|
- Repository browser: handle in-repository submodule urls. (David Turner)
|
||||||
|
- Prevent project transfers if a new group is not selected.
|
||||||
|
- Allow 'no one' as an option for allowed to merge on a procted branch.
|
||||||
|
- Reduce time spent waiting for certain Sidekiq jobs to complete.
|
||||||
|
- Refactor ProjectsFinder#init_collection to produce more efficient queries for retrieving projects.
|
||||||
|
- Remove unused code and uses underscore.
|
||||||
|
- Restricts search projects dropdown to group projects when group is selected.
|
||||||
|
- Properly handle container registry redirects to fix metadata stored on a S3 backend.
|
||||||
|
- Fix LFS timeouts when trying to save large files.
|
||||||
|
- Set artifact working directory to be in the destination store to prevent unnecessary I/O.
|
||||||
|
- Strip trailing whitespaces in submodule URLs.
|
||||||
|
- Make sure reCAPTCHA configuration is loaded when spam checks are initiated.
|
||||||
|
- Fix up arrow not editing last discussion comment.
|
||||||
|
- Added application readiness endpoints to the monitoring health check admin view.
|
||||||
|
- Use wait_for_requests for both ajax and Vue requests.
|
||||||
|
- Cleanup ci_variables schema and table.
|
||||||
|
- Remove foreigh key on ci_trigger_schedules only if it exists.
|
||||||
|
- Allow translation of Pipeline Schedules.
|
||||||
|
|
||||||
## 9.2.9 (2017-07-20)
|
## 9.2.9 (2017-07-20)
|
||||||
|
|
||||||
|
@ -262,6 +964,42 @@ entry.
|
||||||
- Fix preemptive scroll bar on user activity calendar.
|
- Fix preemptive scroll bar on user activity calendar.
|
||||||
- Pipeline chat notifications convert seconds to minutes and hours.
|
- Pipeline chat notifications convert seconds to minutes and hours.
|
||||||
|
|
||||||
|
## 9.1.9 (2017-07-20)
|
||||||
|
|
||||||
|
- Fix an infinite loop when handling user-supplied regular expressions.
|
||||||
|
|
||||||
|
## 9.1.8 (2017-07-19)
|
||||||
|
|
||||||
|
- Improve support for external issue references. !12485
|
||||||
|
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||||
|
- Fix incorrect project authorizations.
|
||||||
|
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||||
|
|
||||||
|
## 9.1.7 (2017-06-07)
|
||||||
|
|
||||||
|
- No changes.
|
||||||
|
|
||||||
|
## 9.1.6 (2017-06-02)
|
||||||
|
|
||||||
|
- Fix visibility when referencing snippets.
|
||||||
|
|
||||||
|
## 9.1.5 (2017-05-31)
|
||||||
|
|
||||||
|
- Move uploads from 'public/uploads' to 'public/uploads/system'.
|
||||||
|
- Restrict API X-Frame-Options to same origin.
|
||||||
|
- Allow users autocomplete by author_id only for authenticated users.
|
||||||
|
|
||||||
|
## 9.1.4 (2017-05-12)
|
||||||
|
|
||||||
|
- Fix error on CI/CD Settings page related to invalid pipeline trigger. !10948 (dosuken123)
|
||||||
|
- Sort the network graph both by commit date and topographically. !11057
|
||||||
|
- Fix cross referencing for private and internal projects. !11243
|
||||||
|
- Handle incoming emails from aliases correctly.
|
||||||
|
- Gracefully handle failures for incoming emails which do not match on the To header, and have no References header.
|
||||||
|
- Add missing project attributes to Import/Export.
|
||||||
|
- Fixed search terms not correctly highlighting.
|
||||||
|
- Fixed bug where merge request JSON would be displayed.
|
||||||
|
|
||||||
## 9.1.3 (2017-05-05)
|
## 9.1.3 (2017-05-05)
|
||||||
|
|
||||||
- Do not show private groups on subgroups page if user doesn't have access to.
|
- Do not show private groups on subgroups page if user doesn't have access to.
|
||||||
|
@ -302,6 +1040,7 @@ entry.
|
||||||
|
|
||||||
## 9.1.0 (2017-04-22)
|
## 9.1.0 (2017-04-22)
|
||||||
|
|
||||||
|
- Add Jupyter notebook rendering !10017
|
||||||
- Added merge requests empty state. !7342
|
- Added merge requests empty state. !7342
|
||||||
- Add option to start a new resolvable discussion in an MR. !7527
|
- Add option to start a new resolvable discussion in an MR. !7527
|
||||||
- Hide form inputs for group member without editing rights. !7816
|
- Hide form inputs for group member without editing rights. !7816
|
||||||
|
@ -548,6 +1287,30 @@ entry.
|
||||||
- Only send chat notifications for the default branch.
|
- Only send chat notifications for the default branch.
|
||||||
- Don't fill in the default kubernetes namespace.
|
- Don't fill in the default kubernetes namespace.
|
||||||
|
|
||||||
|
## 9.0.12 (2017-07-20)
|
||||||
|
|
||||||
|
- Fix an infinite loop when handling user-supplied regular expressions.
|
||||||
|
|
||||||
|
## 9.0.11 (2017-07-19)
|
||||||
|
|
||||||
|
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||||
|
- Fix incorrect project authorizations.
|
||||||
|
- Remove uploads/appearance symlink. A leftover from a previous migration.
|
||||||
|
|
||||||
|
## 9.0.10 (2017-06-07)
|
||||||
|
|
||||||
|
- No changes.
|
||||||
|
|
||||||
|
## 9.0.9 (2017-06-02)
|
||||||
|
|
||||||
|
- Fix visibility when referencing snippets.
|
||||||
|
|
||||||
|
## 9.0.8 (2017-05-31)
|
||||||
|
|
||||||
|
- Move uploads from 'public/uploads' to 'public/uploads/system'.
|
||||||
|
- Restrict API X-Frame-Options to same origin.
|
||||||
|
- Allow users autocomplete by author_id only for authenticated users.
|
||||||
|
|
||||||
## 9.0.7 (2017-05-05)
|
## 9.0.7 (2017-05-05)
|
||||||
|
|
||||||
- Enforce project features when searching blobs and wikis.
|
- Enforce project features when searching blobs and wikis.
|
||||||
|
@ -904,6 +1667,11 @@ entry.
|
||||||
- Change development tanuki favicon colors to match logo color order.
|
- Change development tanuki favicon colors to match logo color order.
|
||||||
- API issues - support filtering by iids.
|
- API issues - support filtering by iids.
|
||||||
|
|
||||||
|
## 8.17.7 (2017-07-19)
|
||||||
|
|
||||||
|
- Renders 404 if given project is not readable by the user on Todos dashboard.
|
||||||
|
- Fix incorrect project authorizations.
|
||||||
|
|
||||||
## 8.17.6 (2017-05-05)
|
## 8.17.6 (2017-05-05)
|
||||||
|
|
||||||
- Enforce project features when searching blobs and wikis.
|
- Enforce project features when searching blobs and wikis.
|
||||||
|
@ -1151,8 +1919,6 @@ entry.
|
||||||
|
|
||||||
## 8.16.7 (2017-02-27)
|
## 8.16.7 (2017-02-27)
|
||||||
|
|
||||||
- No changes.
|
|
||||||
- No changes.
|
|
||||||
- Fix MR changes tab size count when there are over 100 files in the diff.
|
- Fix MR changes tab size count when there are over 100 files in the diff.
|
||||||
|
|
||||||
## 8.16.6 (2017-02-17)
|
## 8.16.6 (2017-02-17)
|
||||||
|
@ -1366,6 +2132,14 @@ entry.
|
||||||
- Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
|
- Prevent the GitHub importer from assigning labels and comments to merge requests or issues belonging to other projects.
|
||||||
- Patch XSS vulnerability in RDOC support.
|
- Patch XSS vulnerability in RDOC support.
|
||||||
|
|
||||||
|
## 8.15.5 (2017-01-20)
|
||||||
|
|
||||||
|
- Ensure export files are removed after a namespace is deleted.
|
||||||
|
- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
|
||||||
|
- Prevent users from creating notes on resources they can't access.
|
||||||
|
- Prevent users from deleting system deploy keys via the project deploy key API.
|
||||||
|
- Upgrade omniauth gem to 1.3.2.
|
||||||
|
|
||||||
## 8.15.4 (2017-01-09)
|
## 8.15.4 (2017-01-09)
|
||||||
|
|
||||||
- Make successful pipeline emails off for watchers. !8176
|
- Make successful pipeline emails off for watchers. !8176
|
||||||
|
@ -1648,6 +2422,14 @@ entry.
|
||||||
- Speed up group milestone index by passing group_id to IssuesFinder. !8363
|
- Speed up group milestone index by passing group_id to IssuesFinder. !8363
|
||||||
- Ensure issuable state changes only fire webhooks once.
|
- Ensure issuable state changes only fire webhooks once.
|
||||||
|
|
||||||
|
## 8.14.7 (2017-01-21)
|
||||||
|
|
||||||
|
- Ensure export files are removed after a namespace is deleted.
|
||||||
|
- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
|
||||||
|
- Prevent users from creating notes on resources they can't access.
|
||||||
|
- Prevent users from deleting system deploy keys via the project deploy key API.
|
||||||
|
- Upgrade omniauth gem to 1.3.2.
|
||||||
|
|
||||||
## 8.14.6 (2017-01-10)
|
## 8.14.6 (2017-01-10)
|
||||||
|
|
||||||
- Update the gitlab-markup gem to the version 1.5.1. !8509
|
- Update the gitlab-markup gem to the version 1.5.1. !8509
|
||||||
|
@ -1930,6 +2712,14 @@ entry.
|
||||||
- Fix "Without projects" filter. !6611 (Ben Bodenmiller)
|
- Fix "Without projects" filter. !6611 (Ben Bodenmiller)
|
||||||
- Fix 404 when visit /projects page
|
- Fix 404 when visit /projects page
|
||||||
|
|
||||||
|
## 8.13.12 (2017-01-21)
|
||||||
|
|
||||||
|
- Ensure export files are removed after a namespace is deleted.
|
||||||
|
- Don't allow project guests to subscribe to merge requests through the API. (Robert Schilling)
|
||||||
|
- Prevent users from creating notes on resources they can't access.
|
||||||
|
- Prevent users from deleting system deploy keys via the project deploy key API.
|
||||||
|
- Upgrade omniauth gem to 1.3.2.
|
||||||
|
|
||||||
## 8.13.11 (2017-01-10)
|
## 8.13.11 (2017-01-10)
|
||||||
|
|
||||||
- Update the gitlab-markup gem to the version 1.5.1. !8509
|
- Update the gitlab-markup gem to the version 1.5.1. !8509
|
||||||
|
|
|
@ -31,7 +31,7 @@ _This notice should stay as the first item in the CONTRIBUTING.MD file._
|
||||||
- [Issue tracker guidelines](#issue-tracker-guidelines)
|
- [Issue tracker guidelines](#issue-tracker-guidelines)
|
||||||
- [Issue weight](#issue-weight)
|
- [Issue weight](#issue-weight)
|
||||||
- [Regression issues](#regression-issues)
|
- [Regression issues](#regression-issues)
|
||||||
- [Technical debt](#technical-debt)
|
- [Technical and UX debt](#technical-and-ux-debt)
|
||||||
- [Stewardship](#stewardship)
|
- [Stewardship](#stewardship)
|
||||||
- [Merge requests](#merge-requests)
|
- [Merge requests](#merge-requests)
|
||||||
- [Merge request guidelines](#merge-request-guidelines)
|
- [Merge request guidelines](#merge-request-guidelines)
|
||||||
|
@ -49,6 +49,8 @@ _This notice should stay as the first item in the CONTRIBUTING.MD file._
|
||||||
Thank you for your interest in contributing to GitLab. This guide details how
|
Thank you for your interest in contributing to GitLab. This guide details how
|
||||||
to contribute to GitLab in a way that is efficient for everyone.
|
to contribute to GitLab in a way that is efficient for everyone.
|
||||||
|
|
||||||
|
Looking for something to work on? Look for the label [Accepting Merge Requests](#i-want-to-contribute).
|
||||||
|
|
||||||
GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
|
GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
|
||||||
source edition, and GitLab Enterprise Edition (EE) which is our commercial
|
source edition, and GitLab Enterprise Edition (EE) which is our commercial
|
||||||
edition. Throughout this guide you will see references to CE and EE for
|
edition. Throughout this guide you will see references to CE and EE for
|
||||||
|
@ -112,8 +114,8 @@ scheduling into milestones. Labelling is a task for everyone.
|
||||||
Most issues will have labels for at least one of the following:
|
Most issues will have labels for at least one of the following:
|
||||||
|
|
||||||
- Type: ~"feature proposal", ~bug, ~customer, etc.
|
- Type: ~"feature proposal", ~bug, ~customer, etc.
|
||||||
- Subject: ~wiki, ~"container registry", ~ldap, ~api, etc.
|
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
|
||||||
- Team: ~CI, ~Discussion, ~Edge, ~Frontend, ~Platform, etc.
|
- Team: ~CI, ~Discussion, ~Edge, ~Platform, etc.
|
||||||
- Priority: ~Deliverable, ~Stretch
|
- Priority: ~Deliverable, ~Stretch
|
||||||
|
|
||||||
All labels, their meaning and priority are defined on the
|
All labels, their meaning and priority are defined on the
|
||||||
|
@ -276,7 +278,7 @@ For feature proposals for EE, open an issue on the
|
||||||
In order to help track the feature proposals, we have created a
|
In order to help track the feature proposals, we have created a
|
||||||
[`feature proposal`][fpl] label. For the time being, users that are not members
|
[`feature proposal`][fpl] label. For the time being, users that are not members
|
||||||
of the project cannot add labels. You can instead ask one of the [core team]
|
of the project cannot add labels. You can instead ask one of the [core team]
|
||||||
members to add the label `feature proposal` to the issue or add the following
|
members to add the label ~"feature proposal" to the issue or add the following
|
||||||
code snippet right after your description in a new line: `~"feature proposal"`.
|
code snippet right after your description in a new line: `~"feature proposal"`.
|
||||||
|
|
||||||
Please keep feature proposals as small and simple as possible, complex ones
|
Please keep feature proposals as small and simple as possible, complex ones
|
||||||
|
@ -342,27 +344,29 @@ addressed.
|
||||||
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
|
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
|
||||||
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
|
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
|
||||||
|
|
||||||
### Technical debt
|
### Technical and UX debt
|
||||||
|
|
||||||
In order to track things that can be improved in GitLab's codebase, we created
|
In order to track things that can be improved in GitLab's codebase,
|
||||||
the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
|
we use the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
|
||||||
|
For user experience improvements, we use the ~"UX debt" label.
|
||||||
|
|
||||||
This label should be added to issues that describe things that can be improved,
|
These labels should be added to issues that describe things that can be improved,
|
||||||
shortcuts that have been taken, code that needs refactoring, features that need
|
shortcuts that have been taken, features that need additional attention, and all
|
||||||
additional attention, and all other things that have been left behind due to
|
other things that have been left behind due to high velocity of development.
|
||||||
high velocity of development.
|
For example, code that needs refactoring should use the ~"technical debt" label,
|
||||||
|
user experience refinements should use the ~"UX debt" label.
|
||||||
|
|
||||||
Everyone can create an issue, though you may need to ask for adding a specific
|
Everyone can create an issue, though you may need to ask for adding a specific
|
||||||
label, if you do not have permissions to do it by yourself. Additional labels
|
label, if you do not have permissions to do it by yourself. Additional labels
|
||||||
can be combined with the `technical debt` label, to make it easier to schedule
|
can be combined with these labels, to make it easier to schedule
|
||||||
the improvements for a release.
|
the improvements for a release.
|
||||||
|
|
||||||
Issues tagged with the `technical debt` label have the same priority like issues
|
Issues tagged with these labels have the same priority like issues
|
||||||
that describe a new feature to be introduced in GitLab, and should be scheduled
|
that describe a new feature to be introduced in GitLab, and should be scheduled
|
||||||
for a release by the appropriate person.
|
for a release by the appropriate person.
|
||||||
|
|
||||||
Make sure to mention the merge request that the `technical debt` issue is
|
Make sure to mention the merge request that the ~"technical debt" issue or
|
||||||
associated with in the description of the issue.
|
~"UX debt" issue is associated with in the description of the issue.
|
||||||
|
|
||||||
### Stewardship
|
### Stewardship
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.10.0
|
0.35.0
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.4.2
|
0.5.1
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
5.0.4
|
5.8.0
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
2.0.0
|
3.0.0
|
||||||
|
|
111
Gemfile
111
Gemfile
|
@ -12,12 +12,13 @@ gem 'sprockets', '~> 3.7.0'
|
||||||
gem 'default_value_for', '~> 3.0.0'
|
gem 'default_value_for', '~> 3.0.0'
|
||||||
|
|
||||||
# Supported DBs
|
# Supported DBs
|
||||||
gem 'mysql2', '~> 0.3.16', group: :mysql
|
gem 'mysql2', '~> 0.4.5', group: :mysql
|
||||||
gem 'pg', '~> 0.18.2', group: :postgres
|
gem 'pg', '~> 0.18.2', group: :postgres
|
||||||
|
|
||||||
gem 'rugged', '~> 0.25.1.1'
|
gem 'rugged', '~> 0.26.0'
|
||||||
|
gem 'grape-route-helpers', '~> 2.0.0'
|
||||||
|
|
||||||
gem 'faraday', '~> 0.11.0'
|
gem 'faraday', '~> 0.12'
|
||||||
|
|
||||||
# Authentication libraries
|
# Authentication libraries
|
||||||
gem 'devise', '~> 4.2'
|
gem 'devise', '~> 4.2'
|
||||||
|
@ -26,7 +27,7 @@ gem 'doorkeeper-openid_connect', '~> 1.1.0'
|
||||||
gem 'omniauth', '~> 1.4.2'
|
gem 'omniauth', '~> 1.4.2'
|
||||||
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'
|
||||||
gem 'omniauth-cas3', '~> 1.1.2'
|
gem 'omniauth-cas3', '~> 1.1.4'
|
||||||
gem 'omniauth-facebook', '~> 4.0.0'
|
gem 'omniauth-facebook', '~> 4.0.0'
|
||||||
gem 'omniauth-github', '~> 1.1.1'
|
gem 'omniauth-github', '~> 1.1.1'
|
||||||
gem 'omniauth-gitlab', '~> 1.0.2'
|
gem 'omniauth-gitlab', '~> 1.0.2'
|
||||||
|
@ -37,7 +38,7 @@ gem 'omniauth-saml', '~> 1.7.0'
|
||||||
gem 'omniauth-shibboleth', '~> 1.2.0'
|
gem 'omniauth-shibboleth', '~> 1.2.0'
|
||||||
gem 'omniauth-twitter', '~> 1.2.0'
|
gem 'omniauth-twitter', '~> 1.2.0'
|
||||||
gem 'omniauth_crowd', '~> 2.2.0'
|
gem 'omniauth_crowd', '~> 2.2.0'
|
||||||
gem 'omniauth-authentiq', '~> 0.3.0'
|
gem 'omniauth-authentiq', '~> 0.3.1'
|
||||||
gem 'rack-oauth2', '~> 1.2.1'
|
gem 'rack-oauth2', '~> 1.2.1'
|
||||||
gem 'jwt', '~> 1.5.6'
|
gem 'jwt', '~> 1.5.6'
|
||||||
|
|
||||||
|
@ -57,10 +58,14 @@ gem 'validates_hostname', '~> 1.0.6'
|
||||||
# Browser detection
|
# Browser detection
|
||||||
gem 'browser', '~> 2.2'
|
gem 'browser', '~> 2.2'
|
||||||
|
|
||||||
|
# GPG
|
||||||
|
gem 'gpgme'
|
||||||
|
|
||||||
# LDAP Auth
|
# LDAP Auth
|
||||||
# GitLab fork with several improvements to original library. For full list of changes
|
# GitLab fork with several improvements to original library. For full list of changes
|
||||||
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
|
# see https://github.com/intridea/omniauth-ldap/compare/master...gitlabhq:master
|
||||||
gem 'gitlab_omniauth-ldap', '~> 1.2.1', require: 'omniauth-ldap'
|
gem 'gitlab_omniauth-ldap', '~> 2.0.3', require: 'omniauth-ldap'
|
||||||
|
gem 'net-ldap'
|
||||||
|
|
||||||
# Git Wiki
|
# Git Wiki
|
||||||
# Required manually in config/initializers/gollum.rb to control load order
|
# Required manually in config/initializers/gollum.rb to control load order
|
||||||
|
@ -71,7 +76,7 @@ gem 'gollum-rugged_adapter', '~> 0.4.4', require: false
|
||||||
gem 'github-linguist', '~> 4.7.0', require: 'linguist'
|
gem 'github-linguist', '~> 4.7.0', require: 'linguist'
|
||||||
|
|
||||||
# API
|
# API
|
||||||
gem 'grape', '~> 0.19.0'
|
gem 'grape', '~> 0.19.2'
|
||||||
gem 'grape-entity', '~> 0.6.0'
|
gem 'grape-entity', '~> 0.6.0'
|
||||||
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||||
|
|
||||||
|
@ -79,24 +84,25 @@ gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
|
||||||
gem 'hashie-forbidden_attributes'
|
gem 'hashie-forbidden_attributes'
|
||||||
|
|
||||||
# Pagination
|
# Pagination
|
||||||
gem 'kaminari', '~> 0.17.0'
|
gem 'kaminari', '~> 1.0'
|
||||||
|
|
||||||
# HAML
|
# HAML
|
||||||
gem 'hamlit', '~> 2.6.1'
|
gem 'hamlit', '~> 2.6.1'
|
||||||
|
|
||||||
# Files attachments
|
# Files attachments
|
||||||
gem 'carrierwave', '~> 1.0'
|
gem 'carrierwave', '~> 1.1'
|
||||||
|
|
||||||
# Drag and Drop UI
|
# Drag and Drop UI
|
||||||
gem 'dropzonejs-rails', '~> 0.7.1'
|
gem 'dropzonejs-rails', '~> 0.7.1'
|
||||||
|
|
||||||
# for backups
|
# for backups
|
||||||
gem 'fog-aws', '~> 0.9'
|
gem 'fog-aws', '~> 1.4'
|
||||||
gem 'fog-core', '~> 1.44'
|
gem 'fog-core', '~> 1.44'
|
||||||
gem 'fog-google', '~> 0.5'
|
gem 'fog-google', '~> 0.5'
|
||||||
gem 'fog-local', '~> 0.3'
|
gem 'fog-local', '~> 0.3'
|
||||||
gem 'fog-openstack', '~> 0.1'
|
gem 'fog-openstack', '~> 0.1'
|
||||||
gem 'fog-rackspace', '~> 0.1.1'
|
gem 'fog-rackspace', '~> 0.1.1'
|
||||||
|
gem 'fog-aliyun', '~> 0.1.0'
|
||||||
|
|
||||||
# for Google storage
|
# for Google storage
|
||||||
gem 'google-api-client', '~> 0.8.6'
|
gem 'google-api-client', '~> 0.8.6'
|
||||||
|
@ -109,7 +115,7 @@ gem 'seed-fu', '~> 2.3.5'
|
||||||
|
|
||||||
# Markdown and HTML processing
|
# Markdown and HTML processing
|
||||||
gem 'html-pipeline', '~> 1.11.0'
|
gem 'html-pipeline', '~> 1.11.0'
|
||||||
gem 'deckar01-task_list', '1.0.6', require: 'task_list/railtie'
|
gem 'deckar01-task_list', '2.0.0'
|
||||||
gem 'gitlab-markup', '~> 1.5.1'
|
gem 'gitlab-markup', '~> 1.5.1'
|
||||||
gem 'redcarpet', '~> 3.4'
|
gem 'redcarpet', '~> 3.4'
|
||||||
gem 'RedCloth', '~> 4.3.2'
|
gem 'RedCloth', '~> 4.3.2'
|
||||||
|
@ -120,11 +126,9 @@ gem 'wikicloth', '0.8.1'
|
||||||
gem 'asciidoctor', '~> 1.5.2'
|
gem 'asciidoctor', '~> 1.5.2'
|
||||||
gem 'asciidoctor-plantuml', '0.0.7'
|
gem 'asciidoctor-plantuml', '0.0.7'
|
||||||
gem 'rouge', '~> 2.0'
|
gem 'rouge', '~> 2.0'
|
||||||
gem 'truncato', '~> 0.7.8'
|
gem 'truncato', '~> 0.7.9'
|
||||||
|
gem 'bootstrap_form', '~> 2.7.0'
|
||||||
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
|
gem 'nokogiri', '~> 1.8.0'
|
||||||
# and https://groups.google.com/forum/#!topic/ruby-security-ann/Dy7YiKb_pMM
|
|
||||||
gem 'nokogiri', '~> 1.6.7', '>= 1.6.7.2'
|
|
||||||
|
|
||||||
# Diffs
|
# Diffs
|
||||||
gem 'diffy', '~> 3.1.0'
|
gem 'diffy', '~> 3.1.0'
|
||||||
|
@ -145,24 +149,24 @@ gem 'acts-as-taggable-on', '~> 4.0'
|
||||||
|
|
||||||
# Background jobs
|
# Background jobs
|
||||||
gem 'sidekiq', '~> 5.0'
|
gem 'sidekiq', '~> 5.0'
|
||||||
gem 'sidekiq-cron', '~> 0.4.4'
|
gem 'sidekiq-cron', '~> 0.6.0'
|
||||||
gem 'redis-namespace', '~> 1.5.2'
|
gem 'redis-namespace', '~> 1.5.2'
|
||||||
gem 'sidekiq-limit_fetch', '~> 3.4'
|
gem 'sidekiq-limit_fetch', '~> 3.4', require: false
|
||||||
|
|
||||||
# Cron Parser
|
# Cron Parser
|
||||||
gem 'rufus-scheduler', '~> 3.1.10'
|
gem 'rufus-scheduler', '~> 3.4'
|
||||||
|
|
||||||
# HTTP requests
|
# HTTP requests
|
||||||
gem 'httparty', '~> 0.13.3'
|
gem 'httparty', '~> 0.13.3'
|
||||||
|
|
||||||
# Colored output to console
|
# Colored output to console
|
||||||
gem 'rainbow', '~> 2.1.0'
|
gem 'rainbow', '~> 2.2'
|
||||||
|
|
||||||
# GitLab settings
|
# GitLab settings
|
||||||
gem 'settingslogic', '~> 2.0.9'
|
gem 'settingslogic', '~> 2.0.9'
|
||||||
|
|
||||||
# Linear-time regex library for untrusted regular expressions
|
# Linear-time regex library for untrusted regular expressions
|
||||||
gem 're2', '~> 1.0.0'
|
gem 're2', '~> 1.1.1'
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
|
|
||||||
|
@ -238,38 +242,52 @@ gem 'webpack-rails', '~> 0.9.10'
|
||||||
gem 'rack-proxy', '~> 0.6.0'
|
gem 'rack-proxy', '~> 0.6.0'
|
||||||
|
|
||||||
gem 'sass-rails', '~> 5.0.6'
|
gem 'sass-rails', '~> 5.0.6'
|
||||||
gem 'coffee-rails', '~> 4.1.0'
|
|
||||||
gem 'uglifier', '~> 2.7.2'
|
gem 'uglifier', '~> 2.7.2'
|
||||||
|
|
||||||
gem 'addressable', '~> 2.3.8'
|
gem 'addressable', '~> 2.3.8'
|
||||||
gem 'bootstrap-sass', '~> 3.3.0'
|
gem 'bootstrap-sass', '~> 3.3.0'
|
||||||
gem 'font-awesome-rails', '~> 4.7'
|
gem 'font-awesome-rails', '~> 4.7'
|
||||||
gem 'gemojione', '~> 3.0'
|
gem 'gemojione', '~> 3.3'
|
||||||
gem 'gon', '~> 6.1.0'
|
gem 'gon', '~> 6.1.0'
|
||||||
gem 'jquery-atwho-rails', '~> 1.3.2'
|
gem 'jquery-atwho-rails', '~> 1.3.2'
|
||||||
gem 'jquery-rails', '~> 4.1.0'
|
gem 'jquery-rails', '~> 4.1.0'
|
||||||
gem 'request_store', '~> 1.3'
|
gem 'request_store', '~> 1.3'
|
||||||
gem 'select2-rails', '~> 3.5.9'
|
gem 'select2-rails', '~> 3.5.9'
|
||||||
gem 'virtus', '~> 1.0.1'
|
gem 'virtus', '~> 1.0.1'
|
||||||
gem 'net-ssh', '~> 3.0.1'
|
|
||||||
gem 'base32', '~> 0.3.0'
|
gem 'base32', '~> 0.3.0'
|
||||||
|
|
||||||
# Sentry integration
|
# Sentry integration
|
||||||
gem 'sentry-raven', '~> 2.4.0'
|
gem 'sentry-raven', '~> 2.5.3'
|
||||||
|
|
||||||
gem 'premailer-rails', '~> 1.9.0'
|
gem 'premailer-rails', '~> 1.9.7'
|
||||||
|
|
||||||
# I18n
|
# I18n
|
||||||
gem 'ruby_parser', '~> 3.8.4', require: false
|
gem 'ruby_parser', '~> 3.8', require: false
|
||||||
|
gem 'rails-i18n', '~> 4.0.9'
|
||||||
gem 'gettext_i18n_rails', '~> 1.8.0'
|
gem 'gettext_i18n_rails', '~> 1.8.0'
|
||||||
gem 'gettext_i18n_rails_js', '~> 1.2.0'
|
gem 'gettext_i18n_rails_js', '~> 1.2.0'
|
||||||
gem 'gettext', '~> 3.2.2', require: false, group: :development
|
gem 'gettext', '~> 3.2.2', require: false, group: :development
|
||||||
|
|
||||||
|
# Perf bar
|
||||||
|
gem 'peek', '~> 1.0.1'
|
||||||
|
gem 'peek-gc', '~> 0.0.2'
|
||||||
|
gem 'peek-host', '~> 1.0.0'
|
||||||
|
gem 'peek-mysql2', '~> 1.1.0', group: :mysql
|
||||||
|
gem 'peek-performance_bar', '~> 1.3.0'
|
||||||
|
gem 'peek-pg', '~> 1.3.0', group: :postgres
|
||||||
|
gem 'peek-rblineprof', '~> 0.2.0'
|
||||||
|
gem 'peek-redis', '~> 1.2.0'
|
||||||
|
gem 'peek-sidekiq', '~> 1.0.3'
|
||||||
|
|
||||||
# Metrics
|
# Metrics
|
||||||
group :metrics do
|
group :metrics do
|
||||||
gem 'allocations', '~> 1.0', require: false, platform: :mri
|
gem 'allocations', '~> 1.0', require: false, platform: :mri
|
||||||
gem 'method_source', '~> 0.8', require: false
|
gem 'method_source', '~> 0.8', require: false
|
||||||
gem 'influxdb', '~> 0.2', require: false
|
gem 'influxdb', '~> 0.2', require: false
|
||||||
|
|
||||||
|
# Prometheus
|
||||||
|
gem 'prometheus-client-mmap', '~>0.7.0.beta14'
|
||||||
|
gem 'raindrops', '~> 0.18'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
|
@ -293,11 +311,11 @@ group :development, :test do
|
||||||
gem 'pry-rails', '~> 0.3.4'
|
gem 'pry-rails', '~> 0.3.4'
|
||||||
|
|
||||||
gem 'awesome_print', '~> 1.2.0', require: false
|
gem 'awesome_print', '~> 1.2.0', require: false
|
||||||
gem 'fuubar', '~> 2.0.0'
|
gem 'fuubar', '~> 2.2.0'
|
||||||
|
|
||||||
gem 'database_cleaner', '~> 1.5.0'
|
gem 'database_cleaner', '~> 1.5.0'
|
||||||
gem 'factory_girl_rails', '~> 4.7.0'
|
gem 'factory_girl_rails', '~> 4.7.0'
|
||||||
gem 'rspec-rails', '~> 3.5.0'
|
gem 'rspec-rails', '~> 3.6.0'
|
||||||
gem 'rspec-retry', '~> 0.4.5'
|
gem 'rspec-retry', '~> 0.4.5'
|
||||||
gem 'spinach-rails', '~> 0.2.1'
|
gem 'spinach-rails', '~> 0.2.1'
|
||||||
gem 'spinach-rerun-reporter', '~> 0.0.2'
|
gem 'spinach-rerun-reporter', '~> 0.0.2'
|
||||||
|
@ -318,10 +336,10 @@ group :development, :test do
|
||||||
gem 'spring-commands-rspec', '~> 1.0.4'
|
gem 'spring-commands-rspec', '~> 1.0.4'
|
||||||
gem 'spring-commands-spinach', '~> 1.1.0'
|
gem 'spring-commands-spinach', '~> 1.1.0'
|
||||||
|
|
||||||
gem 'rubocop', '~> 0.47.1', require: false
|
gem 'rubocop', '~> 0.49.1', require: false
|
||||||
gem 'rubocop-rspec', '~> 1.15.0', require: false
|
gem 'rubocop-rspec', '~> 1.15.1', require: false
|
||||||
gem 'scss_lint', '~> 0.47.0', require: false
|
gem 'scss_lint', '~> 0.54.0', require: false
|
||||||
gem 'haml_lint', '~> 0.21.0', require: false
|
gem 'haml_lint', '~> 0.26.0', require: false
|
||||||
gem 'simplecov', '~> 0.14.0', require: false
|
gem 'simplecov', '~> 0.14.0', require: false
|
||||||
gem 'flay', '~> 2.8.0', require: false
|
gem 'flay', '~> 2.8.0', require: false
|
||||||
gem 'bundler-audit', '~> 0.5.0', require: false
|
gem 'bundler-audit', '~> 0.5.0', require: false
|
||||||
|
@ -337,10 +355,10 @@ group :development, :test do
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'shoulda-matchers', '~> 2.8.0', require: false
|
gem 'shoulda-matchers', '~> 3.1.2', require: false
|
||||||
gem 'email_spec', '~> 1.6.0'
|
gem 'email_spec', '~> 1.6.0'
|
||||||
gem 'json-schema', '~> 2.6.2'
|
gem 'json-schema', '~> 2.6.2'
|
||||||
gem 'webmock', '~> 1.24.0'
|
gem 'webmock', '~> 2.3.2'
|
||||||
gem 'test_after_commit', '~> 1.1'
|
gem 'test_after_commit', '~> 1.1'
|
||||||
gem 'sham_rack', '~> 1.3.6'
|
gem 'sham_rack', '~> 1.3.6'
|
||||||
gem 'timecop', '~> 0.8.0'
|
gem 'timecop', '~> 0.8.0'
|
||||||
|
@ -357,10 +375,10 @@ gem 'html2text'
|
||||||
gem 'ruby-prof', '~> 0.16.2'
|
gem 'ruby-prof', '~> 0.16.2'
|
||||||
|
|
||||||
# OAuth
|
# OAuth
|
||||||
gem 'oauth2', '~> 1.3.0'
|
gem 'oauth2', '~> 1.4'
|
||||||
|
|
||||||
# Soft deletion
|
# Soft deletion
|
||||||
gem 'paranoia', '~> 2.2'
|
gem 'paranoia', '~> 2.3.1'
|
||||||
|
|
||||||
# Health check
|
# Health check
|
||||||
gem 'health_check', '~> 2.6.0'
|
gem 'health_check', '~> 2.6.0'
|
||||||
|
@ -369,7 +387,24 @@ gem 'health_check', '~> 2.6.0'
|
||||||
gem 'vmstat', '~> 2.3.0'
|
gem 'vmstat', '~> 2.3.0'
|
||||||
gem 'sys-filesystem', '~> 1.1.6'
|
gem 'sys-filesystem', '~> 1.1.6'
|
||||||
|
|
||||||
|
# SSH host key support
|
||||||
|
gem 'net-ssh', '~> 4.1.0'
|
||||||
|
|
||||||
|
# Required for ED25519 SSH host key support
|
||||||
|
group :ed25519 do
|
||||||
|
gem 'rbnacl-libsodium'
|
||||||
|
gem 'rbnacl', '~> 3.2'
|
||||||
|
gem 'bcrypt_pbkdf', '~> 1.0'
|
||||||
|
end
|
||||||
|
|
||||||
# Gitaly GRPC client
|
# Gitaly GRPC client
|
||||||
gem 'gitaly', '~> 0.6.0'
|
gem 'gitaly', '~> 0.26.0'
|
||||||
|
|
||||||
gem 'toml-rb', '~> 0.3.15', require: false
|
gem 'toml-rb', '~> 0.3.15', require: false
|
||||||
|
|
||||||
|
# Feature toggles
|
||||||
|
gem 'flipper', '~> 0.10.2'
|
||||||
|
gem 'flipper-active_record', '~> 0.10.2'
|
||||||
|
|
||||||
|
# Structured logging
|
||||||
|
gem 'lograge', '~> 0.5'
|
||||||
|
|
397
Gemfile.lock
397
Gemfile.lock
|
@ -56,6 +56,7 @@ GEM
|
||||||
asciidoctor-plantuml (0.0.7)
|
asciidoctor-plantuml (0.0.7)
|
||||||
asciidoctor (~> 1.5)
|
asciidoctor (~> 1.5)
|
||||||
ast (2.3.0)
|
ast (2.3.0)
|
||||||
|
atomic (1.1.99)
|
||||||
attr_encrypted (3.0.3)
|
attr_encrypted (3.0.3)
|
||||||
encryptor (~> 3.0.0)
|
encryptor (~> 3.0.0)
|
||||||
attr_required (1.0.0)
|
attr_required (1.0.0)
|
||||||
|
@ -74,6 +75,7 @@ GEM
|
||||||
babosa (1.0.2)
|
babosa (1.0.2)
|
||||||
base32 (0.3.2)
|
base32 (0.3.2)
|
||||||
bcrypt (3.1.11)
|
bcrypt (3.1.11)
|
||||||
|
bcrypt_pbkdf (1.0.0)
|
||||||
benchmark-ips (2.3.0)
|
benchmark-ips (2.3.0)
|
||||||
better_errors (2.1.1)
|
better_errors (2.1.1)
|
||||||
coderay (>= 1.0.0)
|
coderay (>= 1.0.0)
|
||||||
|
@ -85,6 +87,7 @@ 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)
|
||||||
|
bootstrap_form (2.7.0)
|
||||||
brakeman (3.6.1)
|
brakeman (3.6.1)
|
||||||
browser (2.2.0)
|
browser (2.2.0)
|
||||||
builder (3.2.3)
|
builder (3.2.3)
|
||||||
|
@ -105,7 +108,7 @@ GEM
|
||||||
capybara-screenshot (1.0.14)
|
capybara-screenshot (1.0.14)
|
||||||
capybara (>= 1.0, < 3)
|
capybara (>= 1.0, < 3)
|
||||||
launchy
|
launchy
|
||||||
carrierwave (1.0.0)
|
carrierwave (1.1.0)
|
||||||
activemodel (>= 4.0.0)
|
activemodel (>= 4.0.0)
|
||||||
activesupport (>= 4.0.0)
|
activesupport (>= 4.0.0)
|
||||||
mime-types (>= 1.16)
|
mime-types (>= 1.16)
|
||||||
|
@ -120,20 +123,15 @@ GEM
|
||||||
coderay (1.1.1)
|
coderay (1.1.1)
|
||||||
coercible (1.0.0)
|
coercible (1.0.0)
|
||||||
descendants_tracker (~> 0.0.1)
|
descendants_tracker (~> 0.0.1)
|
||||||
coffee-rails (4.1.1)
|
|
||||||
coffee-script (>= 2.2.0)
|
|
||||||
railties (>= 4.0.0, < 5.1.x)
|
|
||||||
coffee-script (2.4.1)
|
|
||||||
coffee-script-source
|
|
||||||
execjs
|
|
||||||
coffee-script-source (1.10.0)
|
|
||||||
colorize (0.7.7)
|
colorize (0.7.7)
|
||||||
concurrent-ruby (1.0.5)
|
concurrent-ruby (1.0.5)
|
||||||
|
concurrent-ruby-ext (1.0.5)
|
||||||
|
concurrent-ruby (= 1.0.5)
|
||||||
connection_pool (2.2.1)
|
connection_pool (2.2.1)
|
||||||
crack (0.4.3)
|
crack (0.4.3)
|
||||||
safe_yaml (~> 1.0.0)
|
safe_yaml (~> 1.0.0)
|
||||||
creole (0.5.0)
|
creole (0.5.0)
|
||||||
css_parser (1.4.1)
|
css_parser (1.5.0)
|
||||||
addressable
|
addressable
|
||||||
d3_rails (3.5.11)
|
d3_rails (3.5.11)
|
||||||
railties (>= 3.1.0)
|
railties (>= 3.1.0)
|
||||||
|
@ -141,10 +139,8 @@ GEM
|
||||||
database_cleaner (1.5.3)
|
database_cleaner (1.5.3)
|
||||||
debug_inspector (0.0.2)
|
debug_inspector (0.0.2)
|
||||||
debugger-ruby_core_source (1.3.8)
|
debugger-ruby_core_source (1.3.8)
|
||||||
deckar01-task_list (1.0.6)
|
deckar01-task_list (2.0.0)
|
||||||
activesupport (~> 4.0)
|
|
||||||
html-pipeline
|
html-pipeline
|
||||||
rack (~> 1.0)
|
|
||||||
default_value_for (3.0.2)
|
default_value_for (3.0.2)
|
||||||
activerecord (>= 3.2.0, < 5.1)
|
activerecord (>= 3.2.0, < 5.1)
|
||||||
descendants_tracker (0.0.4)
|
descendants_tracker (0.0.4)
|
||||||
|
@ -161,7 +157,7 @@ GEM
|
||||||
devise (~> 4.0)
|
devise (~> 4.0)
|
||||||
railties
|
railties
|
||||||
rotp (~> 2.0)
|
rotp (~> 2.0)
|
||||||
diff-lcs (1.2.5)
|
diff-lcs (1.3)
|
||||||
diffy (3.1.0)
|
diffy (3.1.0)
|
||||||
docile (1.1.5)
|
docile (1.1.5)
|
||||||
domain_name (0.5.20161021)
|
domain_name (0.5.20161021)
|
||||||
|
@ -181,8 +177,10 @@ GEM
|
||||||
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)
|
||||||
|
et-orbi (1.0.3)
|
||||||
|
tzinfo
|
||||||
eventmachine (1.0.8)
|
eventmachine (1.0.8)
|
||||||
excon (0.55.0)
|
excon (0.57.1)
|
||||||
execjs (2.6.0)
|
execjs (2.6.0)
|
||||||
expression_parser (0.9.0)
|
expression_parser (0.9.0)
|
||||||
extlib (0.9.16)
|
extlib (0.9.16)
|
||||||
|
@ -191,7 +189,7 @@ GEM
|
||||||
factory_girl_rails (4.7.0)
|
factory_girl_rails (4.7.0)
|
||||||
factory_girl (~> 4.7.0)
|
factory_girl (~> 4.7.0)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
faraday (0.11.0)
|
faraday (0.12.1)
|
||||||
multipart-post (>= 1.2, < 3)
|
multipart-post (>= 1.2, < 3)
|
||||||
faraday_middleware (0.11.0.1)
|
faraday_middleware (0.11.0.1)
|
||||||
faraday (>= 0.7.4, < 1.0)
|
faraday (>= 0.7.4, < 1.0)
|
||||||
|
@ -206,29 +204,38 @@ GEM
|
||||||
path_expander (~> 1.0)
|
path_expander (~> 1.0)
|
||||||
ruby_parser (~> 3.0)
|
ruby_parser (~> 3.0)
|
||||||
sexp_processor (~> 4.0)
|
sexp_processor (~> 4.0)
|
||||||
|
flipper (0.10.2)
|
||||||
|
flipper-active_record (0.10.2)
|
||||||
|
activerecord (>= 3.2, < 6)
|
||||||
|
flipper (~> 0.10.2)
|
||||||
flowdock (0.7.1)
|
flowdock (0.7.1)
|
||||||
httparty (~> 0.7)
|
httparty (~> 0.7)
|
||||||
multi_json
|
multi_json
|
||||||
fog-aws (0.13.0)
|
fog-aliyun (0.1.0)
|
||||||
|
fog-core (~> 1.27)
|
||||||
|
fog-json (~> 1.0)
|
||||||
|
ipaddress (~> 0.8)
|
||||||
|
xml-simple (~> 1.1)
|
||||||
|
fog-aws (1.4.0)
|
||||||
fog-core (~> 1.38)
|
fog-core (~> 1.38)
|
||||||
fog-json (~> 1.0)
|
fog-json (~> 1.0)
|
||||||
fog-xml (~> 0.1)
|
fog-xml (~> 0.1)
|
||||||
ipaddress (~> 0.8)
|
ipaddress (~> 0.8)
|
||||||
fog-core (1.44.1)
|
fog-core (1.44.3)
|
||||||
builder
|
builder
|
||||||
excon (~> 0.49)
|
excon (~> 0.49)
|
||||||
formatador (~> 0.2)
|
formatador (~> 0.2)
|
||||||
fog-google (0.5.0)
|
fog-google (0.5.3)
|
||||||
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.3.0)
|
fog-local (0.3.1)
|
||||||
fog-core (~> 1.27)
|
fog-core (~> 1.27)
|
||||||
fog-openstack (0.1.6)
|
fog-openstack (0.1.21)
|
||||||
fog-core (>= 1.39)
|
fog-core (>= 1.40)
|
||||||
fog-json (>= 1.0)
|
fog-json (>= 1.0)
|
||||||
ipaddress (>= 0.8)
|
ipaddress (>= 0.8)
|
||||||
fog-rackspace (0.1.1)
|
fog-rackspace (0.1.1)
|
||||||
|
@ -244,12 +251,12 @@ GEM
|
||||||
foreman (0.78.0)
|
foreman (0.78.0)
|
||||||
thor (~> 0.19.1)
|
thor (~> 0.19.1)
|
||||||
formatador (0.2.5)
|
formatador (0.2.5)
|
||||||
fuubar (2.0.0)
|
fuubar (2.2.0)
|
||||||
rspec (~> 3.0)
|
rspec-core (~> 3.0)
|
||||||
ruby-progressbar (~> 1.4)
|
ruby-progressbar (~> 1.4)
|
||||||
gemnasium-gitlab-service (0.2.6)
|
gemnasium-gitlab-service (0.2.6)
|
||||||
rugged (~> 0.21)
|
rugged (~> 0.21)
|
||||||
gemojione (3.0.1)
|
gemojione (3.3.0)
|
||||||
json
|
json
|
||||||
get_process_mem (0.2.0)
|
get_process_mem (0.2.0)
|
||||||
gettext (3.2.2)
|
gettext (3.2.2)
|
||||||
|
@ -263,7 +270,7 @@ GEM
|
||||||
po_to_json (>= 1.0.0)
|
po_to_json (>= 1.0.0)
|
||||||
rails (>= 3.2.0)
|
rails (>= 3.2.0)
|
||||||
gherkin-ruby (0.3.2)
|
gherkin-ruby (0.3.2)
|
||||||
gitaly (0.6.0)
|
gitaly (0.26.0)
|
||||||
google-protobuf (~> 3.1)
|
google-protobuf (~> 3.1)
|
||||||
grpc (~> 1.0)
|
grpc (~> 1.0)
|
||||||
github-linguist (4.7.6)
|
github-linguist (4.7.6)
|
||||||
|
@ -271,7 +278,7 @@ GEM
|
||||||
escape_utils (~> 1.1.0)
|
escape_utils (~> 1.1.0)
|
||||||
mime-types (>= 1.19)
|
mime-types (>= 1.19)
|
||||||
rugged (>= 0.23.0b)
|
rugged (>= 0.23.0b)
|
||||||
github-markup (1.4.0)
|
github-markup (1.6.1)
|
||||||
gitlab-flowdock-git-hook (1.0.1)
|
gitlab-flowdock-git-hook (1.0.1)
|
||||||
flowdock (~> 0.7)
|
flowdock (~> 0.7)
|
||||||
gitlab-grit (>= 2.4.1)
|
gitlab-grit (>= 2.4.1)
|
||||||
|
@ -282,22 +289,23 @@ GEM
|
||||||
mime-types (>= 1.16, < 3)
|
mime-types (>= 1.16, < 3)
|
||||||
posix-spawn (~> 0.3)
|
posix-spawn (~> 0.3)
|
||||||
gitlab-markup (1.5.1)
|
gitlab-markup (1.5.1)
|
||||||
gitlab_omniauth-ldap (1.2.1)
|
gitlab_omniauth-ldap (2.0.3)
|
||||||
net-ldap (~> 0.9)
|
net-ldap (~> 0.16)
|
||||||
omniauth (~> 1.0)
|
omniauth (~> 1.3)
|
||||||
pyu-ruby-sasl (~> 0.0.3.1)
|
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
|
||||||
rubyntlm (~> 0.3)
|
rubyntlm (~> 0.5)
|
||||||
globalid (0.3.7)
|
globalid (0.3.7)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
gollum-grit_adapter (1.0.1)
|
gollum-grit_adapter (1.0.1)
|
||||||
gitlab-grit (~> 2.7, >= 2.7.1)
|
gitlab-grit (~> 2.7, >= 2.7.1)
|
||||||
gollum-lib (4.2.1)
|
gollum-lib (4.2.7)
|
||||||
github-markup (~> 1.4.0)
|
gemojione (~> 3.2)
|
||||||
|
github-markup (~> 1.6)
|
||||||
gollum-grit_adapter (~> 1.0)
|
gollum-grit_adapter (~> 1.0)
|
||||||
nokogiri (~> 1.6.4)
|
nokogiri (>= 1.6.1, < 2.0)
|
||||||
rouge (~> 2.0)
|
rouge (~> 2.1)
|
||||||
sanitize (~> 2.1.0)
|
sanitize (~> 2.1)
|
||||||
stringex (~> 2.5.1)
|
stringex (~> 2.6)
|
||||||
gollum-rugged_adapter (0.4.4)
|
gollum-rugged_adapter (0.4.4)
|
||||||
mime-types (>= 1.15)
|
mime-types (>= 1.15)
|
||||||
rugged (~> 0.25)
|
rugged (~> 0.25)
|
||||||
|
@ -317,7 +325,7 @@ GEM
|
||||||
multi_json (~> 1.10)
|
multi_json (~> 1.10)
|
||||||
retriable (~> 1.4)
|
retriable (~> 1.4)
|
||||||
signet (~> 0.6)
|
signet (~> 0.6)
|
||||||
google-protobuf (3.2.0.2)
|
google-protobuf (3.3.0)
|
||||||
googleauth (0.5.1)
|
googleauth (0.5.1)
|
||||||
faraday (~> 0.9)
|
faraday (~> 0.9)
|
||||||
jwt (~> 1.4)
|
jwt (~> 1.4)
|
||||||
|
@ -326,34 +334,41 @@ GEM
|
||||||
multi_json (~> 1.11)
|
multi_json (~> 1.11)
|
||||||
os (~> 0.9)
|
os (~> 0.9)
|
||||||
signet (~> 0.7)
|
signet (~> 0.7)
|
||||||
grape (0.19.1)
|
gpgme (2.0.13)
|
||||||
|
mini_portile2 (~> 2.1)
|
||||||
|
grape (0.19.2)
|
||||||
activesupport
|
activesupport
|
||||||
builder
|
builder
|
||||||
hashie (>= 2.1.0)
|
hashie (>= 2.1.0)
|
||||||
multi_json (>= 1.3.2)
|
multi_json (>= 1.3.2)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
mustermann-grape (~> 0.4.0)
|
mustermann-grape (~> 1.0.0)
|
||||||
rack (>= 1.3.0)
|
rack (>= 1.3.0)
|
||||||
rack-accept
|
rack-accept
|
||||||
virtus (>= 1.0.0)
|
virtus (>= 1.0.0)
|
||||||
grape-entity (0.6.0)
|
grape-entity (0.6.0)
|
||||||
activesupport
|
activesupport
|
||||||
multi_json (>= 1.3.2)
|
multi_json (>= 1.3.2)
|
||||||
grpc (1.2.5)
|
grape-route-helpers (2.0.0)
|
||||||
|
activesupport
|
||||||
|
grape (~> 0.16, >= 0.16.0)
|
||||||
|
rake
|
||||||
|
grpc (1.4.0)
|
||||||
google-protobuf (~> 3.1)
|
google-protobuf (~> 3.1)
|
||||||
googleauth (~> 0.5.1)
|
googleauth (~> 0.5.1)
|
||||||
haml (4.0.7)
|
haml (4.0.7)
|
||||||
tilt
|
tilt
|
||||||
haml_lint (0.21.0)
|
haml_lint (0.26.0)
|
||||||
haml (~> 4.0)
|
haml (>= 4.0, < 5.1)
|
||||||
|
rainbow
|
||||||
rake (>= 10, < 13)
|
rake (>= 10, < 13)
|
||||||
rubocop (>= 0.47.0)
|
rubocop (>= 0.49.0)
|
||||||
sysexits (~> 1.1)
|
sysexits (~> 1.1)
|
||||||
hamlit (2.6.1)
|
hamlit (2.6.1)
|
||||||
temple (~> 0.7.6)
|
temple (~> 0.7.6)
|
||||||
thor
|
thor
|
||||||
tilt
|
tilt
|
||||||
hashdiff (0.3.2)
|
hashdiff (0.3.4)
|
||||||
hashie (3.5.5)
|
hashie (3.5.5)
|
||||||
hashie-forbidden_attributes (0.1.1)
|
hashie-forbidden_attributes (0.1.1)
|
||||||
hashie (>= 3.0)
|
hashie (>= 3.0)
|
||||||
|
@ -381,7 +396,7 @@ GEM
|
||||||
json (~> 1.8)
|
json (~> 1.8)
|
||||||
multi_xml (>= 0.5.2)
|
multi_xml (>= 0.5.2)
|
||||||
httpclient (2.8.2)
|
httpclient (2.8.2)
|
||||||
i18n (0.8.1)
|
i18n (0.8.6)
|
||||||
ice_nine (0.11.2)
|
ice_nine (0.11.2)
|
||||||
influxdb (0.2.3)
|
influxdb (0.2.3)
|
||||||
cause
|
cause
|
||||||
|
@ -405,9 +420,18 @@ GEM
|
||||||
json-schema (2.6.2)
|
json-schema (2.6.2)
|
||||||
addressable (~> 2.3.8)
|
addressable (~> 2.3.8)
|
||||||
jwt (1.5.6)
|
jwt (1.5.6)
|
||||||
kaminari (0.17.0)
|
kaminari (1.0.1)
|
||||||
actionpack (>= 3.0.0)
|
activesupport (>= 4.1.0)
|
||||||
activesupport (>= 3.0.0)
|
kaminari-actionview (= 1.0.1)
|
||||||
|
kaminari-activerecord (= 1.0.1)
|
||||||
|
kaminari-core (= 1.0.1)
|
||||||
|
kaminari-actionview (1.0.1)
|
||||||
|
actionview
|
||||||
|
kaminari-core (= 1.0.1)
|
||||||
|
kaminari-activerecord (1.0.1)
|
||||||
|
activerecord
|
||||||
|
kaminari-core (= 1.0.1)
|
||||||
|
kaminari-core (1.0.1)
|
||||||
kgio (2.10.0)
|
kgio (2.10.0)
|
||||||
knapsack (1.11.0)
|
knapsack (1.11.0)
|
||||||
rake
|
rake
|
||||||
|
@ -437,35 +461,39 @@ GEM
|
||||||
logging (2.2.2)
|
logging (2.2.2)
|
||||||
little-plugger (~> 1.1)
|
little-plugger (~> 1.1)
|
||||||
multi_json (~> 1.10)
|
multi_json (~> 1.10)
|
||||||
|
lograge (0.5.1)
|
||||||
|
actionpack (>= 4, < 5.2)
|
||||||
|
activesupport (>= 4, < 5.2)
|
||||||
|
railties (>= 4, < 5.2)
|
||||||
loofah (2.0.3)
|
loofah (2.0.3)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.6.5)
|
mail (2.6.6)
|
||||||
mime-types (>= 1.16, < 4)
|
mime-types (>= 1.16, < 4)
|
||||||
mail_room (0.9.1)
|
mail_room (0.9.1)
|
||||||
memoist (0.15.0)
|
memoist (0.15.0)
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (2.99.3)
|
mime-types (2.99.3)
|
||||||
mimemagic (0.3.0)
|
mimemagic (0.3.0)
|
||||||
mini_portile2 (2.1.0)
|
mini_portile2 (2.2.0)
|
||||||
minitest (5.7.0)
|
minitest (5.7.0)
|
||||||
|
mmap2 (2.2.7)
|
||||||
mousetrap-rails (1.4.6)
|
mousetrap-rails (1.4.6)
|
||||||
multi_json (1.12.1)
|
multi_json (1.12.1)
|
||||||
multi_xml (0.6.0)
|
multi_xml (0.6.0)
|
||||||
multipart-post (2.0.0)
|
multipart-post (2.0.0)
|
||||||
mustermann (0.4.0)
|
mustermann (1.0.0)
|
||||||
tool (~> 0.2)
|
mustermann-grape (1.0.0)
|
||||||
mustermann-grape (0.4.0)
|
mustermann (~> 1.0.0)
|
||||||
mustermann (= 0.4.0)
|
mysql2 (0.4.5)
|
||||||
mysql2 (0.3.20)
|
net-ldap (0.16.0)
|
||||||
net-ldap (0.12.1)
|
net-ssh (4.1.0)
|
||||||
net-ssh (3.0.1)
|
|
||||||
netrc (0.11.0)
|
netrc (0.11.0)
|
||||||
nokogiri (1.6.8.1)
|
nokogiri (1.8.0)
|
||||||
mini_portile2 (~> 2.1.0)
|
mini_portile2 (~> 2.2.0)
|
||||||
numerizer (0.1.1)
|
numerizer (0.1.1)
|
||||||
oauth (0.5.1)
|
oauth (0.5.1)
|
||||||
oauth2 (1.3.1)
|
oauth2 (1.4.0)
|
||||||
faraday (>= 0.8, < 0.12)
|
faraday (>= 0.8, < 0.13)
|
||||||
jwt (~> 1.0)
|
jwt (~> 1.0)
|
||||||
multi_json (~> 1.3)
|
multi_json (~> 1.3)
|
||||||
multi_xml (~> 0.5)
|
multi_xml (~> 0.5)
|
||||||
|
@ -478,15 +506,15 @@ GEM
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
omniauth-auth0 (1.4.1)
|
omniauth-auth0 (1.4.1)
|
||||||
omniauth-oauth2 (~> 1.1)
|
omniauth-oauth2 (~> 1.1)
|
||||||
omniauth-authentiq (0.3.0)
|
omniauth-authentiq (0.3.1)
|
||||||
omniauth-oauth2 (~> 1.3, >= 1.3.1)
|
omniauth-oauth2 (~> 1.3, >= 1.3.1)
|
||||||
omniauth-azure-oauth2 (0.0.6)
|
omniauth-azure-oauth2 (0.0.6)
|
||||||
jwt (~> 1.0)
|
jwt (~> 1.0)
|
||||||
omniauth (~> 1.0)
|
omniauth (~> 1.0)
|
||||||
omniauth-oauth2 (~> 1.1)
|
omniauth-oauth2 (~> 1.1)
|
||||||
omniauth-cas3 (1.1.3)
|
omniauth-cas3 (1.1.4)
|
||||||
addressable (~> 2.3)
|
addressable (~> 2.3)
|
||||||
nokogiri (~> 1.6.6)
|
nokogiri (~> 1.7, >= 1.7.1)
|
||||||
omniauth (~> 1.2)
|
omniauth (~> 1.2)
|
||||||
omniauth-facebook (4.0.0)
|
omniauth-facebook (4.0.0)
|
||||||
omniauth-oauth2 (~> 1.2)
|
omniauth-oauth2 (~> 1.2)
|
||||||
|
@ -530,11 +558,42 @@ GEM
|
||||||
rubypants (~> 0.2)
|
rubypants (~> 0.2)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
os (0.9.6)
|
os (0.9.6)
|
||||||
paranoia (2.2.0)
|
parallel (1.11.2)
|
||||||
activerecord (>= 4.0, < 5.1)
|
paranoia (2.3.1)
|
||||||
|
activerecord (>= 4.0, < 5.2)
|
||||||
parser (2.4.0.0)
|
parser (2.4.0.0)
|
||||||
ast (~> 2.2)
|
ast (~> 2.2)
|
||||||
path_expander (1.0.1)
|
path_expander (1.0.1)
|
||||||
|
peek (1.0.1)
|
||||||
|
concurrent-ruby (>= 0.9.0)
|
||||||
|
concurrent-ruby-ext (>= 0.9.0)
|
||||||
|
railties (>= 4.0.0)
|
||||||
|
peek-gc (0.0.2)
|
||||||
|
peek
|
||||||
|
peek-host (1.0.0)
|
||||||
|
peek
|
||||||
|
peek-mysql2 (1.1.0)
|
||||||
|
atomic (>= 1.0.0)
|
||||||
|
mysql2
|
||||||
|
peek
|
||||||
|
peek-performance_bar (1.3.0)
|
||||||
|
peek (>= 0.1.0)
|
||||||
|
peek-pg (1.3.0)
|
||||||
|
concurrent-ruby
|
||||||
|
concurrent-ruby-ext
|
||||||
|
peek
|
||||||
|
pg
|
||||||
|
peek-rblineprof (0.2.0)
|
||||||
|
peek
|
||||||
|
rblineprof
|
||||||
|
peek-redis (1.2.0)
|
||||||
|
atomic (>= 1.0.0)
|
||||||
|
peek
|
||||||
|
redis
|
||||||
|
peek-sidekiq (1.0.3)
|
||||||
|
atomic (>= 1.0.0)
|
||||||
|
peek
|
||||||
|
sidekiq
|
||||||
pg (0.18.4)
|
pg (0.18.4)
|
||||||
po_to_json (1.0.1)
|
po_to_json (1.0.1)
|
||||||
json (>= 1.6.0)
|
json (>= 1.6.0)
|
||||||
|
@ -543,14 +602,22 @@ GEM
|
||||||
cliver (~> 0.3.1)
|
cliver (~> 0.3.1)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
websocket-driver (>= 0.2.0)
|
websocket-driver (>= 0.2.0)
|
||||||
posix-spawn (0.3.11)
|
posix-spawn (0.3.13)
|
||||||
powerpack (0.1.1)
|
powerpack (0.1.1)
|
||||||
premailer (1.8.6)
|
premailer (1.10.4)
|
||||||
css_parser (>= 1.3.6)
|
addressable
|
||||||
|
css_parser (>= 1.4.10)
|
||||||
htmlentities (>= 4.0.0)
|
htmlentities (>= 4.0.0)
|
||||||
premailer-rails (1.9.2)
|
premailer-rails (1.9.7)
|
||||||
actionmailer (>= 3, < 6)
|
actionmailer (>= 3, < 6)
|
||||||
premailer (~> 1.7, >= 1.7.9)
|
premailer (~> 1.7, >= 1.7.9)
|
||||||
|
proc_to_ast (0.1.0)
|
||||||
|
coderay
|
||||||
|
parser
|
||||||
|
unparser
|
||||||
|
procto (0.0.3)
|
||||||
|
prometheus-client-mmap (0.7.0.beta14)
|
||||||
|
mmap2 (~> 2.2, >= 2.2.7)
|
||||||
pry (0.10.4)
|
pry (0.10.4)
|
||||||
coderay (~> 1.1.0)
|
coderay (~> 1.1.0)
|
||||||
method_source (~> 0.8.1)
|
method_source (~> 0.8.1)
|
||||||
|
@ -561,7 +628,7 @@ GEM
|
||||||
pry-rails (0.3.5)
|
pry-rails (0.3.5)
|
||||||
pry (>= 0.9.10)
|
pry (>= 0.9.10)
|
||||||
pyu-ruby-sasl (0.0.3.3)
|
pyu-ruby-sasl (0.0.3.3)
|
||||||
rack (1.6.5)
|
rack (1.6.8)
|
||||||
rack-accept (0.4.5)
|
rack-accept (0.4.5)
|
||||||
rack (>= 0.4)
|
rack (>= 0.4)
|
||||||
rack-attack (4.4.1)
|
rack-attack (4.4.1)
|
||||||
|
@ -598,19 +665,27 @@ GEM
|
||||||
rails-deprecated_sanitizer (>= 1.0.1)
|
rails-deprecated_sanitizer (>= 1.0.1)
|
||||||
rails-html-sanitizer (1.0.3)
|
rails-html-sanitizer (1.0.3)
|
||||||
loofah (~> 2.0)
|
loofah (~> 2.0)
|
||||||
|
rails-i18n (4.0.9)
|
||||||
|
i18n (~> 0.7)
|
||||||
|
railties (~> 4.0)
|
||||||
railties (4.2.8)
|
railties (4.2.8)
|
||||||
actionpack (= 4.2.8)
|
actionpack (= 4.2.8)
|
||||||
activesupport (= 4.2.8)
|
activesupport (= 4.2.8)
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
rainbow (2.1.0)
|
rainbow (2.2.2)
|
||||||
raindrops (0.17.0)
|
rake
|
||||||
rake (10.5.0)
|
raindrops (0.18.0)
|
||||||
|
rake (12.0.0)
|
||||||
rblineprof (0.3.6)
|
rblineprof (0.3.6)
|
||||||
debugger-ruby_core_source (~> 1.3)
|
debugger-ruby_core_source (~> 1.3)
|
||||||
|
rbnacl (3.4.0)
|
||||||
|
ffi
|
||||||
|
rbnacl-libsodium (1.0.11)
|
||||||
|
rbnacl (>= 3.0.1)
|
||||||
rdoc (4.2.2)
|
rdoc (4.2.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
re2 (1.0.0)
|
re2 (1.1.1)
|
||||||
recaptcha (3.0.0)
|
recaptcha (3.0.0)
|
||||||
json
|
json
|
||||||
recursive-open-struct (1.0.0)
|
recursive-open-struct (1.0.0)
|
||||||
|
@ -644,47 +719,44 @@ GEM
|
||||||
retriable (1.4.1)
|
retriable (1.4.1)
|
||||||
rinku (2.0.0)
|
rinku (2.0.0)
|
||||||
rotp (2.1.2)
|
rotp (2.1.2)
|
||||||
rouge (2.0.7)
|
rouge (2.1.0)
|
||||||
rqrcode (0.7.0)
|
rqrcode (0.7.0)
|
||||||
chunky_png
|
chunky_png
|
||||||
rqrcode-rails3 (0.1.7)
|
rqrcode-rails3 (0.1.7)
|
||||||
rqrcode (>= 0.4.2)
|
rqrcode (>= 0.4.2)
|
||||||
rspec (3.5.0)
|
rspec-core (3.6.0)
|
||||||
rspec-core (~> 3.5.0)
|
rspec-support (~> 3.6.0)
|
||||||
rspec-expectations (~> 3.5.0)
|
rspec-expectations (3.6.0)
|
||||||
rspec-mocks (~> 3.5.0)
|
|
||||||
rspec-core (3.5.0)
|
|
||||||
rspec-support (~> 3.5.0)
|
|
||||||
rspec-expectations (3.5.0)
|
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.5.0)
|
rspec-support (~> 3.6.0)
|
||||||
rspec-mocks (3.5.0)
|
rspec-mocks (3.6.0)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.5.0)
|
rspec-support (~> 3.6.0)
|
||||||
rspec-rails (3.5.0)
|
rspec-rails (3.6.0)
|
||||||
actionpack (>= 3.0)
|
actionpack (>= 3.0)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 3.0)
|
||||||
railties (>= 3.0)
|
railties (>= 3.0)
|
||||||
rspec-core (~> 3.5.0)
|
rspec-core (~> 3.6.0)
|
||||||
rspec-expectations (~> 3.5.0)
|
rspec-expectations (~> 3.6.0)
|
||||||
rspec-mocks (~> 3.5.0)
|
rspec-mocks (~> 3.6.0)
|
||||||
rspec-support (~> 3.5.0)
|
rspec-support (~> 3.6.0)
|
||||||
rspec-retry (0.4.5)
|
rspec-retry (0.4.5)
|
||||||
rspec-core
|
rspec-core
|
||||||
rspec-set (0.1.3)
|
rspec-set (0.1.3)
|
||||||
rspec-support (3.5.0)
|
rspec-support (3.6.0)
|
||||||
rspec_profiling (0.0.5)
|
rspec_profiling (0.0.5)
|
||||||
activerecord
|
activerecord
|
||||||
pg
|
pg
|
||||||
rails
|
rails
|
||||||
sqlite3
|
sqlite3
|
||||||
rubocop (0.47.1)
|
rubocop (0.49.1)
|
||||||
|
parallel (~> 1.10)
|
||||||
parser (>= 2.3.3.1, < 3.0)
|
parser (>= 2.3.3.1, < 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.15.0)
|
rubocop-rspec (1.15.1)
|
||||||
rubocop (>= 0.42.0)
|
rubocop (>= 0.42.0)
|
||||||
ruby-fogbugz (0.2.1)
|
ruby-fogbugz (0.2.1)
|
||||||
crack (~> 0.4)
|
crack (~> 0.4)
|
||||||
|
@ -692,13 +764,14 @@ GEM
|
||||||
ruby-progressbar (1.8.1)
|
ruby-progressbar (1.8.1)
|
||||||
ruby-saml (1.4.1)
|
ruby-saml (1.4.1)
|
||||||
nokogiri (>= 1.5.10)
|
nokogiri (>= 1.5.10)
|
||||||
ruby_parser (3.8.4)
|
ruby_parser (3.9.0)
|
||||||
sexp_processor (~> 4.1)
|
sexp_processor (~> 4.1)
|
||||||
rubyntlm (0.5.2)
|
rubyntlm (0.6.2)
|
||||||
rubypants (0.2.0)
|
rubypants (0.2.0)
|
||||||
rubyzip (1.2.1)
|
rubyzip (1.2.1)
|
||||||
rufus-scheduler (3.1.10)
|
rufus-scheduler (3.4.0)
|
||||||
rugged (0.25.1.1)
|
et-orbi (~> 1.0)
|
||||||
|
rugged (0.26.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)
|
||||||
|
@ -712,31 +785,30 @@ GEM
|
||||||
sawyer (0.8.1)
|
sawyer (0.8.1)
|
||||||
addressable (>= 2.3.5, < 2.6)
|
addressable (>= 2.3.5, < 2.6)
|
||||||
faraday (~> 0.8, < 1.0)
|
faraday (~> 0.8, < 1.0)
|
||||||
scss_lint (0.47.1)
|
scss_lint (0.54.0)
|
||||||
rake (>= 0.9, < 11)
|
rake (>= 0.9, < 13)
|
||||||
sass (~> 3.4.15)
|
sass (~> 3.4.20)
|
||||||
securecompare (1.0.0)
|
securecompare (1.0.0)
|
||||||
seed-fu (2.3.6)
|
seed-fu (2.3.6)
|
||||||
activerecord (>= 3.1)
|
activerecord (>= 3.1)
|
||||||
activesupport (>= 3.1)
|
activesupport (>= 3.1)
|
||||||
select2-rails (3.5.9.3)
|
select2-rails (3.5.9.3)
|
||||||
thor (~> 0.14)
|
thor (~> 0.14)
|
||||||
sentry-raven (2.4.0)
|
sentry-raven (2.5.3)
|
||||||
faraday (>= 0.7.6, < 1.0)
|
faraday (>= 0.7.6, < 1.0)
|
||||||
settingslogic (2.0.9)
|
settingslogic (2.0.9)
|
||||||
sexp_processor (4.8.0)
|
sexp_processor (4.9.0)
|
||||||
sham_rack (1.3.6)
|
sham_rack (1.3.6)
|
||||||
rack
|
rack
|
||||||
shoulda-matchers (2.8.0)
|
shoulda-matchers (3.1.2)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 4.0.0)
|
||||||
sidekiq (5.0.0)
|
sidekiq (5.0.4)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
connection_pool (~> 2.2, >= 2.2.0)
|
connection_pool (~> 2.2, >= 2.2.0)
|
||||||
rack-protection (>= 1.5.0)
|
rack-protection (>= 1.5.0)
|
||||||
redis (~> 3.3, >= 3.3.3)
|
redis (~> 3.3, >= 3.3.3)
|
||||||
sidekiq-cron (0.4.4)
|
sidekiq-cron (0.6.0)
|
||||||
redis-namespace (>= 1.5.2)
|
rufus-scheduler (>= 3.3.0)
|
||||||
rufus-scheduler (>= 2.0.24)
|
|
||||||
sidekiq (>= 4.2.1)
|
sidekiq (>= 4.2.1)
|
||||||
sidekiq-limit_fetch (3.4.0)
|
sidekiq-limit_fetch (3.4.0)
|
||||||
sidekiq (>= 4)
|
sidekiq (>= 4)
|
||||||
|
@ -784,7 +856,7 @@ GEM
|
||||||
state_machines-activerecord (0.4.0)
|
state_machines-activerecord (0.4.0)
|
||||||
activerecord (>= 4.1, < 5.1)
|
activerecord (>= 4.1, < 5.1)
|
||||||
state_machines-activemodel (>= 0.3.0)
|
state_machines-activemodel (>= 0.3.0)
|
||||||
stringex (2.5.2)
|
stringex (2.7.1)
|
||||||
sys-filesystem (1.1.6)
|
sys-filesystem (1.1.6)
|
||||||
ffi
|
ffi
|
||||||
sysexits (1.2.0)
|
sysexits (1.2.0)
|
||||||
|
@ -803,11 +875,10 @@ GEM
|
||||||
timfel-krb5-auth (0.8.3)
|
timfel-krb5-auth (0.8.3)
|
||||||
toml-rb (0.3.15)
|
toml-rb (0.3.15)
|
||||||
citrus (~> 3.0, > 3.0)
|
citrus (~> 3.0, > 3.0)
|
||||||
tool (0.2.3)
|
truncato (0.7.10)
|
||||||
truncato (0.7.8)
|
|
||||||
htmlentities (~> 4.3.1)
|
htmlentities (~> 4.3.1)
|
||||||
nokogiri (~> 1.6.1)
|
nokogiri (~> 1.8.0, >= 1.7.0)
|
||||||
tzinfo (1.2.2)
|
tzinfo (1.2.3)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
u2f (0.2.1)
|
u2f (0.2.1)
|
||||||
uglifier (2.7.2)
|
uglifier (2.7.2)
|
||||||
|
@ -817,7 +888,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.1.3)
|
unicode-display_width (1.3.0)
|
||||||
unicorn (5.1.0)
|
unicorn (5.1.0)
|
||||||
kgio (~> 2.6)
|
kgio (~> 2.6)
|
||||||
raindrops (~> 0.7)
|
raindrops (~> 0.7)
|
||||||
|
@ -838,7 +909,7 @@ GEM
|
||||||
vmstat (2.3.0)
|
vmstat (2.3.0)
|
||||||
warden (1.2.6)
|
warden (1.2.6)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
webmock (1.24.6)
|
webmock (2.3.2)
|
||||||
addressable (>= 2.3.6)
|
addressable (>= 2.3.6)
|
||||||
crack (>= 0.3.2)
|
crack (>= 0.3.2)
|
||||||
hashdiff
|
hashdiff
|
||||||
|
@ -874,27 +945,28 @@ DEPENDENCIES
|
||||||
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)
|
||||||
|
bcrypt_pbkdf (~> 1.0)
|
||||||
benchmark-ips (~> 2.3.0)
|
benchmark-ips (~> 2.3.0)
|
||||||
better_errors (~> 2.1.0)
|
better_errors (~> 2.1.0)
|
||||||
binding_of_caller (~> 0.7.2)
|
binding_of_caller (~> 0.7.2)
|
||||||
bootstrap-sass (~> 3.3.0)
|
bootstrap-sass (~> 3.3.0)
|
||||||
|
bootstrap_form (~> 2.7.0)
|
||||||
brakeman (~> 3.6.0)
|
brakeman (~> 3.6.0)
|
||||||
browser (~> 2.2)
|
browser (~> 2.2)
|
||||||
bullet (~> 5.5.0)
|
bullet (~> 5.5.0)
|
||||||
bundler-audit (~> 0.5.0)
|
bundler-audit (~> 0.5.0)
|
||||||
capybara (~> 2.6.2)
|
capybara (~> 2.6.2)
|
||||||
capybara-screenshot (~> 1.0.0)
|
capybara-screenshot (~> 1.0.0)
|
||||||
carrierwave (~> 1.0)
|
carrierwave (~> 1.1)
|
||||||
charlock_holmes (~> 0.7.3)
|
charlock_holmes (~> 0.7.3)
|
||||||
chronic (~> 0.10.2)
|
chronic (~> 0.10.2)
|
||||||
chronic_duration (~> 0.10.6)
|
chronic_duration (~> 0.10.6)
|
||||||
coffee-rails (~> 4.1.0)
|
|
||||||
concurrent-ruby (~> 1.0.5)
|
concurrent-ruby (~> 1.0.5)
|
||||||
connection_pool (~> 2.0)
|
connection_pool (~> 2.0)
|
||||||
creole (~> 0.5.0)
|
creole (~> 0.5.0)
|
||||||
d3_rails (~> 3.5.0)
|
d3_rails (~> 3.5.0)
|
||||||
database_cleaner (~> 1.5.0)
|
database_cleaner (~> 1.5.0)
|
||||||
deckar01-task_list (= 1.0.6)
|
deckar01-task_list (= 2.0.0)
|
||||||
default_value_for (~> 3.0.0)
|
default_value_for (~> 3.0.0)
|
||||||
devise (~> 4.2)
|
devise (~> 4.2)
|
||||||
devise-two-factor (~> 3.0.0)
|
devise-two-factor (~> 3.0.0)
|
||||||
|
@ -905,10 +977,13 @@ DEPENDENCIES
|
||||||
email_reply_trimmer (~> 0.1)
|
email_reply_trimmer (~> 0.1)
|
||||||
email_spec (~> 1.6.0)
|
email_spec (~> 1.6.0)
|
||||||
factory_girl_rails (~> 4.7.0)
|
factory_girl_rails (~> 4.7.0)
|
||||||
faraday (~> 0.11.0)
|
faraday (~> 0.12)
|
||||||
ffaker (~> 2.4)
|
ffaker (~> 2.4)
|
||||||
flay (~> 2.8.0)
|
flay (~> 2.8.0)
|
||||||
fog-aws (~> 0.9)
|
flipper (~> 0.10.2)
|
||||||
|
flipper-active_record (~> 0.10.2)
|
||||||
|
fog-aliyun (~> 0.1.0)
|
||||||
|
fog-aws (~> 1.4)
|
||||||
fog-core (~> 1.44)
|
fog-core (~> 1.44)
|
||||||
fog-google (~> 0.5)
|
fog-google (~> 0.5)
|
||||||
fog-local (~> 0.3)
|
fog-local (~> 0.3)
|
||||||
|
@ -916,24 +991,26 @@ DEPENDENCIES
|
||||||
fog-rackspace (~> 0.1.1)
|
fog-rackspace (~> 0.1.1)
|
||||||
font-awesome-rails (~> 4.7)
|
font-awesome-rails (~> 4.7)
|
||||||
foreman (~> 0.78.0)
|
foreman (~> 0.78.0)
|
||||||
fuubar (~> 2.0.0)
|
fuubar (~> 2.2.0)
|
||||||
gemnasium-gitlab-service (~> 0.2)
|
gemnasium-gitlab-service (~> 0.2)
|
||||||
gemojione (~> 3.0)
|
gemojione (~> 3.3)
|
||||||
gettext (~> 3.2.2)
|
gettext (~> 3.2.2)
|
||||||
gettext_i18n_rails (~> 1.8.0)
|
gettext_i18n_rails (~> 1.8.0)
|
||||||
gettext_i18n_rails_js (~> 1.2.0)
|
gettext_i18n_rails_js (~> 1.2.0)
|
||||||
gitaly (~> 0.6.0)
|
gitaly (~> 0.26.0)
|
||||||
github-linguist (~> 4.7.0)
|
github-linguist (~> 4.7.0)
|
||||||
gitlab-flowdock-git-hook (~> 1.0.1)
|
gitlab-flowdock-git-hook (~> 1.0.1)
|
||||||
gitlab-markup (~> 1.5.1)
|
gitlab-markup (~> 1.5.1)
|
||||||
gitlab_omniauth-ldap (~> 1.2.1)
|
gitlab_omniauth-ldap (~> 2.0.3)
|
||||||
gollum-lib (~> 4.2)
|
gollum-lib (~> 4.2)
|
||||||
gollum-rugged_adapter (~> 0.4.4)
|
gollum-rugged_adapter (~> 0.4.4)
|
||||||
gon (~> 6.1.0)
|
gon (~> 6.1.0)
|
||||||
google-api-client (~> 0.8.6)
|
google-api-client (~> 0.8.6)
|
||||||
grape (~> 0.19.0)
|
gpgme
|
||||||
|
grape (~> 0.19.2)
|
||||||
grape-entity (~> 0.6.0)
|
grape-entity (~> 0.6.0)
|
||||||
haml_lint (~> 0.21.0)
|
grape-route-helpers (~> 2.0.0)
|
||||||
|
haml_lint (~> 0.26.0)
|
||||||
hamlit (~> 2.6.1)
|
hamlit (~> 2.6.1)
|
||||||
hashie-forbidden_attributes
|
hashie-forbidden_attributes
|
||||||
health_check (~> 2.6.0)
|
health_check (~> 2.6.0)
|
||||||
|
@ -947,28 +1024,30 @@ DEPENDENCIES
|
||||||
jquery-rails (~> 4.1.0)
|
jquery-rails (~> 4.1.0)
|
||||||
json-schema (~> 2.6.2)
|
json-schema (~> 2.6.2)
|
||||||
jwt (~> 1.5.6)
|
jwt (~> 1.5.6)
|
||||||
kaminari (~> 0.17.0)
|
kaminari (~> 1.0)
|
||||||
knapsack (~> 1.11.0)
|
knapsack (~> 1.11.0)
|
||||||
kubeclient (~> 2.2.0)
|
kubeclient (~> 2.2.0)
|
||||||
letter_opener_web (~> 1.3.0)
|
letter_opener_web (~> 1.3.0)
|
||||||
license_finder (~> 2.1.0)
|
license_finder (~> 2.1.0)
|
||||||
licensee (~> 8.7.0)
|
licensee (~> 8.7.0)
|
||||||
|
lograge (~> 0.5)
|
||||||
loofah (~> 2.0.3)
|
loofah (~> 2.0.3)
|
||||||
mail_room (~> 0.9.1)
|
mail_room (~> 0.9.1)
|
||||||
method_source (~> 0.8)
|
method_source (~> 0.8)
|
||||||
minitest (~> 5.7.0)
|
minitest (~> 5.7.0)
|
||||||
mousetrap-rails (~> 1.4.6)
|
mousetrap-rails (~> 1.4.6)
|
||||||
mysql2 (~> 0.3.16)
|
mysql2 (~> 0.4.5)
|
||||||
net-ssh (~> 3.0.1)
|
net-ldap
|
||||||
nokogiri (~> 1.6.7, >= 1.6.7.2)
|
net-ssh (~> 4.1.0)
|
||||||
oauth2 (~> 1.3.0)
|
nokogiri (~> 1.8.0)
|
||||||
|
oauth2 (~> 1.4)
|
||||||
octokit (~> 4.6.2)
|
octokit (~> 4.6.2)
|
||||||
oj (~> 2.17.4)
|
oj (~> 2.17.4)
|
||||||
omniauth (~> 1.4.2)
|
omniauth (~> 1.4.2)
|
||||||
omniauth-auth0 (~> 1.4.1)
|
omniauth-auth0 (~> 1.4.1)
|
||||||
omniauth-authentiq (~> 0.3.0)
|
omniauth-authentiq (~> 0.3.1)
|
||||||
omniauth-azure-oauth2 (~> 0.0.6)
|
omniauth-azure-oauth2 (~> 0.0.6)
|
||||||
omniauth-cas3 (~> 1.1.2)
|
omniauth-cas3 (~> 1.1.4)
|
||||||
omniauth-facebook (~> 4.0.0)
|
omniauth-facebook (~> 4.0.0)
|
||||||
omniauth-github (~> 1.1.1)
|
omniauth-github (~> 1.1.1)
|
||||||
omniauth-gitlab (~> 1.0.2)
|
omniauth-gitlab (~> 1.0.2)
|
||||||
|
@ -980,10 +1059,20 @@ DEPENDENCIES
|
||||||
omniauth-twitter (~> 1.2.0)
|
omniauth-twitter (~> 1.2.0)
|
||||||
omniauth_crowd (~> 2.2.0)
|
omniauth_crowd (~> 2.2.0)
|
||||||
org-ruby (~> 0.9.12)
|
org-ruby (~> 0.9.12)
|
||||||
paranoia (~> 2.2)
|
paranoia (~> 2.3.1)
|
||||||
|
peek (~> 1.0.1)
|
||||||
|
peek-gc (~> 0.0.2)
|
||||||
|
peek-host (~> 1.0.0)
|
||||||
|
peek-mysql2 (~> 1.1.0)
|
||||||
|
peek-performance_bar (~> 1.3.0)
|
||||||
|
peek-pg (~> 1.3.0)
|
||||||
|
peek-rblineprof (~> 0.2.0)
|
||||||
|
peek-redis (~> 1.2.0)
|
||||||
|
peek-sidekiq (~> 1.0.3)
|
||||||
pg (~> 0.18.2)
|
pg (~> 0.18.2)
|
||||||
poltergeist (~> 1.9.0)
|
poltergeist (~> 1.9.0)
|
||||||
premailer-rails (~> 1.9.0)
|
premailer-rails (~> 1.9.7)
|
||||||
|
prometheus-client-mmap (~> 0.7.0.beta14)
|
||||||
pry-byebug (~> 3.4.1)
|
pry-byebug (~> 3.4.1)
|
||||||
pry-rails (~> 0.3.4)
|
pry-rails (~> 0.3.4)
|
||||||
rack-attack (~> 4.4.1)
|
rack-attack (~> 4.4.1)
|
||||||
|
@ -992,10 +1081,14 @@ DEPENDENCIES
|
||||||
rack-proxy (~> 0.6.0)
|
rack-proxy (~> 0.6.0)
|
||||||
rails (= 4.2.8)
|
rails (= 4.2.8)
|
||||||
rails-deprecated_sanitizer (~> 1.0.3)
|
rails-deprecated_sanitizer (~> 1.0.3)
|
||||||
rainbow (~> 2.1.0)
|
rails-i18n (~> 4.0.9)
|
||||||
|
rainbow (~> 2.2)
|
||||||
|
raindrops (~> 0.18)
|
||||||
rblineprof (~> 0.3.6)
|
rblineprof (~> 0.3.6)
|
||||||
|
rbnacl (~> 3.2)
|
||||||
|
rbnacl-libsodium
|
||||||
rdoc (~> 4.2)
|
rdoc (~> 4.2)
|
||||||
re2 (~> 1.0.0)
|
re2 (~> 1.1.1)
|
||||||
recaptcha (~> 3.0)
|
recaptcha (~> 3.0)
|
||||||
redcarpet (~> 3.4)
|
redcarpet (~> 3.4)
|
||||||
redis (~> 3.2)
|
redis (~> 3.2)
|
||||||
|
@ -1005,28 +1098,28 @@ DEPENDENCIES
|
||||||
responders (~> 2.0)
|
responders (~> 2.0)
|
||||||
rouge (~> 2.0)
|
rouge (~> 2.0)
|
||||||
rqrcode-rails3 (~> 0.1.7)
|
rqrcode-rails3 (~> 0.1.7)
|
||||||
rspec-rails (~> 3.5.0)
|
rspec-rails (~> 3.6.0)
|
||||||
rspec-retry (~> 0.4.5)
|
rspec-retry (~> 0.4.5)
|
||||||
rspec-set (~> 0.1.3)
|
rspec-set (~> 0.1.3)
|
||||||
rspec_profiling (~> 0.0.5)
|
rspec_profiling (~> 0.0.5)
|
||||||
rubocop (~> 0.47.1)
|
rubocop (~> 0.49.1)
|
||||||
rubocop-rspec (~> 1.15.0)
|
rubocop-rspec (~> 1.15.1)
|
||||||
ruby-fogbugz (~> 0.2.1)
|
ruby-fogbugz (~> 0.2.1)
|
||||||
ruby-prof (~> 0.16.2)
|
ruby-prof (~> 0.16.2)
|
||||||
ruby_parser (~> 3.8.4)
|
ruby_parser (~> 3.8)
|
||||||
rufus-scheduler (~> 3.1.10)
|
rufus-scheduler (~> 3.4)
|
||||||
rugged (~> 0.25.1.1)
|
rugged (~> 0.26.0)
|
||||||
sanitize (~> 2.0)
|
sanitize (~> 2.0)
|
||||||
sass-rails (~> 5.0.6)
|
sass-rails (~> 5.0.6)
|
||||||
scss_lint (~> 0.47.0)
|
scss_lint (~> 0.54.0)
|
||||||
seed-fu (~> 2.3.5)
|
seed-fu (~> 2.3.5)
|
||||||
select2-rails (~> 3.5.9)
|
select2-rails (~> 3.5.9)
|
||||||
sentry-raven (~> 2.4.0)
|
sentry-raven (~> 2.5.3)
|
||||||
settingslogic (~> 2.0.9)
|
settingslogic (~> 2.0.9)
|
||||||
sham_rack (~> 1.3.6)
|
sham_rack (~> 1.3.6)
|
||||||
shoulda-matchers (~> 2.8.0)
|
shoulda-matchers (~> 3.1.2)
|
||||||
sidekiq (~> 5.0)
|
sidekiq (~> 5.0)
|
||||||
sidekiq-cron (~> 0.4.4)
|
sidekiq-cron (~> 0.6.0)
|
||||||
sidekiq-limit_fetch (~> 3.4)
|
sidekiq-limit_fetch (~> 3.4)
|
||||||
simplecov (~> 0.14.0)
|
simplecov (~> 0.14.0)
|
||||||
slack-notifier (~> 1.5.1)
|
slack-notifier (~> 1.5.1)
|
||||||
|
@ -1043,7 +1136,7 @@ DEPENDENCIES
|
||||||
thin (~> 1.7.0)
|
thin (~> 1.7.0)
|
||||||
timecop (~> 0.8.0)
|
timecop (~> 0.8.0)
|
||||||
toml-rb (~> 0.3.15)
|
toml-rb (~> 0.3.15)
|
||||||
truncato (~> 0.7.8)
|
truncato (~> 0.7.9)
|
||||||
u2f (~> 0.2.1)
|
u2f (~> 0.2.1)
|
||||||
uglifier (~> 2.7.2)
|
uglifier (~> 2.7.2)
|
||||||
underscore-rails (~> 1.8.0)
|
underscore-rails (~> 1.8.0)
|
||||||
|
@ -1054,9 +1147,9 @@ DEPENDENCIES
|
||||||
version_sorter (~> 2.1.0)
|
version_sorter (~> 2.1.0)
|
||||||
virtus (~> 1.0.1)
|
virtus (~> 1.0.1)
|
||||||
vmstat (~> 2.3.0)
|
vmstat (~> 2.3.0)
|
||||||
webmock (~> 1.24.0)
|
webmock (~> 2.3.2)
|
||||||
webpack-rails (~> 0.9.10)
|
webpack-rails (~> 0.9.10)
|
||||||
wikicloth (= 0.8.1)
|
wikicloth (= 0.8.1)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.15.0
|
1.15.3
|
||||||
|
|
20
PROCESS.md
20
PROCESS.md
|
@ -128,7 +128,7 @@ information, see
|
||||||
|
|
||||||
### After the 7th
|
### After the 7th
|
||||||
|
|
||||||
Once the stable branch is frozen, only fixes for regressions (bugs introduced in that same release)
|
Once the stable branch is frozen, only fixes for [regressions](#regressions)
|
||||||
and security issues will be cherry-picked into the stable branch.
|
and security issues will be cherry-picked into the stable branch.
|
||||||
Any merge requests cherry-picked into the stable branch for a previous release will also be picked into the latest stable branch.
|
Any merge requests cherry-picked into the stable branch for a previous release will also be picked into the latest stable branch.
|
||||||
These fixes will be shipped in the next RC for that release if it is before the 22nd.
|
These fixes will be shipped in the next RC for that release if it is before the 22nd.
|
||||||
|
@ -158,6 +158,24 @@ release should have the correct milestone assigned _and_ have the label
|
||||||
Merge requests without a milestone and this label will
|
Merge requests without a milestone and this label will
|
||||||
not be merged into any stable branches.
|
not be merged into any stable branches.
|
||||||
|
|
||||||
|
### Regressions
|
||||||
|
|
||||||
|
A regression for a particular monthly release is a bug that exists in that
|
||||||
|
release, but wasn't present in the release before. This includes bugs in
|
||||||
|
features that were only added in that monthly release. Every regression **must**
|
||||||
|
have the milestone of the release it was introduced in - if a regression doesn't
|
||||||
|
have a milestone, it might be 'just' a bug!
|
||||||
|
|
||||||
|
For instance, if 10.5.0 adds a feature, and that feature doesn't work correctly,
|
||||||
|
then this is a regression in 10.5. If 10.5.1 then fixes that, but 10.5.3 somehow
|
||||||
|
reintroduces the bug, then this bug is still a regression in 10.5.
|
||||||
|
|
||||||
|
Because GitLab.com runs release candidates of new releases, a regression can be
|
||||||
|
reported in a release before its 'official' release date on the 22nd of the
|
||||||
|
month. When we say 'the most recent monthly release', this can refer to either
|
||||||
|
the version currently running on GitLab.com, or the most recent version
|
||||||
|
available in the package repositories.
|
||||||
|
|
||||||
## Release retrospective and kickoff
|
## Release retrospective and kickoff
|
||||||
|
|
||||||
### Retrospective
|
### Retrospective
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
## Test coverage
|
## Test coverage
|
||||||
|
|
||||||
- [![Ruby coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)](https://gitlab-org.gitlab.io/gitlab-ce/coverage-ruby) Ruby
|
- [![Ruby coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=coverage)](https://gitlab-org.gitlab.io/gitlab-ce/coverage-ruby) Ruby
|
||||||
- [![JavaScript coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=rake+karma)](https://gitlab-org.gitlab.io/gitlab-ce/coverage-javascript) JavaScript
|
- [![JavaScript coverage](https://gitlab.com/gitlab-org/gitlab-ce/badges/master/coverage.svg?job=karma)](https://gitlab-org.gitlab.io/gitlab-ce/coverage-javascript) JavaScript
|
||||||
|
|
||||||
## Canonical source
|
## Canonical source
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
9.2.10
|
9.5.4
|
||||||
|
|
4
app/assets/images/i2p-step.svg
Normal file
4
app/assets/images/i2p-step.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 120" enable-background="new 0 0 12 120">
|
||||||
|
<path d="m12 6c0-3.309-2.691-6-6-6s-6 2.691-6 6c0 2.967 2.167 5.431 5 5.91v108.09h2v-108.09c2.833-.479 5-2.943 5-5.91m-6 4c-2.206 0-4-1.794-4-4s1.794-4 4-4 4 1.794 4 4-1.794 4-4 4"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 311 B |
BIN
app/assets/images/new_nav.png
Normal file
BIN
app/assets/images/new_nav.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
app/assets/images/new_repo.png
Normal file
BIN
app/assets/images/new_repo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
app/assets/images/old_nav.png
Normal file
BIN
app/assets/images/old_nav.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
app/assets/images/old_repo.png
Normal file
BIN
app/assets/images/old_repo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -5,7 +5,8 @@ import Cookies from 'js-cookie';
|
||||||
|
|
||||||
class Activities {
|
class Activities {
|
||||||
constructor() {
|
constructor() {
|
||||||
Pager.init(20, true, false, this.updateTooltips);
|
Pager.init(20, true, false, data => data, this.updateTooltips);
|
||||||
|
|
||||||
$('.event-filter-link').on('click', (e) => {
|
$('.event-filter-link').on('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.toggleFilter(e.currentTarget);
|
this.toggleFilter(e.currentTarget);
|
||||||
|
@ -19,7 +20,7 @@ class Activities {
|
||||||
|
|
||||||
reloadActivities() {
|
reloadActivities() {
|
||||||
$('.content_list').html('');
|
$('.content_list').html('');
|
||||||
Pager.init(20, true, false, this.updateTooltips);
|
Pager.init(20, true, false, data => data, this.updateTooltips);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleFilter(sender) {
|
toggleFilter(sender) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ class AjaxLoadingSpinner {
|
||||||
e.target.setAttribute('disabled', '');
|
e.target.setAttribute('disabled', '');
|
||||||
const iconElement = e.target.querySelector('i');
|
const iconElement = e.target.querySelector('i');
|
||||||
// get first fa- icon
|
// get first fa- icon
|
||||||
const originalIcon = iconElement.className.match(/(fa-)([^\s]+)/g).first();
|
const originalIcon = iconElement.className.match(/(fa-)([^\s]+)/g)[0];
|
||||||
iconElement.dataset.icon = originalIcon;
|
iconElement.dataset.icon = originalIcon;
|
||||||
AjaxLoadingSpinner.toggleLoadingIcon(iconElement);
|
AjaxLoadingSpinner.toggleLoadingIcon(iconElement);
|
||||||
$(e.target).off('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
|
$(e.target).off('ajax:beforeSend', AjaxLoadingSpinner.ajaxBeforeSend);
|
||||||
|
|
|
@ -1,148 +1,190 @@
|
||||||
/* eslint-disable func-names, space-before-function-paren, quotes, object-shorthand, camelcase, no-var, comma-dangle, prefer-arrow-callback, quote-props, no-param-reassign, max-len */
|
import $ from 'jquery';
|
||||||
|
|
||||||
var Api = {
|
const Api = {
|
||||||
groupsPath: "/api/:version/groups.json",
|
groupsPath: '/api/:version/groups.json',
|
||||||
groupPath: "/api/:version/groups/:id.json",
|
groupPath: '/api/:version/groups/:id.json',
|
||||||
namespacesPath: "/api/:version/namespaces.json",
|
namespacesPath: '/api/:version/namespaces.json',
|
||||||
groupProjectsPath: "/api/:version/groups/:id/projects.json",
|
groupProjectsPath: '/api/:version/groups/:id/projects.json',
|
||||||
projectsPath: "/api/:version/projects.json?simple=true",
|
projectsPath: '/api/:version/projects.json?simple=true',
|
||||||
labelsPath: "/:namespace_path/:project_path/labels",
|
labelsPath: '/:namespace_path/:project_path/labels',
|
||||||
licensePath: "/api/:version/templates/licenses/:key",
|
licensePath: '/api/:version/templates/licenses/:key',
|
||||||
gitignorePath: "/api/:version/templates/gitignores/:key",
|
gitignorePath: '/api/:version/templates/gitignores/:key',
|
||||||
gitlabCiYmlPath: "/api/:version/templates/gitlab_ci_ymls/:key",
|
gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key',
|
||||||
dockerfilePath: "/api/:version/templates/dockerfiles/:key",
|
dockerfilePath: '/api/:version/templates/dockerfiles/:key',
|
||||||
issuableTemplatePath: "/:namespace_path/:project_path/templates/:type/:key",
|
issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key',
|
||||||
group: function(group_id, callback) {
|
usersPath: '/api/:version/users.json',
|
||||||
var url = Api.buildUrl(Api.groupPath)
|
commitPath: '/api/:version/projects/:id/repository/commits',
|
||||||
.replace(':id', group_id);
|
|
||||||
|
group(groupId, callback) {
|
||||||
|
const url = Api.buildUrl(Api.groupPath)
|
||||||
|
.replace(':id', groupId);
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: url,
|
url,
|
||||||
dataType: "json"
|
dataType: 'json',
|
||||||
}).done(function(group) {
|
})
|
||||||
return callback(group);
|
.done(group => callback(group));
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Return groups list. Filtered by query
|
// Return groups list. Filtered by query
|
||||||
groups: function(query, options, callback) {
|
groups(query, options, callback) {
|
||||||
var url = Api.buildUrl(Api.groupsPath);
|
const url = Api.buildUrl(Api.groupsPath);
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: url,
|
url,
|
||||||
data: $.extend({
|
data: Object.assign({
|
||||||
search: query,
|
|
||||||
per_page: 20
|
|
||||||
}, options),
|
|
||||||
dataType: "json"
|
|
||||||
}).done(function(groups) {
|
|
||||||
return callback(groups);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// Return namespaces list. Filtered by query
|
|
||||||
namespaces: function(query, callback) {
|
|
||||||
var url = Api.buildUrl(Api.namespacesPath);
|
|
||||||
return $.ajax({
|
|
||||||
url: url,
|
|
||||||
data: {
|
|
||||||
search: query,
|
|
||||||
per_page: 20
|
|
||||||
},
|
|
||||||
dataType: "json"
|
|
||||||
}).done(function(namespaces) {
|
|
||||||
return callback(namespaces);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// Return projects list. Filtered by query
|
|
||||||
projects: function(query, options, callback) {
|
|
||||||
var url = Api.buildUrl(Api.projectsPath);
|
|
||||||
return $.ajax({
|
|
||||||
url: url,
|
|
||||||
data: $.extend({
|
|
||||||
search: query,
|
search: query,
|
||||||
per_page: 20,
|
per_page: 20,
|
||||||
membership: true
|
|
||||||
}, options),
|
}, options),
|
||||||
dataType: "json"
|
dataType: 'json',
|
||||||
}).done(function(projects) {
|
})
|
||||||
return callback(projects);
|
.done(groups => callback(groups));
|
||||||
});
|
|
||||||
},
|
},
|
||||||
newLabel: function(namespace_path, project_path, data, callback) {
|
|
||||||
var url = Api.buildUrl(Api.labelsPath)
|
// Return namespaces list. Filtered by query
|
||||||
.replace(':namespace_path', namespace_path)
|
namespaces(query, callback) {
|
||||||
.replace(':project_path', project_path);
|
const url = Api.buildUrl(Api.namespacesPath);
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: url,
|
url,
|
||||||
type: "POST",
|
|
||||||
data: { 'label': data },
|
|
||||||
dataType: "json"
|
|
||||||
}).done(function(label) {
|
|
||||||
return callback(label);
|
|
||||||
}).error(function(message) {
|
|
||||||
return callback(message.responseJSON);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// Return group projects list. Filtered by query
|
|
||||||
groupProjects: function(group_id, query, callback) {
|
|
||||||
var url = Api.buildUrl(Api.groupProjectsPath)
|
|
||||||
.replace(':id', group_id);
|
|
||||||
return $.ajax({
|
|
||||||
url: url,
|
|
||||||
data: {
|
data: {
|
||||||
search: query,
|
search: query,
|
||||||
per_page: 20
|
per_page: 20,
|
||||||
},
|
},
|
||||||
dataType: "json"
|
dataType: 'json',
|
||||||
}).done(function(projects) {
|
}).done(namespaces => callback(namespaces));
|
||||||
return callback(projects);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Return projects list. Filtered by query
|
||||||
|
projects(query, options, callback) {
|
||||||
|
const url = Api.buildUrl(Api.projectsPath);
|
||||||
|
return $.ajax({
|
||||||
|
url,
|
||||||
|
data: Object.assign({
|
||||||
|
search: query,
|
||||||
|
per_page: 20,
|
||||||
|
membership: true,
|
||||||
|
}, options),
|
||||||
|
dataType: 'json',
|
||||||
|
})
|
||||||
|
.done(projects => callback(projects));
|
||||||
|
},
|
||||||
|
|
||||||
|
newLabel(namespacePath, projectPath, data, callback) {
|
||||||
|
const url = Api.buildUrl(Api.labelsPath)
|
||||||
|
.replace(':namespace_path', namespacePath)
|
||||||
|
.replace(':project_path', projectPath);
|
||||||
|
return $.ajax({
|
||||||
|
url,
|
||||||
|
type: 'POST',
|
||||||
|
data: { label: data },
|
||||||
|
dataType: 'json',
|
||||||
|
})
|
||||||
|
.done(label => callback(label))
|
||||||
|
.fail(message => callback(message.responseJSON));
|
||||||
|
},
|
||||||
|
|
||||||
|
// Return group projects list. Filtered by query
|
||||||
|
groupProjects(groupId, query, callback) {
|
||||||
|
const url = Api.buildUrl(Api.groupProjectsPath)
|
||||||
|
.replace(':id', groupId);
|
||||||
|
return $.ajax({
|
||||||
|
url,
|
||||||
|
data: {
|
||||||
|
search: query,
|
||||||
|
per_page: 20,
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
})
|
||||||
|
.done(projects => callback(projects));
|
||||||
|
},
|
||||||
|
|
||||||
|
commitMultiple(id, data, callback) {
|
||||||
|
const url = Api.buildUrl(Api.commitPath)
|
||||||
|
.replace(':id', id);
|
||||||
|
return $.ajax({
|
||||||
|
url,
|
||||||
|
type: 'POST',
|
||||||
|
contentType: 'application/json; charset=utf-8',
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
dataType: 'json',
|
||||||
|
})
|
||||||
|
.done(commitData => callback(commitData))
|
||||||
|
.fail(message => callback(message.responseJSON));
|
||||||
|
},
|
||||||
|
|
||||||
// Return text for a specific license
|
// Return text for a specific license
|
||||||
licenseText: function(key, data, callback) {
|
licenseText(key, data, callback) {
|
||||||
var url = Api.buildUrl(Api.licensePath)
|
const url = Api.buildUrl(Api.licensePath)
|
||||||
.replace(':key', key);
|
.replace(':key', key);
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: url,
|
url,
|
||||||
data: data
|
data,
|
||||||
}).done(function(license) {
|
})
|
||||||
return callback(license);
|
.done(license => callback(license));
|
||||||
});
|
|
||||||
},
|
},
|
||||||
gitignoreText: function(key, callback) {
|
|
||||||
var url = Api.buildUrl(Api.gitignorePath)
|
gitignoreText(key, callback) {
|
||||||
|
const url = Api.buildUrl(Api.gitignorePath)
|
||||||
.replace(':key', key);
|
.replace(':key', key);
|
||||||
return $.get(url, function(gitignore) {
|
return $.get(url, gitignore => callback(gitignore));
|
||||||
return callback(gitignore);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
gitlabCiYml: function(key, callback) {
|
|
||||||
var url = Api.buildUrl(Api.gitlabCiYmlPath)
|
gitlabCiYml(key, callback) {
|
||||||
|
const url = Api.buildUrl(Api.gitlabCiYmlPath)
|
||||||
.replace(':key', key);
|
.replace(':key', key);
|
||||||
return $.get(url, function(file) {
|
return $.get(url, file => callback(file));
|
||||||
return callback(file);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
dockerfileYml: function(key, callback) {
|
|
||||||
var url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
|
dockerfileYml(key, callback) {
|
||||||
|
const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
|
||||||
$.get(url, callback);
|
$.get(url, callback);
|
||||||
},
|
},
|
||||||
issueTemplate: function(namespacePath, projectPath, key, type, callback) {
|
|
||||||
var url = Api.buildUrl(Api.issuableTemplatePath)
|
issueTemplate(namespacePath, projectPath, key, type, callback) {
|
||||||
|
const url = Api.buildUrl(Api.issuableTemplatePath)
|
||||||
.replace(':key', key)
|
.replace(':key', key)
|
||||||
.replace(':type', type)
|
.replace(':type', type)
|
||||||
.replace(':project_path', projectPath)
|
.replace(':project_path', projectPath)
|
||||||
.replace(':namespace_path', namespacePath);
|
.replace(':namespace_path', namespacePath);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: url,
|
url,
|
||||||
dataType: 'json'
|
dataType: 'json',
|
||||||
}).done(function(file) {
|
})
|
||||||
callback(null, file);
|
.done(file => callback(null, file))
|
||||||
}).error(callback);
|
.fail(callback);
|
||||||
},
|
},
|
||||||
buildUrl: function(url) {
|
|
||||||
|
users(query, options) {
|
||||||
|
const url = Api.buildUrl(this.usersPath);
|
||||||
|
return Api.wrapAjaxCall({
|
||||||
|
url,
|
||||||
|
data: Object.assign({
|
||||||
|
search: query,
|
||||||
|
per_page: 20,
|
||||||
|
}, options),
|
||||||
|
dataType: 'json',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
buildUrl(url) {
|
||||||
|
let urlRoot = '';
|
||||||
if (gon.relative_url_root != null) {
|
if (gon.relative_url_root != null) {
|
||||||
url = gon.relative_url_root + url;
|
urlRoot = gon.relative_url_root;
|
||||||
}
|
|
||||||
return url.replace(':version', gon.api_version);
|
|
||||||
}
|
}
|
||||||
|
return urlRoot + url.replace(':version', gon.api_version);
|
||||||
|
},
|
||||||
|
|
||||||
|
wrapAjaxCall(options) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// jQuery 2 is not Promises/A+ compatible (missing catch)
|
||||||
|
$.ajax(options) // eslint-disable-line promise/catch-or-return
|
||||||
|
.then(data => resolve(data),
|
||||||
|
(jqXHR, textStatus, errorThrown) => {
|
||||||
|
const error = new Error(`${options.url}: ${errorThrown}`);
|
||||||
|
error.textStatus = textStatus;
|
||||||
|
reject(error);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
window.Api = Api;
|
export default Api;
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
|
/* eslint-disable class-methods-use-this */
|
||||||
/* global Flash */
|
/* global Flash */
|
||||||
|
import _ from 'underscore';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
|
|
||||||
import emojiMap from 'emojis/digests.json';
|
|
||||||
import emojiAliases from 'emojis/aliases.json';
|
|
||||||
import { glEmojiTag } from './behaviors/gl_emoji';
|
|
||||||
import isEmojiNameValid from './behaviors/gl_emoji/is_emoji_name_valid';
|
|
||||||
|
|
||||||
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
|
const animationEndEventString = 'animationend webkitAnimationEnd MSAnimationEnd oAnimationEnd';
|
||||||
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
|
const transitionEndEventString = 'transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd';
|
||||||
const requestAnimationFrame = window.requestAnimationFrame ||
|
const requestAnimationFrame = window.requestAnimationFrame ||
|
||||||
|
@ -16,8 +12,6 @@ const requestAnimationFrame = window.requestAnimationFrame ||
|
||||||
|
|
||||||
const FROM_SENTENCE_REGEX = /(?:, and | and |, )/; // For separating lists produced by ruby's Array#toSentence
|
const FROM_SENTENCE_REGEX = /(?:, and | and |, )/; // For separating lists produced by ruby's Array#toSentence
|
||||||
|
|
||||||
let categoryMap = null;
|
|
||||||
|
|
||||||
const categoryLabelMap = {
|
const categoryLabelMap = {
|
||||||
activity: 'Activity',
|
activity: 'Activity',
|
||||||
people: 'People',
|
people: 'People',
|
||||||
|
@ -29,48 +23,10 @@ const categoryLabelMap = {
|
||||||
flags: 'Flags',
|
flags: 'Flags',
|
||||||
};
|
};
|
||||||
|
|
||||||
function buildCategoryMap() {
|
class AwardsHandler {
|
||||||
return Object.keys(emojiMap).reduce((currentCategoryMap, emojiNameKey) => {
|
constructor(emoji) {
|
||||||
const emojiInfo = emojiMap[emojiNameKey];
|
this.emoji = emoji;
|
||||||
if (currentCategoryMap[emojiInfo.category]) {
|
|
||||||
currentCategoryMap[emojiInfo.category].push(emojiNameKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentCategoryMap;
|
|
||||||
}, {
|
|
||||||
activity: [],
|
|
||||||
people: [],
|
|
||||||
nature: [],
|
|
||||||
food: [],
|
|
||||||
travel: [],
|
|
||||||
objects: [],
|
|
||||||
symbols: [],
|
|
||||||
flags: [],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderCategory(name, emojiList, opts = {}) {
|
|
||||||
return `
|
|
||||||
<h5 class="emoji-menu-title">
|
|
||||||
${name}
|
|
||||||
</h5>
|
|
||||||
<ul class="clearfix emoji-menu-list ${opts.menuListClass || ''}">
|
|
||||||
${emojiList.map(emojiName => `
|
|
||||||
<li class="emoji-menu-list-item">
|
|
||||||
<button class="emoji-menu-btn text-center js-emoji-btn" type="button">
|
|
||||||
${glEmojiTag(emojiName, {
|
|
||||||
sprite: true,
|
|
||||||
})}
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
`).join('\n')}
|
|
||||||
</ul>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function AwardsHandler() {
|
|
||||||
this.eventListeners = [];
|
this.eventListeners = [];
|
||||||
this.aliases = emojiAliases;
|
|
||||||
// If the user shows intent let's pre-build the menu
|
// If the user shows intent let's pre-build the menu
|
||||||
this.registerEventListener('one', $(document), 'mouseenter focus', '.js-add-award', 'mouseenter focus', () => {
|
this.registerEventListener('one', $(document), 'mouseenter focus', '.js-add-award', 'mouseenter focus', () => {
|
||||||
const $menu = $('.emoji-menu');
|
const $menu = $('.emoji-menu');
|
||||||
|
@ -79,8 +35,6 @@ function AwardsHandler() {
|
||||||
this.createEmojiMenu();
|
this.createEmojiMenu();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Prebuild the categoryMap
|
|
||||||
categoryMap = categoryMap || buildCategoryMap();
|
|
||||||
});
|
});
|
||||||
this.registerEventListener('on', $(document), 'click', '.js-add-award', (e) => {
|
this.registerEventListener('on', $(document), 'click', '.js-add-award', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -105,22 +59,22 @@ function AwardsHandler() {
|
||||||
const $target = $(e.currentTarget);
|
const $target = $(e.currentTarget);
|
||||||
const $glEmojiElement = $target.find('gl-emoji');
|
const $glEmojiElement = $target.find('gl-emoji');
|
||||||
const $spriteIconElement = $target.find('.icon');
|
const $spriteIconElement = $target.find('.icon');
|
||||||
const emoji = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data('name');
|
const emojiName = ($glEmojiElement.length ? $glEmojiElement : $spriteIconElement).data('name');
|
||||||
|
|
||||||
$target.closest('.js-awards-block').addClass('current');
|
$target.closest('.js-awards-block').addClass('current');
|
||||||
this.addAward(this.getVotesBlock(), this.getAwardUrl(), emoji);
|
this.addAward(this.getVotesBlock(), this.getAwardUrl(), emojiName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.registerEventListener = function registerEventListener(method = 'on', element, ...args) {
|
registerEventListener(method = 'on', element, ...args) {
|
||||||
element[method].call(element, ...args);
|
element[method].call(element, ...args);
|
||||||
this.eventListeners.push({
|
this.eventListeners.push({
|
||||||
element,
|
element,
|
||||||
args,
|
args,
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.showEmojiMenu = function showEmojiMenu($addBtn) {
|
showEmojiMenu($addBtn) {
|
||||||
if ($addBtn.hasClass('js-note-emoji')) {
|
if ($addBtn.hasClass('js-note-emoji')) {
|
||||||
$addBtn.closest('.note').find('.js-awards-block').addClass('current');
|
$addBtn.closest('.note').find('.js-awards-block').addClass('current');
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,27 +109,27 @@ AwardsHandler.prototype.showEmojiMenu = function showEmojiMenu($addBtn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$thumbsBtn.toggleClass('disabled', $userAuthored);
|
$thumbsBtn.toggleClass('disabled', $userAuthored);
|
||||||
};
|
}
|
||||||
|
|
||||||
// Create the emoji menu with the first category of emojis.
|
// Create the emoji menu with the first category of emojis.
|
||||||
// Then render the remaining categories of emojis one by one to avoid jank.
|
// Then render the remaining categories of emojis one by one to avoid jank.
|
||||||
AwardsHandler.prototype.createEmojiMenu = function createEmojiMenu(callback) {
|
createEmojiMenu(callback) {
|
||||||
if (this.isCreatingEmojiMenu) {
|
if (this.isCreatingEmojiMenu) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isCreatingEmojiMenu = true;
|
this.isCreatingEmojiMenu = true;
|
||||||
|
|
||||||
// Render the first category
|
// Render the first category
|
||||||
categoryMap = categoryMap || buildCategoryMap();
|
const categoryMap = this.emoji.getEmojiCategoryMap();
|
||||||
const categoryNameKey = Object.keys(categoryMap)[0];
|
const categoryNameKey = Object.keys(categoryMap)[0];
|
||||||
const emojisInCategory = categoryMap[categoryNameKey];
|
const emojisInCategory = categoryMap[categoryNameKey];
|
||||||
const firstCategory = renderCategory(categoryLabelMap[categoryNameKey], emojisInCategory);
|
const firstCategory = this.renderCategory(categoryLabelMap[categoryNameKey], emojisInCategory);
|
||||||
|
|
||||||
// Render the frequently used
|
// Render the frequently used
|
||||||
const frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
|
const frequentlyUsedEmojis = this.getFrequentlyUsedEmojis();
|
||||||
let frequentlyUsedCatgegory = '';
|
let frequentlyUsedCatgegory = '';
|
||||||
if (frequentlyUsedEmojis.length > 0) {
|
if (frequentlyUsedEmojis.length > 0) {
|
||||||
frequentlyUsedCatgegory = renderCategory('Frequently used', frequentlyUsedEmojis, {
|
frequentlyUsedCatgegory = this.renderCategory('Frequently used', frequentlyUsedEmojis, {
|
||||||
menuListClass: 'frequent-emojis',
|
menuListClass: 'frequent-emojis',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -198,17 +152,15 @@ AwardsHandler.prototype.createEmojiMenu = function createEmojiMenu(callback) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler
|
addRemainingEmojiMenuCategories() {
|
||||||
.prototype
|
|
||||||
.addRemainingEmojiMenuCategories = function addRemainingEmojiMenuCategories() {
|
|
||||||
if (this.isAddingRemainingEmojiMenuCategories) {
|
if (this.isAddingRemainingEmojiMenuCategories) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.isAddingRemainingEmojiMenuCategories = true;
|
this.isAddingRemainingEmojiMenuCategories = true;
|
||||||
|
|
||||||
categoryMap = categoryMap || buildCategoryMap();
|
const categoryMap = this.emoji.getEmojiCategoryMap();
|
||||||
|
|
||||||
// Avoid the jank and render the remaining categories separately
|
// Avoid the jank and render the remaining categories separately
|
||||||
// This will take more time, but makes UI more responsive
|
// This will take more time, but makes UI more responsive
|
||||||
|
@ -220,7 +172,7 @@ AwardsHandler
|
||||||
promiseChain.then(() =>
|
promiseChain.then(() =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
const emojisInCategory = categoryMap[categoryNameKey];
|
const emojisInCategory = categoryMap[categoryNameKey];
|
||||||
const categoryMarkup = renderCategory(
|
const categoryMarkup = this.renderCategory(
|
||||||
categoryLabelMap[categoryNameKey],
|
categoryLabelMap[categoryNameKey],
|
||||||
emojisInCategory,
|
emojisInCategory,
|
||||||
);
|
);
|
||||||
|
@ -243,9 +195,28 @@ AwardsHandler
|
||||||
emojiContentElement.insertAdjacentHTML('beforeend', '<p>We encountered an error while adding the remaining categories</p>');
|
emojiContentElement.insertAdjacentHTML('beforeend', '<p>We encountered an error while adding the remaining categories</p>');
|
||||||
throw new Error(`Error occurred in addRemainingEmojiMenuCategories: ${err.message}`);
|
throw new Error(`Error occurred in addRemainingEmojiMenuCategories: ${err.message}`);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.positionMenu = function positionMenu($menu, $addBtn) {
|
renderCategory(name, emojiList, opts = {}) {
|
||||||
|
return `
|
||||||
|
<h5 class="emoji-menu-title">
|
||||||
|
${name}
|
||||||
|
</h5>
|
||||||
|
<ul class="clearfix emoji-menu-list ${opts.menuListClass || ''}">
|
||||||
|
${emojiList.map(emojiName => `
|
||||||
|
<li class="emoji-menu-list-item">
|
||||||
|
<button class="emoji-menu-btn text-center js-emoji-btn" type="button">
|
||||||
|
${this.emoji.glEmojiTag(emojiName, {
|
||||||
|
sprite: true,
|
||||||
|
})}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
`).join('\n')}
|
||||||
|
</ul>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
positionMenu($menu, $addBtn) {
|
||||||
const position = $addBtn.data('position');
|
const position = $addBtn.data('position');
|
||||||
// The menu could potentially be off-screen or in a hidden overflow element
|
// The menu could potentially be off-screen or in a hidden overflow element
|
||||||
// So we position the element absolute in the body
|
// So we position the element absolute in the body
|
||||||
|
@ -260,16 +231,10 @@ AwardsHandler.prototype.positionMenu = function positionMenu($menu, $addBtn) {
|
||||||
$menu.removeClass('is-aligned-right');
|
$menu.removeClass('is-aligned-right');
|
||||||
}
|
}
|
||||||
return $menu.css(css);
|
return $menu.css(css);
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.addAward = function addAward(
|
addAward(votesBlock, awardUrl, emoji, checkMutuality, callback) {
|
||||||
votesBlock,
|
const normalizedEmoji = this.emoji.normalizeEmojiName(emoji);
|
||||||
awardUrl,
|
|
||||||
emoji,
|
|
||||||
checkMutuality,
|
|
||||||
callback,
|
|
||||||
) {
|
|
||||||
const normalizedEmoji = this.normalizeEmojiName(emoji);
|
|
||||||
const $emojiButton = this.findEmojiIcon(votesBlock, normalizedEmoji).parent();
|
const $emojiButton = this.findEmojiIcon(votesBlock, normalizedEmoji).parent();
|
||||||
this.postEmoji($emojiButton, awardUrl, normalizedEmoji, () => {
|
this.postEmoji($emojiButton, awardUrl, normalizedEmoji, () => {
|
||||||
this.addAwardToEmojiBar(votesBlock, normalizedEmoji, checkMutuality);
|
this.addAwardToEmojiBar(votesBlock, normalizedEmoji, checkMutuality);
|
||||||
|
@ -277,18 +242,14 @@ AwardsHandler.prototype.addAward = function addAward(
|
||||||
});
|
});
|
||||||
$('.emoji-menu').removeClass('is-visible');
|
$('.emoji-menu').removeClass('is-visible');
|
||||||
$('.js-add-award.is-active').removeClass('is-active');
|
$('.js-add-award.is-active').removeClass('is-active');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.addAwardToEmojiBar = function addAwardToEmojiBar(
|
addAwardToEmojiBar(votesBlock, emoji, checkForMutuality) {
|
||||||
votesBlock,
|
|
||||||
emoji,
|
|
||||||
checkForMutuality,
|
|
||||||
) {
|
|
||||||
if (checkForMutuality || checkForMutuality === null) {
|
if (checkForMutuality || checkForMutuality === null) {
|
||||||
this.checkMutuality(votesBlock, emoji);
|
this.checkMutuality(votesBlock, emoji);
|
||||||
}
|
}
|
||||||
this.addEmojiToFrequentlyUsedList(emoji);
|
this.addEmojiToFrequentlyUsedList(emoji);
|
||||||
const normalizedEmoji = this.normalizeEmojiName(emoji);
|
const normalizedEmoji = this.emoji.normalizeEmojiName(emoji);
|
||||||
const $emojiButton = this.findEmojiIcon(votesBlock, normalizedEmoji).parent();
|
const $emojiButton = this.findEmojiIcon(votesBlock, normalizedEmoji).parent();
|
||||||
if ($emojiButton.length > 0) {
|
if ($emojiButton.length > 0) {
|
||||||
if (this.isActive($emojiButton)) {
|
if (this.isActive($emojiButton)) {
|
||||||
|
@ -304,9 +265,9 @@ AwardsHandler.prototype.addAwardToEmojiBar = function addAwardToEmojiBar(
|
||||||
votesBlock.removeClass('hidden');
|
votesBlock.removeClass('hidden');
|
||||||
this.createEmoji(votesBlock, normalizedEmoji);
|
this.createEmoji(votesBlock, normalizedEmoji);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.getVotesBlock = function getVotesBlock() {
|
getVotesBlock() {
|
||||||
const currentBlock = $('.js-awards-block.current');
|
const currentBlock = $('.js-awards-block.current');
|
||||||
let resultantVotesBlock = currentBlock;
|
let resultantVotesBlock = currentBlock;
|
||||||
if (currentBlock.length === 0) {
|
if (currentBlock.length === 0) {
|
||||||
|
@ -314,13 +275,13 @@ AwardsHandler.prototype.getVotesBlock = function getVotesBlock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultantVotesBlock;
|
return resultantVotesBlock;
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.getAwardUrl = function getAwardUrl() {
|
getAwardUrl() {
|
||||||
return this.getVotesBlock().data('award-url');
|
return this.getVotesBlock().data('award-url');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.checkMutuality = function checkMutuality(votesBlock, emoji) {
|
checkMutuality(votesBlock, emoji) {
|
||||||
const awardUrl = this.getAwardUrl();
|
const awardUrl = this.getAwardUrl();
|
||||||
if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
|
if (emoji === 'thumbsup' || emoji === 'thumbsdown') {
|
||||||
const mutualVote = emoji === 'thumbsup' ? 'thumbsdown' : 'thumbsup';
|
const mutualVote = emoji === 'thumbsup' ? 'thumbsdown' : 'thumbsup';
|
||||||
|
@ -330,17 +291,17 @@ AwardsHandler.prototype.checkMutuality = function checkMutuality(votesBlock, emo
|
||||||
this.addAward(votesBlock, awardUrl, mutualVote, false);
|
this.addAward(votesBlock, awardUrl, mutualVote, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.isActive = function isActive($emojiButton) {
|
isActive($emojiButton) {
|
||||||
return $emojiButton.hasClass('active');
|
return $emojiButton.hasClass('active');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.isUserAuthored = function isUserAuthored($button) {
|
isUserAuthored($button) {
|
||||||
return $button.hasClass('js-user-authored');
|
return $button.hasClass('js-user-authored');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.decrementCounter = function decrementCounter($emojiButton, emoji) {
|
decrementCounter($emojiButton, emoji) {
|
||||||
const counter = $('.js-counter', $emojiButton);
|
const counter = $('.js-counter', $emojiButton);
|
||||||
const counterNumber = parseInt(counter.text(), 10);
|
const counterNumber = parseInt(counter.text(), 10);
|
||||||
if (counterNumber > 1) {
|
if (counterNumber > 1) {
|
||||||
|
@ -357,22 +318,22 @@ AwardsHandler.prototype.decrementCounter = function decrementCounter($emojiButto
|
||||||
this.removeEmoji($emojiButton);
|
this.removeEmoji($emojiButton);
|
||||||
}
|
}
|
||||||
return $emojiButton.removeClass('active');
|
return $emojiButton.removeClass('active');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.removeEmoji = function removeEmoji($emojiButton) {
|
removeEmoji($emojiButton) {
|
||||||
$emojiButton.tooltip('destroy');
|
$emojiButton.tooltip('destroy');
|
||||||
$emojiButton.remove();
|
$emojiButton.remove();
|
||||||
const $votesBlock = this.getVotesBlock();
|
const $votesBlock = this.getVotesBlock();
|
||||||
if ($votesBlock.find('.js-emoji-btn').length === 0) {
|
if ($votesBlock.find('.js-emoji-btn').length === 0) {
|
||||||
$votesBlock.addClass('hidden');
|
$votesBlock.addClass('hidden');
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.getAwardTooltip = function getAwardTooltip($awardBlock) {
|
getAwardTooltip($awardBlock) {
|
||||||
return $awardBlock.attr('data-original-title') || $awardBlock.attr('data-title') || '';
|
return $awardBlock.attr('data-original-title') || $awardBlock.attr('data-title') || '';
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.toSentence = function toSentence(list) {
|
toSentence(list) {
|
||||||
let sentence;
|
let sentence;
|
||||||
if (list.length <= 2) {
|
if (list.length <= 2) {
|
||||||
sentence = list.join(' and ');
|
sentence = list.join(' and ');
|
||||||
|
@ -381,9 +342,9 @@ AwardsHandler.prototype.toSentence = function toSentence(list) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return sentence;
|
return sentence;
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.removeYouFromUserList = function removeYouFromUserList($emojiButton) {
|
removeYouFromUserList($emojiButton) {
|
||||||
const awardBlock = $emojiButton;
|
const awardBlock = $emojiButton;
|
||||||
const originalTitle = this.getAwardTooltip(awardBlock);
|
const originalTitle = this.getAwardTooltip(awardBlock);
|
||||||
const authors = originalTitle.split(FROM_SENTENCE_REGEX);
|
const authors = originalTitle.split(FROM_SENTENCE_REGEX);
|
||||||
|
@ -395,9 +356,9 @@ AwardsHandler.prototype.removeYouFromUserList = function removeYouFromUserList($
|
||||||
.removeAttr('data-original-title')
|
.removeAttr('data-original-title')
|
||||||
.attr('title', this.toSentence(authors))
|
.attr('title', this.toSentence(authors))
|
||||||
.tooltip('fixTitle');
|
.tooltip('fixTitle');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.addYouToUserList = function addYouToUserList(votesBlock, emoji) {
|
addYouToUserList(votesBlock, emoji) {
|
||||||
const awardBlock = this.findEmojiIcon(votesBlock, emoji).parent();
|
const awardBlock = this.findEmojiIcon(votesBlock, emoji).parent();
|
||||||
const origTitle = this.getAwardTooltip(awardBlock);
|
const origTitle = this.getAwardTooltip(awardBlock);
|
||||||
let users = [];
|
let users = [];
|
||||||
|
@ -408,14 +369,12 @@ AwardsHandler.prototype.addYouToUserList = function addYouToUserList(votesBlock,
|
||||||
return awardBlock
|
return awardBlock
|
||||||
.attr('title', this.toSentence(users))
|
.attr('title', this.toSentence(users))
|
||||||
.tooltip('fixTitle');
|
.tooltip('fixTitle');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler
|
createAwardButtonForVotesBlock(votesBlock, emojiName) {
|
||||||
.prototype
|
|
||||||
.createAwardButtonForVotesBlock = function createAwardButtonForVotesBlock(votesBlock, emojiName) {
|
|
||||||
const buttonHtml = `
|
const buttonHtml = `
|
||||||
<button class="btn award-control js-emoji-btn has-tooltip active" title="You" data-placement="bottom">
|
<button class="btn award-control js-emoji-btn has-tooltip active" title="You" data-placement="bottom">
|
||||||
${glEmojiTag(emojiName)}
|
${this.emoji.glEmojiTag(emojiName)}
|
||||||
<span class="award-control-text js-counter">1</span>
|
<span class="award-control-text js-counter">1</span>
|
||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
|
@ -424,27 +383,27 @@ AwardsHandler
|
||||||
this.animateEmoji($emojiButton);
|
this.animateEmoji($emojiButton);
|
||||||
$('.award-control').tooltip();
|
$('.award-control').tooltip();
|
||||||
votesBlock.removeClass('current');
|
votesBlock.removeClass('current');
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.animateEmoji = function animateEmoji($emoji) {
|
animateEmoji($emoji) {
|
||||||
const className = 'pulse animated once short';
|
const className = 'pulse animated once short';
|
||||||
$emoji.addClass(className);
|
$emoji.addClass(className);
|
||||||
|
|
||||||
this.registerEventListener('on', $emoji, animationEndEventString, (e) => {
|
this.registerEventListener('on', $emoji, animationEndEventString, (e) => {
|
||||||
$(e.currentTarget).removeClass(className);
|
$(e.currentTarget).removeClass(className);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.createEmoji = function createEmoji(votesBlock, emoji) {
|
createEmoji(votesBlock, emoji) {
|
||||||
if ($('.emoji-menu').length) {
|
if ($('.emoji-menu').length) {
|
||||||
this.createAwardButtonForVotesBlock(votesBlock, emoji);
|
this.createAwardButtonForVotesBlock(votesBlock, emoji);
|
||||||
}
|
}
|
||||||
this.createEmojiMenu(() => {
|
this.createEmojiMenu(() => {
|
||||||
this.createAwardButtonForVotesBlock(votesBlock, emoji);
|
this.createAwardButtonForVotesBlock(votesBlock, emoji);
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.postEmoji = function postEmoji($emojiButton, awardUrl, emoji, callback) {
|
postEmoji($emojiButton, awardUrl, emoji, callback) {
|
||||||
if (this.isUserAuthored($emojiButton)) {
|
if (this.isUserAuthored($emojiButton)) {
|
||||||
this.userAuthored($emojiButton);
|
this.userAuthored($emojiButton);
|
||||||
} else {
|
} else {
|
||||||
|
@ -456,13 +415,13 @@ AwardsHandler.prototype.postEmoji = function postEmoji($emojiButton, awardUrl, e
|
||||||
}
|
}
|
||||||
}).fail(() => new Flash('Something went wrong on our end.'));
|
}).fail(() => new Flash('Something went wrong on our end.'));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.findEmojiIcon = function findEmojiIcon(votesBlock, emoji) {
|
findEmojiIcon(votesBlock, emoji) {
|
||||||
return votesBlock.find(`.js-emoji-btn [data-name="${emoji}"]`);
|
return votesBlock.find(`.js-emoji-btn [data-name="${emoji}"]`);
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.userAuthored = function userAuthored($emojiButton) {
|
userAuthored($emojiButton) {
|
||||||
const oldTitle = this.getAwardTooltip($emojiButton);
|
const oldTitle = this.getAwardTooltip($emojiButton);
|
||||||
const newTitle = 'You cannot vote on your own issue, MR and note';
|
const newTitle = 'You cannot vote on your own issue, MR and note';
|
||||||
gl.utils.updateTooltipTitle($emojiButton, newTitle).tooltip('show');
|
gl.utils.updateTooltipTitle($emojiButton, newTitle).tooltip('show');
|
||||||
|
@ -471,40 +430,34 @@ AwardsHandler.prototype.userAuthored = function userAuthored($emojiButton) {
|
||||||
$emojiButton.tooltip('hide');
|
$emojiButton.tooltip('hide');
|
||||||
gl.utils.updateTooltipTitle($emojiButton, oldTitle);
|
gl.utils.updateTooltipTitle($emojiButton, oldTitle);
|
||||||
}, 2800);
|
}, 2800);
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.scrollToAwards = function scrollToAwards() {
|
scrollToAwards() {
|
||||||
const options = {
|
const options = {
|
||||||
scrollTop: $('.awards').offset().top - 110,
|
scrollTop: $('.awards').offset().top - 110,
|
||||||
};
|
};
|
||||||
return $('body, html').animate(options, 200);
|
return $('body, html').animate(options, 200);
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.normalizeEmojiName = function normalizeEmojiName(emoji) {
|
addEmojiToFrequentlyUsedList(emoji) {
|
||||||
return Object.prototype.hasOwnProperty.call(this.aliases, emoji) ? this.aliases[emoji] : emoji;
|
if (this.emoji.isEmojiNameValid(emoji)) {
|
||||||
};
|
|
||||||
|
|
||||||
AwardsHandler
|
|
||||||
.prototype
|
|
||||||
.addEmojiToFrequentlyUsedList = function addEmojiToFrequentlyUsedList(emoji) {
|
|
||||||
if (isEmojiNameValid(emoji)) {
|
|
||||||
this.frequentlyUsedEmojis = _.uniq(this.getFrequentlyUsedEmojis().concat(emoji));
|
this.frequentlyUsedEmojis = _.uniq(this.getFrequentlyUsedEmojis().concat(emoji));
|
||||||
Cookies.set('frequently_used_emojis', this.frequentlyUsedEmojis.join(','), { expires: 365 });
|
Cookies.set('frequently_used_emojis', this.frequentlyUsedEmojis.join(','), { expires: 365 });
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.getFrequentlyUsedEmojis = function getFrequentlyUsedEmojis() {
|
getFrequentlyUsedEmojis() {
|
||||||
return this.frequentlyUsedEmojis || (() => {
|
return this.frequentlyUsedEmojis || (() => {
|
||||||
const frequentlyUsedEmojis = _.uniq((Cookies.get('frequently_used_emojis') || '').split(','));
|
const frequentlyUsedEmojis = _.uniq((Cookies.get('frequently_used_emojis') || '').split(','));
|
||||||
this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter(
|
this.frequentlyUsedEmojis = frequentlyUsedEmojis.filter(
|
||||||
inputName => isEmojiNameValid(inputName),
|
inputName => this.emoji.isEmojiNameValid(inputName),
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.frequentlyUsedEmojis;
|
return this.frequentlyUsedEmojis;
|
||||||
})();
|
})();
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.setupSearch = function setupSearch() {
|
setupSearch() {
|
||||||
const $search = $('.js-emoji-menu-search');
|
const $search = $('.js-emoji-menu-search');
|
||||||
|
|
||||||
this.registerEventListener('on', $search, 'input', (e) => {
|
this.registerEventListener('on', $search, 'input', (e) => {
|
||||||
|
@ -519,9 +472,9 @@ AwardsHandler.prototype.setupSearch = function setupSearch() {
|
||||||
this.searchEmojis('');
|
this.searchEmojis('');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
AwardsHandler.prototype.searchEmojis = function searchEmojis(term) {
|
searchEmojis(term) {
|
||||||
const $search = $('.js-emoji-menu-search');
|
const $search = $('.js-emoji-menu-search');
|
||||||
$search.val(term);
|
$search.val(term);
|
||||||
|
|
||||||
|
@ -537,31 +490,29 @@ AwardsHandler.prototype.searchEmojis = function searchEmojis(term) {
|
||||||
} else {
|
} else {
|
||||||
$('.emoji-menu-content').children().show();
|
$('.emoji-menu-content').children().show();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
AwardsHandler.prototype.findMatchingEmojiElements = function findMatchingEmojiElements(term) {
|
|
||||||
const safeTerm = term.toLowerCase();
|
|
||||||
|
|
||||||
const namesMatchingAlias = [];
|
|
||||||
Object.keys(emojiAliases).forEach((alias) => {
|
|
||||||
if (alias.indexOf(safeTerm) >= 0) {
|
|
||||||
namesMatchingAlias.push(emojiAliases[alias]);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
const $matchingElements = namesMatchingAlias.concat(safeTerm)
|
|
||||||
.reduce(
|
|
||||||
($result, searchTerm) =>
|
|
||||||
$result.add($(`.emoji-menu-list:not(.frequent-emojis) [data-name*="${searchTerm}"]`)),
|
|
||||||
$([]),
|
|
||||||
);
|
|
||||||
return $matchingElements.closest('li').clone();
|
|
||||||
};
|
|
||||||
|
|
||||||
AwardsHandler.prototype.destroy = function destroy() {
|
findMatchingEmojiElements(query) {
|
||||||
|
const emojiMatches = this.emoji.filterEmojiNamesByAlias(query);
|
||||||
|
const $emojiElements = $('.emoji-menu-list:not(.frequent-emojis) [data-name]');
|
||||||
|
const $matchingElements = $emojiElements
|
||||||
|
.filter((i, elm) => emojiMatches.indexOf(elm.dataset.name) >= 0);
|
||||||
|
return $matchingElements.closest('li').clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
this.eventListeners.forEach((entry) => {
|
this.eventListeners.forEach((entry) => {
|
||||||
entry.element.off.call(entry.element, ...entry.args);
|
entry.element.off.call(entry.element, ...entry.args);
|
||||||
});
|
});
|
||||||
$('.emoji-menu').remove();
|
$('.emoji-menu').remove();
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default AwardsHandler;
|
let awardsHandlerPromise = null;
|
||||||
|
export default function loadAwardsHandler(reload = false) {
|
||||||
|
if (!awardsHandlerPromise || reload) {
|
||||||
|
awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji')
|
||||||
|
.then(Emoji => new AwardsHandler(Emoji));
|
||||||
|
}
|
||||||
|
return awardsHandlerPromise;
|
||||||
|
}
|
||||||
|
|
|
@ -1,23 +1,8 @@
|
||||||
import autosize from 'vendor/autosize';
|
import autosize from 'vendor/autosize';
|
||||||
|
|
||||||
$(() => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const $fields = $('.js-autosize');
|
const autosizeEls = document.querySelectorAll('.js-autosize');
|
||||||
|
|
||||||
$fields.on('autosize:resized', function resized() {
|
autosize(autosizeEls);
|
||||||
const $field = $(this);
|
autosize.update(autosizeEls);
|
||||||
$field.data('height', $field.outerHeight());
|
|
||||||
});
|
|
||||||
|
|
||||||
$fields.on('resize.autosize', function resize() {
|
|
||||||
const $field = $(this);
|
|
||||||
if ($field.data('height') !== $field.outerHeight()) {
|
|
||||||
$field.data('height', $field.outerHeight());
|
|
||||||
autosize.destroy($field);
|
|
||||||
$field.css('max-height', window.outerHeight);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
autosize($fields);
|
|
||||||
autosize.update($fields);
|
|
||||||
$fields.css('resize', 'vertical');
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,75 +1,9 @@
|
||||||
import installCustomElements from 'document-register-element';
|
import installCustomElements from 'document-register-element';
|
||||||
import emojiMap from 'emojis/digests.json';
|
import isEmojiUnicodeSupported from '../emoji/support';
|
||||||
import emojiAliases from 'emojis/aliases.json';
|
|
||||||
import { getUnicodeSupportMap } from './gl_emoji/unicode_support_map';
|
|
||||||
import { isEmojiUnicodeSupported } from './gl_emoji/is_emoji_unicode_supported';
|
|
||||||
|
|
||||||
installCustomElements(window);
|
installCustomElements(window);
|
||||||
|
|
||||||
const generatedUnicodeSupportMap = getUnicodeSupportMap();
|
export default function installGlEmojiElement() {
|
||||||
|
|
||||||
function emojiImageTag(name, src) {
|
|
||||||
return `<img class="emoji" title=":${name}:" alt=":${name}:" src="${src}" width="20" height="20" align="absmiddle" />`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function assembleFallbackImageSrc(inputName) {
|
|
||||||
let name = Object.prototype.hasOwnProperty.call(emojiAliases, inputName) ?
|
|
||||||
emojiAliases[inputName] : inputName;
|
|
||||||
let emojiInfo = emojiMap[name];
|
|
||||||
// Fallback to question mark for unknown emojis
|
|
||||||
if (!emojiInfo) {
|
|
||||||
name = 'grey_question';
|
|
||||||
emojiInfo = emojiMap[name];
|
|
||||||
}
|
|
||||||
const fallbackImageSrc = `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/emoji/${name}-${emojiInfo.digest}.png`;
|
|
||||||
|
|
||||||
return fallbackImageSrc;
|
|
||||||
}
|
|
||||||
const glEmojiTagDefaults = {
|
|
||||||
sprite: false,
|
|
||||||
forceFallback: false,
|
|
||||||
};
|
|
||||||
function glEmojiTag(inputName, options) {
|
|
||||||
const opts = Object.assign({}, glEmojiTagDefaults, options);
|
|
||||||
let name = Object.prototype.hasOwnProperty.call(emojiAliases, inputName) ?
|
|
||||||
emojiAliases[inputName] : inputName;
|
|
||||||
let emojiInfo = emojiMap[name];
|
|
||||||
// Fallback to question mark for unknown emojis
|
|
||||||
if (!emojiInfo) {
|
|
||||||
name = 'grey_question';
|
|
||||||
emojiInfo = emojiMap[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
const fallbackImageSrc = assembleFallbackImageSrc(name);
|
|
||||||
const fallbackSpriteClass = `emoji-${name}`;
|
|
||||||
|
|
||||||
const classList = [];
|
|
||||||
if (opts.forceFallback && opts.sprite) {
|
|
||||||
classList.push('emoji-icon');
|
|
||||||
classList.push(fallbackSpriteClass);
|
|
||||||
}
|
|
||||||
const classAttribute = classList.length > 0 ? `class="${classList.join(' ')}"` : '';
|
|
||||||
const fallbackSpriteAttribute = opts.sprite ? `data-fallback-sprite-class="${fallbackSpriteClass}"` : '';
|
|
||||||
let contents = emojiInfo.moji;
|
|
||||||
if (opts.forceFallback && !opts.sprite) {
|
|
||||||
contents = emojiImageTag(name, fallbackImageSrc);
|
|
||||||
}
|
|
||||||
|
|
||||||
return `
|
|
||||||
<gl-emoji
|
|
||||||
${classAttribute}
|
|
||||||
data-name="${name}"
|
|
||||||
data-fallback-src="${fallbackImageSrc}"
|
|
||||||
${fallbackSpriteAttribute}
|
|
||||||
data-unicode-version="${emojiInfo.unicodeVersion}"
|
|
||||||
title="${emojiInfo.description}"
|
|
||||||
>
|
|
||||||
${contents}
|
|
||||||
</gl-emoji>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function installGlEmojiElement() {
|
|
||||||
const GlEmojiElementProto = Object.create(HTMLElement.prototype);
|
const GlEmojiElementProto = Object.create(HTMLElement.prototype);
|
||||||
GlEmojiElementProto.createdCallback = function createdCallback() {
|
GlEmojiElementProto.createdCallback = function createdCallback() {
|
||||||
const emojiUnicode = this.textContent.trim();
|
const emojiUnicode = this.textContent.trim();
|
||||||
|
@ -88,20 +22,29 @@ function installGlEmojiElement() {
|
||||||
const hasCssSpriteFalback = fallbackSpriteClass && fallbackSpriteClass.length > 0;
|
const hasCssSpriteFalback = fallbackSpriteClass && fallbackSpriteClass.length > 0;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
emojiUnicode &&
|
||||||
isEmojiUnicode &&
|
isEmojiUnicode &&
|
||||||
!isEmojiUnicodeSupported(generatedUnicodeSupportMap, emojiUnicode, unicodeVersion)
|
!isEmojiUnicodeSupported(emojiUnicode, unicodeVersion)
|
||||||
) {
|
) {
|
||||||
// CSS sprite fallback takes precedence over image fallback
|
// CSS sprite fallback takes precedence over image fallback
|
||||||
if (hasCssSpriteFalback) {
|
if (hasCssSpriteFalback) {
|
||||||
// IE 11 doesn't like adding multiple at once :(
|
// IE 11 doesn't like adding multiple at once :(
|
||||||
this.classList.add('emoji-icon');
|
this.classList.add('emoji-icon');
|
||||||
this.classList.add(fallbackSpriteClass);
|
this.classList.add(fallbackSpriteClass);
|
||||||
} else if (hasImageFallback) {
|
} else {
|
||||||
|
import(/* webpackChunkName: 'emoji' */ '../emoji')
|
||||||
|
.then(({ emojiImageTag, emojiFallbackImageSrc }) => {
|
||||||
|
if (hasImageFallback) {
|
||||||
this.innerHTML = emojiImageTag(name, fallbackSrc);
|
this.innerHTML = emojiImageTag(name, fallbackSrc);
|
||||||
} else {
|
} else {
|
||||||
const src = assembleFallbackImageSrc(name);
|
const src = emojiFallbackImageSrc(name);
|
||||||
this.innerHTML = emojiImageTag(name, src);
|
this.innerHTML = emojiImageTag(name, src);
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// do nothing
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,9 +52,3 @@ function installGlEmojiElement() {
|
||||||
prototype: GlEmojiElementProto,
|
prototype: GlEmojiElementProto,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
|
||||||
installGlEmojiElement,
|
|
||||||
glEmojiTag,
|
|
||||||
emojiImageTag,
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
import emojiMap from 'emojis/digests.json';
|
|
||||||
import emojiAliases from 'emojis/aliases.json';
|
|
||||||
|
|
||||||
function isEmojiNameValid(inputName) {
|
|
||||||
const name = Object.prototype.hasOwnProperty.call(emojiAliases, inputName) ?
|
|
||||||
emojiAliases[inputName] : inputName;
|
|
||||||
|
|
||||||
return name && emojiMap[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
export default isEmojiNameValid;
|
|
|
@ -1,7 +1,7 @@
|
||||||
import './autosize';
|
import './autosize';
|
||||||
import './bind_in_out';
|
import './bind_in_out';
|
||||||
import './details_behavior';
|
import './details_behavior';
|
||||||
import { installGlEmojiElement } from './gl_emoji';
|
import installGlEmojiElement from './gl_emoji';
|
||||||
import './quick_submit';
|
import './quick_submit';
|
||||||
import './requires_input';
|
import './requires_input';
|
||||||
import './toggler_behavior';
|
import './toggler_behavior';
|
||||||
|
|
|
@ -40,7 +40,7 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const $form = $(e.target).closest('form');
|
const $form = $(e.target).closest('form');
|
||||||
const $submitButton = $form.find('input[type=submit], button[type=submit]');
|
const $submitButton = $form.find('input[type=submit], button[type=submit]').first();
|
||||||
|
|
||||||
if (!$submitButton.attr('disabled')) {
|
if (!$submitButton.attr('disabled')) {
|
||||||
$submitButton.trigger('click', [e]);
|
$submitButton.trigger('click', [e]);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import _ from 'underscore';
|
||||||
import '../commons/bootstrap';
|
import '../commons/bootstrap';
|
||||||
|
|
||||||
// Requires Input behavior
|
// Requires Input behavior
|
||||||
|
@ -48,7 +49,9 @@ function hideOrShowHelpBlock(form) {
|
||||||
|
|
||||||
$(() => {
|
$(() => {
|
||||||
const $form = $('form.js-requires-input');
|
const $form = $('form.js-requires-input');
|
||||||
|
if ($form) {
|
||||||
$form.requiresInput();
|
$form.requiresInput();
|
||||||
hideOrShowHelpBlock($form);
|
hideOrShowHelpBlock($form);
|
||||||
$('.select2.js-select-namespace').change(() => hideOrShowHelpBlock($form));
|
$('.select2.js-select-namespace').change(() => hideOrShowHelpBlock($form));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
// Toggle button. Show/hide content inside parent container.
|
// Toggle button. Show/hide content inside parent container.
|
||||||
// Button does not change visibility. If button has icon - it changes chevron style.
|
// Button does not change visibility. If button has icon - it changes chevron style.
|
||||||
//
|
//
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
/* global Flash */
|
|
||||||
|
|
||||||
import sqljs from 'sql.js';
|
import sqljs from 'sql.js';
|
||||||
import { template as _template } from 'underscore';
|
import { template as _template } from 'underscore';
|
||||||
|
|
||||||
|
@ -15,19 +13,27 @@ const PREVIEW_TEMPLATE = _template(`
|
||||||
class BalsamiqViewer {
|
class BalsamiqViewer {
|
||||||
constructor(viewer) {
|
constructor(viewer) {
|
||||||
this.viewer = viewer;
|
this.viewer = viewer;
|
||||||
this.endpoint = this.viewer.dataset.endpoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFile() {
|
loadFile(endpoint) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
xhr.open('GET', this.endpoint, true);
|
xhr.open('GET', endpoint, true);
|
||||||
xhr.responseType = 'arraybuffer';
|
xhr.responseType = 'arraybuffer';
|
||||||
|
xhr.onload = loadEvent => this.fileLoaded(loadEvent, resolve, reject);
|
||||||
xhr.onload = this.renderFile.bind(this);
|
xhr.onerror = reject;
|
||||||
xhr.onerror = BalsamiqViewer.onError;
|
|
||||||
|
|
||||||
xhr.send();
|
xhr.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fileLoaded(loadEvent, resolve, reject) {
|
||||||
|
if (loadEvent.target.status !== 200) return reject();
|
||||||
|
|
||||||
|
this.renderFile(loadEvent);
|
||||||
|
|
||||||
|
return resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFile(loadEvent) {
|
renderFile(loadEvent) {
|
||||||
|
@ -103,12 +109,6 @@ class BalsamiqViewer {
|
||||||
static parseTitle(resource) {
|
static parseTitle(resource) {
|
||||||
return JSON.parse(resource.values[0][2]).name;
|
return JSON.parse(resource.values[0][2]).name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static onError() {
|
|
||||||
const flash = new Flash('Balsamiq file could not be loaded.');
|
|
||||||
|
|
||||||
return flash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default BalsamiqViewer;
|
export default BalsamiqViewer;
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
|
/* global Flash */
|
||||||
|
|
||||||
import BalsamiqViewer from './balsamiq/balsamiq_viewer';
|
import BalsamiqViewer from './balsamiq/balsamiq_viewer';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
function onError() {
|
||||||
const balsamiqViewer = new BalsamiqViewer(document.getElementById('js-balsamiq-viewer'));
|
const flash = new window.Flash('Balsamiq file could not be loaded.');
|
||||||
balsamiqViewer.loadFile();
|
|
||||||
});
|
return flash;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadBalsamiqFile() {
|
||||||
|
const viewer = document.getElementById('js-balsamiq-viewer');
|
||||||
|
|
||||||
|
if (!(viewer instanceof Element)) return;
|
||||||
|
|
||||||
|
const endpoint = viewer.dataset.endpoint;
|
||||||
|
|
||||||
|
const balsamiqViewer = new BalsamiqViewer(viewer);
|
||||||
|
balsamiqViewer.loadFile(endpoint).catch(onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(loadBalsamiqFile);
|
||||||
|
|
|
@ -1,9 +1,24 @@
|
||||||
/* eslint-disable func-names, object-shorthand, prefer-arrow-callback */
|
/* eslint-disable func-names, object-shorthand, prefer-arrow-callback */
|
||||||
/* global Dropzone */
|
/* global Dropzone */
|
||||||
|
|
||||||
|
import '../lib/utils/url_utility';
|
||||||
|
import { HIDDEN_CLASS } from '../lib/utils/constants';
|
||||||
|
|
||||||
|
function toggleLoading($el, $icon, loading) {
|
||||||
|
if (loading) {
|
||||||
|
$el.disable();
|
||||||
|
$icon.removeClass(HIDDEN_CLASS);
|
||||||
|
} else {
|
||||||
|
$el.enable();
|
||||||
|
$icon.addClass(HIDDEN_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
export default class BlobFileDropzone {
|
export default class BlobFileDropzone {
|
||||||
constructor(form, method) {
|
constructor(form, method) {
|
||||||
const formDropzone = form.find('.dropzone');
|
const formDropzone = form.find('.dropzone');
|
||||||
|
const submitButton = form.find('#submit-all');
|
||||||
|
const submitButtonLoadingIcon = submitButton.find('.js-loading-icon');
|
||||||
|
const dropzoneMessage = form.find('.dz-message');
|
||||||
Dropzone.autoDiscover = false;
|
Dropzone.autoDiscover = false;
|
||||||
|
|
||||||
const dropzone = formDropzone.dropzone({
|
const dropzone = formDropzone.dropzone({
|
||||||
|
@ -26,16 +41,24 @@ export default class BlobFileDropzone {
|
||||||
},
|
},
|
||||||
init: function () {
|
init: function () {
|
||||||
this.on('addedfile', function () {
|
this.on('addedfile', function () {
|
||||||
|
toggleLoading(submitButton, submitButtonLoadingIcon, false);
|
||||||
|
dropzoneMessage.addClass(HIDDEN_CLASS);
|
||||||
$('.dropzone-alerts').html('').hide();
|
$('.dropzone-alerts').html('').hide();
|
||||||
});
|
});
|
||||||
|
this.on('removedfile', function () {
|
||||||
|
toggleLoading(submitButton, submitButtonLoadingIcon, false);
|
||||||
|
dropzoneMessage.removeClass(HIDDEN_CLASS);
|
||||||
|
});
|
||||||
this.on('success', function (header, response) {
|
this.on('success', function (header, response) {
|
||||||
window.location.href = response.filePath;
|
$('#modal-upload-blob').modal('hide');
|
||||||
|
window.gl.utils.visitUrl(response.filePath);
|
||||||
});
|
});
|
||||||
this.on('maxfilesexceeded', function (file) {
|
this.on('maxfilesexceeded', function (file) {
|
||||||
|
dropzoneMessage.addClass(HIDDEN_CLASS);
|
||||||
this.removeFile(file);
|
this.removeFile(file);
|
||||||
});
|
});
|
||||||
this.on('sending', function (file, xhr, formData) {
|
this.on('sending', function (file, xhr, formData) {
|
||||||
formData.append('branch_name', form.find('input[name="branch_name"]').val());
|
formData.append('branch_name', form.find('.js-branch-name').val());
|
||||||
formData.append('create_merge_request', form.find('.js-create-merge-request').val());
|
formData.append('create_merge_request', form.find('.js-create-merge-request').val());
|
||||||
formData.append('commit_message', form.find('.js-commit-message').val());
|
formData.append('commit_message', form.find('.js-commit-message').val());
|
||||||
});
|
});
|
||||||
|
@ -48,14 +71,15 @@ export default class BlobFileDropzone {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const submitButton = form.find('#submit-all')[0];
|
submitButton.on('click', (e) => {
|
||||||
submitButton.addEventListener('click', function (e) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (dropzone[0].dropzone.getQueuedFiles().length === 0) {
|
if (dropzone[0].dropzone.getQueuedFiles().length === 0) {
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
alert('Please select a file');
|
alert('Please select a file');
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
toggleLoading(submitButton, submitButtonLoadingIcon, true);
|
||||||
dropzone[0].dropzone.processQueue();
|
dropzone[0].dropzone.processQueue();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
class CreateBranchDropdown {
|
|
||||||
constructor(el, targetBranchDropdown) {
|
|
||||||
this.targetBranchDropdown = targetBranchDropdown;
|
|
||||||
this.el = el;
|
|
||||||
this.dropdownBack = this.el.closest('.dropdown').querySelector('.dropdown-menu-back');
|
|
||||||
this.cancelButton = this.el.querySelector('.js-cancel-branch-btn');
|
|
||||||
this.newBranchField = this.el.querySelector('#new_branch_name');
|
|
||||||
this.newBranchCreateButton = this.el.querySelector('.js-new-branch-btn');
|
|
||||||
|
|
||||||
this.newBranchCreateButton.setAttribute('disabled', '');
|
|
||||||
|
|
||||||
this.addBindings();
|
|
||||||
this.cleanupWrapper = this.cleanup.bind(this);
|
|
||||||
document.addEventListener('beforeunload', this.cleanupWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup() {
|
|
||||||
this.cleanBindings();
|
|
||||||
document.removeEventListener('beforeunload', this.cleanupWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanBindings() {
|
|
||||||
this.newBranchField.removeEventListener('keyup', this.enableBranchCreateButtonWrapper);
|
|
||||||
this.newBranchField.removeEventListener('change', this.enableBranchCreateButtonWrapper);
|
|
||||||
this.newBranchField.removeEventListener('keydown', this.handleNewBranchKeydownWrapper);
|
|
||||||
this.dropdownBack.removeEventListener('click', this.resetFormWrapper);
|
|
||||||
this.cancelButton.removeEventListener('click', this.handleCancelClickWrapper);
|
|
||||||
this.newBranchCreateButton.removeEventListener('click', this.createBranchWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
addBindings() {
|
|
||||||
this.enableBranchCreateButtonWrapper = this.enableBranchCreateButton.bind(this);
|
|
||||||
this.handleNewBranchKeydownWrapper = this.handleNewBranchKeydown.bind(this);
|
|
||||||
this.resetFormWrapper = this.resetForm.bind(this);
|
|
||||||
this.handleCancelClickWrapper = this.handleCancelClick.bind(this);
|
|
||||||
this.createBranchWrapper = this.createBranch.bind(this);
|
|
||||||
|
|
||||||
this.newBranchField.addEventListener('keyup', this.enableBranchCreateButtonWrapper);
|
|
||||||
this.newBranchField.addEventListener('change', this.enableBranchCreateButtonWrapper);
|
|
||||||
this.newBranchField.addEventListener('keydown', this.handleNewBranchKeydownWrapper);
|
|
||||||
this.dropdownBack.addEventListener('click', this.resetFormWrapper);
|
|
||||||
this.cancelButton.addEventListener('click', this.handleCancelClickWrapper);
|
|
||||||
this.newBranchCreateButton.addEventListener('click', this.createBranchWrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCancelClick(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
this.resetForm();
|
|
||||||
this.dropdownBack.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
handleNewBranchKeydown(e) {
|
|
||||||
const keyCode = e.which;
|
|
||||||
const ENTER_KEYCODE = 13;
|
|
||||||
if (keyCode === ENTER_KEYCODE) {
|
|
||||||
this.createBranch(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enableBranchCreateButton() {
|
|
||||||
if (this.newBranchField.value !== '') {
|
|
||||||
this.newBranchCreateButton.removeAttribute('disabled');
|
|
||||||
} else {
|
|
||||||
this.newBranchCreateButton.setAttribute('disabled', '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resetForm() {
|
|
||||||
this.newBranchField.value = '';
|
|
||||||
this.enableBranchCreateButtonWrapper();
|
|
||||||
}
|
|
||||||
|
|
||||||
createBranch(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (this.newBranchCreateButton.getAttribute('disabled') === '') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const newBranchName = this.newBranchField.value;
|
|
||||||
this.targetBranchDropdown.setNewBranch(newBranchName);
|
|
||||||
this.resetForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.gl = window.gl || {};
|
|
||||||
gl.CreateBranchDropdown = CreateBranchDropdown;
|
|
|
@ -1,5 +1,3 @@
|
||||||
/* global Api */
|
|
||||||
|
|
||||||
export default class FileTemplateSelector {
|
export default class FileTemplateSelector {
|
||||||
constructor(mediator) {
|
constructor(mediator) {
|
||||||
this.mediator = mediator;
|
this.mediator = mediator;
|
||||||
|
@ -65,4 +63,3 @@ export default class FileTemplateSelector {
|
||||||
this.reportSelection(opts);
|
this.reportSelection(opts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,9 @@ export default () => {
|
||||||
methods: {
|
methods: {
|
||||||
loadFile() {
|
loadFile() {
|
||||||
this.$http.get(el.dataset.endpoint)
|
this.$http.get(el.dataset.endpoint)
|
||||||
|
.then(response => response.json())
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.json = res.json();
|
this.json = res;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
/* eslint-disable class-methods-use-this */
|
|
||||||
const SELECT_ITEM_MSG = 'Select';
|
|
||||||
|
|
||||||
class TargetBranchDropDown {
|
|
||||||
constructor(dropdown) {
|
|
||||||
this.dropdown = dropdown;
|
|
||||||
this.$dropdown = $(dropdown);
|
|
||||||
this.fieldName = this.dropdown.getAttribute('data-field-name');
|
|
||||||
this.form = this.dropdown.closest('form');
|
|
||||||
this.createDropdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bootstrap() {
|
|
||||||
const dropdowns = document.querySelectorAll('.js-project-branches-dropdown');
|
|
||||||
[].forEach.call(dropdowns, dropdown => new TargetBranchDropDown(dropdown));
|
|
||||||
}
|
|
||||||
|
|
||||||
createDropdown() {
|
|
||||||
const self = this;
|
|
||||||
this.$dropdown.glDropdown({
|
|
||||||
selectable: true,
|
|
||||||
filterable: true,
|
|
||||||
search: {
|
|
||||||
fields: ['title'],
|
|
||||||
},
|
|
||||||
data: (term, callback) => $.ajax({
|
|
||||||
url: self.dropdown.getAttribute('data-refs-url'),
|
|
||||||
data: {
|
|
||||||
ref: self.dropdown.getAttribute('data-ref'),
|
|
||||||
show_all: true,
|
|
||||||
},
|
|
||||||
dataType: 'json',
|
|
||||||
}).done(refs => callback(self.dropdownData(refs))),
|
|
||||||
toggleLabel(item, el) {
|
|
||||||
if (el.is('.is-active')) {
|
|
||||||
return item.text;
|
|
||||||
}
|
|
||||||
return SELECT_ITEM_MSG;
|
|
||||||
},
|
|
||||||
clicked(options) {
|
|
||||||
options.e.preventDefault();
|
|
||||||
self.onClick.call(self);
|
|
||||||
},
|
|
||||||
fieldName: self.fieldName,
|
|
||||||
});
|
|
||||||
return new gl.CreateBranchDropdown(this.form.querySelector('.dropdown-new-branch'), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick() {
|
|
||||||
this.enableSubmit();
|
|
||||||
this.$dropdown.trigger('change.branch');
|
|
||||||
}
|
|
||||||
|
|
||||||
enableSubmit() {
|
|
||||||
const submitBtn = this.form.querySelector('[type="submit"]');
|
|
||||||
if (this.branchInput && this.branchInput.value) {
|
|
||||||
submitBtn.removeAttribute('disabled');
|
|
||||||
} else {
|
|
||||||
submitBtn.setAttribute('disabled', '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dropdownData(refs) {
|
|
||||||
const branchList = this.dropdownItems(refs);
|
|
||||||
this.cachedRefs = refs;
|
|
||||||
this.addDefaultBranch(branchList);
|
|
||||||
this.addNewBranch(branchList);
|
|
||||||
return { Branches: branchList };
|
|
||||||
}
|
|
||||||
|
|
||||||
dropdownItems(refs) {
|
|
||||||
return refs.map(this.dropdownItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
dropdownItem(ref) {
|
|
||||||
return { id: ref, text: ref, title: ref };
|
|
||||||
}
|
|
||||||
|
|
||||||
addDefaultBranch(branchList) {
|
|
||||||
// when no branch is selected do nothing
|
|
||||||
if (!this.branchInput) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const branchInputVal = this.branchInput.value;
|
|
||||||
const currentBranchIndex = this.searchBranch(branchList, branchInputVal);
|
|
||||||
|
|
||||||
if (currentBranchIndex === -1) {
|
|
||||||
this.unshiftBranch(branchList, this.dropdownItem(branchInputVal));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addNewBranch(branchList) {
|
|
||||||
if (this.newBranch) {
|
|
||||||
this.unshiftBranch(branchList, this.newBranch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
searchBranch(branchList, branchName) {
|
|
||||||
return _.findIndex(branchList, el => branchName === el.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
unshiftBranch(branchList, branch) {
|
|
||||||
const branchIndex = this.searchBranch(branchList, branch.id);
|
|
||||||
|
|
||||||
if (branchIndex === -1) {
|
|
||||||
branchList.unshift(branch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setNewBranch(newBranchName) {
|
|
||||||
this.newBranch = this.dropdownItem(newBranchName);
|
|
||||||
this.refreshData();
|
|
||||||
this.selectBranch(this.searchBranch(this.glDropdown.fullData.Branches, newBranchName));
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshData() {
|
|
||||||
this.glDropdown.fullData = this.dropdownData(this.cachedRefs);
|
|
||||||
this.clearFilter();
|
|
||||||
}
|
|
||||||
|
|
||||||
clearFilter() {
|
|
||||||
// apply an empty filter in order to refresh the data
|
|
||||||
this.glDropdown.filter.filter('');
|
|
||||||
this.dropdown.closest('.dropdown').querySelector('.dropdown-page-one .dropdown-input-field').value = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
selectBranch(index) {
|
|
||||||
const branch = this.dropdown.closest('.dropdown').querySelectorAll('li a')[index];
|
|
||||||
|
|
||||||
if (!branch.classList.contains('is-active')) {
|
|
||||||
branch.click();
|
|
||||||
} else {
|
|
||||||
this.closeDropdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
closeDropdown() {
|
|
||||||
this.dropdown.closest('.dropdown').querySelector('.dropdown-menu-close').click();
|
|
||||||
}
|
|
||||||
|
|
||||||
get branchInput() {
|
|
||||||
return this.form.querySelector(`input[name="${this.fieldName}"]`);
|
|
||||||
}
|
|
||||||
|
|
||||||
get glDropdown() {
|
|
||||||
return this.$dropdown.data('glDropdown');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.gl = window.gl || {};
|
|
||||||
gl.TargetBranchDropDown = TargetBranchDropDown;
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global Api */
|
import Api from '../../api';
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global Api */
|
import Api from '../../api';
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global Api */
|
import Api from '../../api';
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global Api */
|
import Api from '../../api';
|
||||||
|
|
||||||
import FileTemplateSelector from '../file_template_selector';
|
import FileTemplateSelector from '../file_template_selector';
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,38 @@
|
||||||
/* global Flash */
|
/* global Flash */
|
||||||
export default class BlobViewer {
|
export default class BlobViewer {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
BlobViewer.initAuxiliaryViewer();
|
||||||
|
|
||||||
|
this.initMainViewers();
|
||||||
|
}
|
||||||
|
|
||||||
|
static initAuxiliaryViewer() {
|
||||||
|
const auxiliaryViewer = document.querySelector('.blob-viewer[data-type="auxiliary"]');
|
||||||
|
if (!auxiliaryViewer) return;
|
||||||
|
|
||||||
|
BlobViewer.loadViewer(auxiliaryViewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
initMainViewers() {
|
||||||
|
this.$fileHolder = $('.file-holder');
|
||||||
|
if (!this.$fileHolder.length) return;
|
||||||
|
|
||||||
this.switcher = document.querySelector('.js-blob-viewer-switcher');
|
this.switcher = document.querySelector('.js-blob-viewer-switcher');
|
||||||
this.switcherBtns = document.querySelectorAll('.js-blob-viewer-switch-btn');
|
this.switcherBtns = document.querySelectorAll('.js-blob-viewer-switch-btn');
|
||||||
this.copySourceBtn = document.querySelector('.js-copy-blob-source-btn');
|
this.copySourceBtn = document.querySelector('.js-copy-blob-source-btn');
|
||||||
this.simpleViewer = document.querySelector('.blob-viewer[data-type="simple"]');
|
|
||||||
this.richViewer = document.querySelector('.blob-viewer[data-type="rich"]');
|
|
||||||
this.$fileHolder = $('.file-holder');
|
|
||||||
|
|
||||||
let initialViewerName = document.querySelector('.blob-viewer:not(.hidden)').getAttribute('data-type');
|
this.simpleViewer = this.$fileHolder[0].querySelector('.blob-viewer[data-type="simple"]');
|
||||||
|
this.richViewer = this.$fileHolder[0].querySelector('.blob-viewer[data-type="rich"]');
|
||||||
|
|
||||||
this.initBindings();
|
this.initBindings();
|
||||||
|
|
||||||
|
this.switchToInitialViewer();
|
||||||
|
}
|
||||||
|
|
||||||
|
switchToInitialViewer() {
|
||||||
|
const initialViewer = this.$fileHolder[0].querySelector('.blob-viewer:not(.hidden)');
|
||||||
|
let initialViewerName = initialViewer.getAttribute('data-type');
|
||||||
|
|
||||||
if (this.switcher && location.hash.indexOf('#L') === 0) {
|
if (this.switcher && location.hash.indexOf('#L') === 0) {
|
||||||
initialViewerName = 'simple';
|
initialViewerName = 'simple';
|
||||||
}
|
}
|
||||||
|
@ -61,41 +82,13 @@ export default class BlobViewer {
|
||||||
$(this.copySourceBtn).tooltip('fixTitle');
|
$(this.copySourceBtn).tooltip('fixTitle');
|
||||||
}
|
}
|
||||||
|
|
||||||
loadViewer(viewerParam) {
|
|
||||||
const viewer = viewerParam;
|
|
||||||
const url = viewer.getAttribute('data-url');
|
|
||||||
|
|
||||||
if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
viewer.setAttribute('data-loading', 'true');
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url,
|
|
||||||
dataType: 'JSON',
|
|
||||||
})
|
|
||||||
.fail(() => new Flash('Error loading source view'))
|
|
||||||
.done((data) => {
|
|
||||||
viewer.innerHTML = data.html;
|
|
||||||
$(viewer).renderGFM();
|
|
||||||
|
|
||||||
viewer.setAttribute('data-loaded', 'true');
|
|
||||||
|
|
||||||
this.$fileHolder.trigger('highlight:line');
|
|
||||||
gl.utils.handleLocationHash();
|
|
||||||
|
|
||||||
this.toggleCopyButtonState();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
switchToViewer(name) {
|
switchToViewer(name) {
|
||||||
const newViewer = document.querySelector(`.blob-viewer[data-type='${name}']`);
|
const newViewer = this.$fileHolder[0].querySelector(`.blob-viewer[data-type='${name}']`);
|
||||||
if (this.activeViewer === newViewer) return;
|
if (this.activeViewer === newViewer) return;
|
||||||
|
|
||||||
const oldButton = document.querySelector('.js-blob-viewer-switch-btn.active');
|
const oldButton = document.querySelector('.js-blob-viewer-switch-btn.active');
|
||||||
const newButton = document.querySelector(`.js-blob-viewer-switch-btn[data-viewer='${name}']`);
|
const newButton = document.querySelector(`.js-blob-viewer-switch-btn[data-viewer='${name}']`);
|
||||||
const oldViewer = document.querySelector(`.blob-viewer:not([data-type='${name}'])`);
|
const oldViewer = this.$fileHolder[0].querySelector(`.blob-viewer:not([data-type='${name}'])`);
|
||||||
|
|
||||||
if (oldButton) {
|
if (oldButton) {
|
||||||
oldButton.classList.remove('active');
|
oldButton.classList.remove('active');
|
||||||
|
@ -116,6 +109,41 @@ export default class BlobViewer {
|
||||||
|
|
||||||
this.toggleCopyButtonState();
|
this.toggleCopyButtonState();
|
||||||
|
|
||||||
this.loadViewer(newViewer);
|
BlobViewer.loadViewer(newViewer)
|
||||||
|
.then((viewer) => {
|
||||||
|
$(viewer).renderGFM();
|
||||||
|
|
||||||
|
this.$fileHolder.trigger('highlight:line');
|
||||||
|
gl.utils.handleLocationHash();
|
||||||
|
|
||||||
|
this.toggleCopyButtonState();
|
||||||
|
})
|
||||||
|
.catch(() => new Flash('Error loading viewer'));
|
||||||
|
}
|
||||||
|
|
||||||
|
static loadViewer(viewerParam) {
|
||||||
|
const viewer = viewerParam;
|
||||||
|
const url = viewer.getAttribute('data-url');
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) {
|
||||||
|
resolve(viewer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
viewer.setAttribute('data-loading', 'true');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url,
|
||||||
|
dataType: 'JSON',
|
||||||
|
})
|
||||||
|
.fail(reject)
|
||||||
|
.done((data) => {
|
||||||
|
viewer.innerHTML = data.html;
|
||||||
|
viewer.setAttribute('data-loaded', 'true');
|
||||||
|
|
||||||
|
resolve(viewer);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import BlobFileDropzone from '../blob/blob_file_dropzone';
|
||||||
$(() => {
|
$(() => {
|
||||||
const editBlobForm = $('.js-edit-blob-form');
|
const editBlobForm = $('.js-edit-blob-form');
|
||||||
const uploadBlobForm = $('.js-upload-blob-form');
|
const uploadBlobForm = $('.js-upload-blob-form');
|
||||||
|
const deleteBlobForm = $('.js-delete-blob-form');
|
||||||
|
|
||||||
if (editBlobForm.length) {
|
if (editBlobForm.length) {
|
||||||
const urlRoot = editBlobForm.data('relative-url-root');
|
const urlRoot = editBlobForm.data('relative-url-root');
|
||||||
|
@ -30,4 +31,8 @@ $(() => {
|
||||||
'.btn-upload-file',
|
'.btn-upload-file',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deleteBlobForm.length) {
|
||||||
|
new NewCommitForm(deleteBlobForm);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,27 +2,27 @@
|
||||||
/* global BoardService */
|
/* global BoardService */
|
||||||
/* global Flash */
|
/* global Flash */
|
||||||
|
|
||||||
|
import _ from 'underscore';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VueResource from 'vue-resource';
|
import VueResource from 'vue-resource';
|
||||||
import FilteredSearchBoards from './filtered_search_boards';
|
import FilteredSearchBoards from './filtered_search_boards';
|
||||||
import eventHub from './eventhub';
|
import eventHub from './eventhub';
|
||||||
|
import './models/issue';
|
||||||
require('./models/issue');
|
import './models/label';
|
||||||
require('./models/label');
|
import './models/list';
|
||||||
require('./models/list');
|
import './models/milestone';
|
||||||
require('./models/milestone');
|
import './models/assignee';
|
||||||
require('./models/assignee');
|
import './stores/boards_store';
|
||||||
require('./stores/boards_store');
|
import './stores/modal_store';
|
||||||
require('./stores/modal_store');
|
import './services/board_service';
|
||||||
require('./services/board_service');
|
import './mixins/modal_mixins';
|
||||||
require('./mixins/modal_mixins');
|
import './mixins/sortable_default_options';
|
||||||
require('./mixins/sortable_default_options');
|
import './filters/due_date_filters';
|
||||||
require('./filters/due_date_filters');
|
import './components/board';
|
||||||
require('./components/board');
|
import './components/board_sidebar';
|
||||||
require('./components/board_sidebar');
|
import './components/new_list_dropdown';
|
||||||
require('./components/new_list_dropdown');
|
import './components/modal/index';
|
||||||
require('./components/modal/index');
|
import '../vue_shared/vue_resource_interceptor';
|
||||||
require('../vue_shared/vue_resource_interceptor');
|
|
||||||
|
|
||||||
Vue.use(VueResource);
|
Vue.use(VueResource);
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ $(() => {
|
||||||
gl.boardService = new BoardService(this.endpoint, this.bulkUpdatePath, this.boardId);
|
gl.boardService = new BoardService(this.endpoint, this.bulkUpdatePath, this.boardId);
|
||||||
|
|
||||||
this.filterManager = new FilteredSearchBoards(Store.filter, true);
|
this.filterManager = new FilteredSearchBoards(Store.filter, true);
|
||||||
|
this.filterManager.setup();
|
||||||
|
|
||||||
// Listen for updateTokens event
|
// Listen for updateTokens event
|
||||||
eventHub.$on('updateTokens', this.updateTokens);
|
eventHub.$on('updateTokens', this.updateTokens);
|
||||||
|
@ -81,13 +82,16 @@ $(() => {
|
||||||
mounted () {
|
mounted () {
|
||||||
Store.disabled = this.disabled;
|
Store.disabled = this.disabled;
|
||||||
gl.boardService.all()
|
gl.boardService.all()
|
||||||
|
.then(response => response.json())
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
resp.json().forEach((board) => {
|
resp.forEach((board) => {
|
||||||
const list = Store.addList(board, this.defaultAvatar);
|
const list = Store.addList(board, this.defaultAvatar);
|
||||||
|
|
||||||
if (list.type === 'closed') {
|
if (list.type === 'closed') {
|
||||||
list.position = Infinity;
|
list.position = Infinity;
|
||||||
list.label = { description: 'Shows all closed issues. Moving an issue to this list closes it' };
|
list.label = { description: 'Shows all closed issues. Moving an issue to this list closes it' };
|
||||||
|
} else if (list.type === 'backlog') {
|
||||||
|
list.position = -1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -95,7 +99,8 @@ $(() => {
|
||||||
|
|
||||||
Store.addBlankState();
|
Store.addBlankState();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}).catch(() => new Flash('An error occurred. Please try again.'));
|
})
|
||||||
|
.catch(() => new Flash('An error occurred. Please try again.'));
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateTokens() {
|
updateTokens() {
|
||||||
|
@ -128,7 +133,7 @@ $(() => {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
disabled() {
|
disabled() {
|
||||||
return !this.store.lists.filter(list => list.type !== 'blank' && list.type !== 'done').length;
|
return !this.store.lists.filter(list => !list.preset).length;
|
||||||
},
|
},
|
||||||
tooltipTitle() {
|
tooltipTitle() {
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
/* eslint-disable comma-dangle, space-before-function-paren, one-var */
|
/* eslint-disable comma-dangle, space-before-function-paren, one-var */
|
||||||
/* global Sortable */
|
/* global Sortable */
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import AccessorUtilities from '../../lib/utils/accessor';
|
||||||
import boardList from './board_list';
|
import boardList from './board_list';
|
||||||
import boardBlankState from './board_blank_state';
|
import boardBlankState from './board_blank_state';
|
||||||
|
import './board_delete';
|
||||||
require('./board_delete');
|
|
||||||
require('./board_list');
|
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
|
||||||
|
@ -24,6 +23,10 @@ gl.issueBoards.Board = Vue.extend({
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
issueLinkBase: String,
|
issueLinkBase: String,
|
||||||
rootPath: String,
|
rootPath: String,
|
||||||
|
boardId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
@ -80,7 +83,16 @@ gl.issueBoards.Board = Vue.extend({
|
||||||
methods: {
|
methods: {
|
||||||
showNewIssueForm() {
|
showNewIssueForm() {
|
||||||
this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm;
|
this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm;
|
||||||
|
},
|
||||||
|
toggleExpanded(e) {
|
||||||
|
if (this.list.isExpandable && !e.target.classList.contains('js-no-trigger-collapse')) {
|
||||||
|
this.list.isExpanded = !this.list.isExpanded;
|
||||||
|
|
||||||
|
if (AccessorUtilities.isLocalStorageAccessSafe()) {
|
||||||
|
localStorage.setItem(`boards.${this.boardId}.${this.list.type}.expanded`, this.list.isExpanded);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({
|
this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({
|
||||||
|
@ -104,4 +116,11 @@ gl.issueBoards.Board = Vue.extend({
|
||||||
|
|
||||||
this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions);
|
this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions);
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
if (this.list.isExpandable && AccessorUtilities.isLocalStorageAccessSafe()) {
|
||||||
|
const isCollapsed = localStorage.getItem(`boards.${this.boardId}.${this.list.type}.expanded`) === 'false';
|
||||||
|
|
||||||
|
this.list.isExpanded = !isCollapsed;
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* global ListLabel */
|
/* global ListLabel */
|
||||||
|
|
||||||
|
import _ from 'underscore';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
@ -64,8 +65,9 @@ export default {
|
||||||
|
|
||||||
// Save the labels
|
// Save the labels
|
||||||
gl.boardService.generateDefaultLists()
|
gl.boardService.generateDefaultLists()
|
||||||
.then((resp) => {
|
.then(resp => resp.json())
|
||||||
resp.json().forEach((listObj) => {
|
.then((data) => {
|
||||||
|
data.forEach((listObj) => {
|
||||||
const list = Store.findList('title', listObj.title);
|
const list = Store.findList('title', listObj.title);
|
||||||
|
|
||||||
list.id = listObj.id;
|
list.id = listObj.id;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require('./issue_card_inner');
|
import './issue_card_inner';
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import boardNewIssue from './board_new_issue';
|
import boardNewIssue from './board_new_issue';
|
||||||
import boardCard from './board_card';
|
import boardCard from './board_card';
|
||||||
import eventHub from '../eventhub';
|
import eventHub from '../eventhub';
|
||||||
|
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
boardCard,
|
boardCard,
|
||||||
boardNewIssue,
|
boardNewIssue,
|
||||||
|
loadingIcon,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
listHeight() {
|
listHeight() {
|
||||||
|
@ -55,6 +57,9 @@ export default {
|
||||||
scrollTop() {
|
scrollTop() {
|
||||||
return this.$refs.list.scrollTop + this.listHeight();
|
return this.$refs.list.scrollTop + this.listHeight();
|
||||||
},
|
},
|
||||||
|
scrollToTop() {
|
||||||
|
this.$refs.list.scrollTop = 0;
|
||||||
|
},
|
||||||
loadNextPage() {
|
loadNextPage() {
|
||||||
const getIssues = this.list.nextPage();
|
const getIssues = this.list.nextPage();
|
||||||
const loadingDone = () => {
|
const loadingDone = () => {
|
||||||
|
@ -106,6 +111,7 @@ export default {
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
eventHub.$on(`hide-issue-form-${this.list.id}`, this.toggleForm);
|
eventHub.$on(`hide-issue-form-${this.list.id}`, this.toggleForm);
|
||||||
|
eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const options = gl.issueBoards.getBoardSortableDefaultOptions({
|
const options = gl.issueBoards.getBoardSortableDefaultOptions({
|
||||||
|
@ -148,6 +154,7 @@ export default {
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
eventHub.$off(`hide-issue-form-${this.list.id}`, this.toggleForm);
|
eventHub.$off(`hide-issue-form-${this.list.id}`, this.toggleForm);
|
||||||
|
eventHub.$off(`scroll-board-list-${this.list.id}`, this.scrollToTop);
|
||||||
this.$refs.list.removeEventListener('scroll', this.onScroll);
|
this.$refs.list.removeEventListener('scroll', this.onScroll);
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
|
@ -156,14 +163,13 @@ export default {
|
||||||
class="board-list-loading text-center"
|
class="board-list-loading text-center"
|
||||||
aria-label="Loading issues"
|
aria-label="Loading issues"
|
||||||
v-if="loading">
|
v-if="loading">
|
||||||
<i
|
<loading-icon />
|
||||||
class="fa fa-spinner fa-spin"
|
|
||||||
aria-hidden="true">
|
|
||||||
</i>
|
|
||||||
</div>
|
</div>
|
||||||
|
<transition name="slide-down">
|
||||||
<board-new-issue
|
<board-new-issue
|
||||||
:list="list"
|
:list="list"
|
||||||
v-if="list.type !== 'closed' && showIssueForm"/>
|
v-if="list.type !== 'closed' && showIssueForm"/>
|
||||||
|
</transition>
|
||||||
<ul
|
<ul
|
||||||
class="board-list"
|
class="board-list"
|
||||||
v-show="!loading"
|
v-show="!loading"
|
||||||
|
@ -184,12 +190,12 @@ export default {
|
||||||
class="board-list-count text-center"
|
class="board-list-count text-center"
|
||||||
v-if="showCount"
|
v-if="showCount"
|
||||||
data-id="-1">
|
data-id="-1">
|
||||||
<i
|
|
||||||
class="fa fa-spinner fa-spin"
|
<loading-icon
|
||||||
aria-label="Loading more issues"
|
v-show="list.loadingMore"
|
||||||
aria-hidden="true"
|
label="Loading more issues"
|
||||||
v-show="list.loadingMore">
|
/>
|
||||||
</i>
|
|
||||||
<span v-if="list.issues.length === list.issuesSize">
|
<span v-if="list.issues.length === list.issuesSize">
|
||||||
Showing all issues
|
Showing all issues
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
submit(e) {
|
submit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (this.title.trim() === '') return;
|
if (this.title.trim() === '') return Promise.resolve();
|
||||||
|
|
||||||
this.error = false;
|
this.error = false;
|
||||||
|
|
||||||
|
@ -29,7 +29,10 @@ export default {
|
||||||
assignees: [],
|
assignees: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.list.newIssue(issue)
|
eventHub.$emit(`scroll-board-list-${this.list.id}`);
|
||||||
|
this.cancel();
|
||||||
|
|
||||||
|
return this.list.newIssue(issue)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Need this because our jQuery very kindly disables buttons on ALL form submissions
|
// Need this because our jQuery very kindly disables buttons on ALL form submissions
|
||||||
$(this.$refs.submitButton).enable();
|
$(this.$refs.submitButton).enable();
|
||||||
|
@ -47,8 +50,6 @@ export default {
|
||||||
// Show error message
|
// Show error message
|
||||||
this.error = true;
|
this.error = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.cancel();
|
|
||||||
},
|
},
|
||||||
cancel() {
|
cancel() {
|
||||||
this.title = '';
|
this.title = '';
|
||||||
|
@ -75,6 +76,7 @@ export default {
|
||||||
type="text"
|
type="text"
|
||||||
v-model="title"
|
v-model="title"
|
||||||
ref="input"
|
ref="input"
|
||||||
|
autocomplete="off"
|
||||||
:id="list.id + '-title'" />
|
:id="list.id + '-title'" />
|
||||||
<div class="clearfix prepend-top-10">
|
<div class="clearfix prepend-top-10">
|
||||||
<button class="btn btn-success pull-left"
|
<button class="btn btn-success pull-left"
|
||||||
|
|
|
@ -7,11 +7,9 @@
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import eventHub from '../../sidebar/event_hub';
|
import eventHub from '../../sidebar/event_hub';
|
||||||
|
|
||||||
import AssigneeTitle from '../../sidebar/components/assignees/assignee_title';
|
import AssigneeTitle from '../../sidebar/components/assignees/assignee_title';
|
||||||
import Assignees from '../../sidebar/components/assignees/assignees';
|
import Assignees from '../../sidebar/components/assignees/assignees';
|
||||||
|
import './sidebar/remove_issue';
|
||||||
require('./sidebar/remove_issue');
|
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
|
||||||
|
@ -34,9 +32,12 @@ gl.issueBoards.BoardSidebar = Vue.extend({
|
||||||
showSidebar () {
|
showSidebar () {
|
||||||
return Object.keys(this.issue).length;
|
return Object.keys(this.issue).length;
|
||||||
},
|
},
|
||||||
assigneeId() {
|
milestoneTitle() {
|
||||||
return this.issue.assignee ? this.issue.assignee.id : 0;
|
return this.issue.milestone ? this.issue.milestone.title : 'No Milestone';
|
||||||
}
|
},
|
||||||
|
canRemove() {
|
||||||
|
return !this.list.preset;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
detail: {
|
detail: {
|
||||||
|
@ -62,18 +63,6 @@ gl.issueBoards.BoardSidebar = Vue.extend({
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
},
|
},
|
||||||
issue () {
|
|
||||||
if (this.showSidebar) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
$('.right-sidebar').getNiceScroll(0).doScrollTop(0, 0);
|
|
||||||
$('.right-sidebar').getNiceScroll().resize();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.issue = this.detail.issue;
|
|
||||||
this.list = this.detail.list;
|
|
||||||
},
|
|
||||||
deep: true
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeSidebar () {
|
closeSidebar () {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||||
import eventHub from '../eventhub';
|
import eventHub from '../eventhub';
|
||||||
|
|
||||||
const Store = gl.issueBoards.BoardsStore;
|
const Store = gl.issueBoards.BoardsStore;
|
||||||
|
@ -38,6 +39,9 @@ gl.issueBoards.IssueCardInner = Vue.extend({
|
||||||
maxCounter: 99,
|
maxCounter: 99,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
userAvatarLink,
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
numberOverLimit() {
|
numberOverLimit() {
|
||||||
return this.issue.assignees.length - this.limitBeforeCounter;
|
return this.issue.assignees.length - this.limitBeforeCounter;
|
||||||
|
@ -93,9 +97,8 @@ gl.issueBoards.IssueCardInner = Vue.extend({
|
||||||
return `Avatar for ${assignee.name}`;
|
return `Avatar for ${assignee.name}`;
|
||||||
},
|
},
|
||||||
showLabel(label) {
|
showLabel(label) {
|
||||||
if (!this.list) return true;
|
if (!label.id) return false;
|
||||||
|
return true;
|
||||||
return !this.list.label || label.id !== this.list.label.id;
|
|
||||||
},
|
},
|
||||||
filterByLabel(label, e) {
|
filterByLabel(label, e) {
|
||||||
if (!this.updateFilters) return;
|
if (!this.updateFilters) return;
|
||||||
|
@ -146,23 +149,17 @@ gl.issueBoards.IssueCardInner = Vue.extend({
|
||||||
</span>
|
</span>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="card-assignee">
|
<div class="card-assignee">
|
||||||
<a
|
<user-avatar-link
|
||||||
class="has-tooltip js-no-trigger"
|
|
||||||
:href="assigneeUrl(assignee)"
|
|
||||||
:title="assigneeUrlTitle(assignee)"
|
|
||||||
v-for="(assignee, index) in issue.assignees"
|
v-for="(assignee, index) in issue.assignees"
|
||||||
|
:key="assignee.id"
|
||||||
v-if="shouldRenderAssignee(index)"
|
v-if="shouldRenderAssignee(index)"
|
||||||
data-container="body"
|
class="js-no-trigger"
|
||||||
data-placement="bottom"
|
:link-href="assigneeUrl(assignee)"
|
||||||
>
|
:img-alt="avatarUrlTitle(assignee)"
|
||||||
<img
|
:img-src="assignee.avatar"
|
||||||
class="avatar avatar-inline s20"
|
:tooltip-text="assigneeUrlTitle(assignee)"
|
||||||
:src="assignee.avatar"
|
tooltip-placement="bottom"
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
:alt="avatarUrlTitle(assignee)"
|
|
||||||
/>
|
/>
|
||||||
</a>
|
|
||||||
<span
|
<span
|
||||||
class="avatar-counter has-tooltip"
|
class="avatar-counter has-tooltip"
|
||||||
:title="assigneeCounterTooltip"
|
:title="assigneeCounterTooltip"
|
||||||
|
|
|
@ -13,6 +13,7 @@ export default {
|
||||||
FilteredSearchContainer.container = this.$el;
|
FilteredSearchContainer.container = this.$el;
|
||||||
|
|
||||||
this.filteredSearch = new FilteredSearchBoards(this.store);
|
this.filteredSearch = new FilteredSearchBoards(this.store);
|
||||||
|
this.filteredSearch.setup();
|
||||||
this.filteredSearch.removeTokens();
|
this.filteredSearch.removeTokens();
|
||||||
this.filteredSearch.handleInputPlaceholder();
|
this.filteredSearch.handleInputPlaceholder();
|
||||||
this.filteredSearch.toggleClearSearchButton();
|
this.filteredSearch.toggleClearSearchButton();
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
/* global Flash */
|
/* global Flash */
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import './lists_dropdown';
|
||||||
require('./lists_dropdown');
|
|
||||||
|
|
||||||
const ModalStore = gl.issueBoards.ModalStore;
|
const ModalStore = gl.issueBoards.ModalStore;
|
||||||
|
|
||||||
|
@ -27,7 +26,8 @@ gl.issueBoards.ModalFooter = Vue.extend({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addIssues() {
|
addIssues() {
|
||||||
const list = this.modal.selectedList || this.state.lists[0];
|
const firstListIndex = 1;
|
||||||
|
const list = this.modal.selectedList || this.state.lists[firstListIndex];
|
||||||
const selectedIssues = ModalStore.getSelectedIssues();
|
const selectedIssues = ModalStore.getSelectedIssues();
|
||||||
const issueIds = selectedIssues.map(issue => issue.globalId);
|
const issueIds = selectedIssues.map(issue => issue.globalId);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import modalFilters from './filters';
|
import modalFilters from './filters';
|
||||||
|
import './tabs';
|
||||||
require('./tabs');
|
|
||||||
|
|
||||||
const ModalStore = gl.issueBoards.ModalStore;
|
const ModalStore = gl.issueBoards.ModalStore;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/* global ListIssue */
|
/* global ListIssue */
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import queryData from '../../utils/query_data';
|
import queryData from '~/boards/utils/query_data';
|
||||||
|
import loadingIcon from '~/vue_shared/components/loading_icon.vue';
|
||||||
require('./header');
|
import './header';
|
||||||
require('./list');
|
import './list';
|
||||||
require('./footer');
|
import './footer';
|
||||||
require('./empty_state');
|
import './empty_state';
|
||||||
|
|
||||||
const ModalStore = gl.issueBoards.ModalStore;
|
const ModalStore = gl.issueBoards.ModalStore;
|
||||||
|
|
||||||
|
@ -88,9 +88,9 @@ gl.issueBoards.IssuesModal = Vue.extend({
|
||||||
return gl.boardService.getBacklog(queryData(this.filter.path, {
|
return gl.boardService.getBacklog(queryData(this.filter.path, {
|
||||||
page: this.page,
|
page: this.page,
|
||||||
per: this.perPage,
|
per: this.perPage,
|
||||||
})).then((res) => {
|
}))
|
||||||
const data = res.json();
|
.then(resp => resp.json())
|
||||||
|
.then((data) => {
|
||||||
if (clearIssues) {
|
if (clearIssues) {
|
||||||
this.issues = [];
|
this.issues = [];
|
||||||
}
|
}
|
||||||
|
@ -137,6 +137,7 @@ gl.issueBoards.IssuesModal = Vue.extend({
|
||||||
'modal-list': gl.issueBoards.ModalList,
|
'modal-list': gl.issueBoards.ModalList,
|
||||||
'modal-footer': gl.issueBoards.ModalFooter,
|
'modal-footer': gl.issueBoards.ModalFooter,
|
||||||
'empty-state': gl.issueBoards.ModalEmptyState,
|
'empty-state': gl.issueBoards.ModalEmptyState,
|
||||||
|
loadingIcon,
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
<div
|
<div
|
||||||
|
@ -161,7 +162,7 @@ gl.issueBoards.IssuesModal = Vue.extend({
|
||||||
class="add-issues-list text-center"
|
class="add-issues-list text-center"
|
||||||
v-if="loading || filterLoading">
|
v-if="loading || filterLoading">
|
||||||
<div class="add-issues-list-loading">
|
<div class="add-issues-list-loading">
|
||||||
<i class="fa fa-spinner fa-spin"></i>
|
<loading-icon />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<modal-footer></modal-footer>
|
<modal-footer></modal-footer>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* global ListIssue */
|
/* global ListIssue */
|
||||||
/* global bp */
|
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import bp from '../../../breakpoints';
|
||||||
|
|
||||||
const ModalStore = gl.issueBoards.ModalStore;
|
const ModalStore = gl.issueBoards.ModalStore;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ gl.issueBoards.ModalFooterListsDropdown = Vue.extend({
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
selected() {
|
selected() {
|
||||||
return this.modal.selectedList || this.state.lists[0];
|
return this.modal.selectedList || this.state.lists[1];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* eslint-disable comma-dangle, func-names, no-new, space-before-function-paren, one-var,
|
/* eslint-disable comma-dangle, func-names, no-new, space-before-function-paren, one-var,
|
||||||
promise/catch-or-return */
|
promise/catch-or-return */
|
||||||
|
import _ from 'underscore';
|
||||||
|
|
||||||
window.gl = window.gl || {};
|
window.gl = window.gl || {};
|
||||||
window.gl.issueBoards = window.gl.issueBoards || {};
|
window.gl.issueBoards = window.gl.issueBoards || {};
|
||||||
|
|
|
@ -46,8 +46,7 @@ gl.issueBoards.RemoveIssueBtn = Vue.extend({
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
<div
|
<div
|
||||||
class="block list"
|
class="block list">
|
||||||
v-if="list.type !== 'closed'">
|
|
||||||
<button
|
<button
|
||||||
class="btn btn-default btn-block"
|
class="btn btn-default btn-block"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import FilteredSearchContainer from '../filtered_search/container';
|
import FilteredSearchContainer from '../filtered_search/container';
|
||||||
|
|
||||||
export default class FilteredSearchBoards extends gl.FilteredSearchManager {
|
export default class FilteredSearchBoards extends gl.FilteredSearchManager {
|
||||||
constructor(store, updateUrl = false) {
|
constructor(store, updateUrl = false, cantEdit = []) {
|
||||||
super('boards');
|
super('boards');
|
||||||
|
|
||||||
this.store = store;
|
this.store = store;
|
||||||
|
@ -11,6 +11,7 @@ export default class FilteredSearchBoards extends gl.FilteredSearchManager {
|
||||||
// Issue boards is slightly different, we handle all the requests async
|
// Issue boards is slightly different, we handle all the requests async
|
||||||
// instead or reloading the page, we just re-fire the list ajax requests
|
// instead or reloading the page, we just re-fire the list ajax requests
|
||||||
this.isHandledAsync = true;
|
this.isHandledAsync = true;
|
||||||
|
this.cantEdit = cantEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateObject(path) {
|
updateObject(path) {
|
||||||
|
@ -40,4 +41,8 @@ export default class FilteredSearchBoards extends gl.FilteredSearchManager {
|
||||||
// Get the placeholder back if search is empty
|
// Get the placeholder back if search is empty
|
||||||
this.filteredSearchInput.dispatchEvent(new Event('input'));
|
this.filteredSearchInput.dispatchEvent(new Event('input'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canEdit(tokenName) {
|
||||||
|
return this.cantEdit.indexOf(tokenName) === -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ class List {
|
||||||
this.position = obj.position;
|
this.position = obj.position;
|
||||||
this.title = obj.title;
|
this.title = obj.title;
|
||||||
this.type = obj.list_type;
|
this.type = obj.list_type;
|
||||||
this.preset = ['closed', 'blank'].indexOf(this.type) > -1;
|
this.preset = ['backlog', 'closed', 'blank'].indexOf(this.type) > -1;
|
||||||
|
this.isExpandable = ['backlog', 'closed'].indexOf(this.type) > -1;
|
||||||
|
this.isExpanded = true;
|
||||||
this.page = 1;
|
this.page = 1;
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.loadingMore = false;
|
this.loadingMore = false;
|
||||||
|
@ -38,9 +40,8 @@ class List {
|
||||||
|
|
||||||
save () {
|
save () {
|
||||||
return gl.boardService.createList(this.label.id)
|
return gl.boardService.createList(this.label.id)
|
||||||
.then((resp) => {
|
.then(resp => resp.json())
|
||||||
const data = resp.json();
|
.then((data) => {
|
||||||
|
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
this.type = data.list_type;
|
this.type = data.list_type;
|
||||||
this.position = data.position;
|
this.position = data.position;
|
||||||
|
@ -89,8 +90,8 @@ class List {
|
||||||
}
|
}
|
||||||
|
|
||||||
return gl.boardService.getIssuesForList(this.id, data)
|
return gl.boardService.getIssuesForList(this.id, data)
|
||||||
.then((resp) => {
|
.then(resp => resp.json())
|
||||||
const data = resp.json();
|
.then((data) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.issuesSize = data.size;
|
this.issuesSize = data.size;
|
||||||
|
|
||||||
|
@ -103,13 +104,18 @@ class List {
|
||||||
}
|
}
|
||||||
|
|
||||||
newIssue (issue) {
|
newIssue (issue) {
|
||||||
this.addIssue(issue);
|
this.addIssue(issue, null, 0);
|
||||||
this.issuesSize += 1;
|
this.issuesSize += 1;
|
||||||
|
|
||||||
return gl.boardService.newIssue(this.id, issue)
|
return gl.boardService.newIssue(this.id, issue)
|
||||||
.then((resp) => {
|
.then(resp => resp.json())
|
||||||
const data = resp.json();
|
.then((data) => {
|
||||||
issue.id = data.iid;
|
issue.id = data.iid;
|
||||||
|
|
||||||
|
if (this.issuesSize > 1) {
|
||||||
|
const moveBeforeIid = this.issues[1].id;
|
||||||
|
gl.boardService.moveIssue(issue.id, null, null, null, moveBeforeIid);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,6 @@ class BoardService {
|
||||||
url: bulkUpdatePath,
|
url: bulkUpdatePath,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Vue.http.interceptors.push((request, next) => {
|
|
||||||
request.headers['X-CSRF-Token'] = $.rails.csrfToken();
|
|
||||||
next();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
all () {
|
all () {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable comma-dangle, space-before-function-paren, one-var, no-shadow, dot-notation, max-len */
|
/* eslint-disable comma-dangle, space-before-function-paren, one-var, no-shadow, dot-notation, max-len */
|
||||||
/* global List */
|
/* global List */
|
||||||
|
import _ from 'underscore';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
|
|
||||||
window.gl = window.gl || {};
|
window.gl = window.gl || {};
|
||||||
|
@ -22,6 +22,7 @@ gl.issueBoards.BoardsStore = {
|
||||||
create () {
|
create () {
|
||||||
this.state.lists = [];
|
this.state.lists = [];
|
||||||
this.filter.path = gl.utils.getUrlParamsArray().join('&');
|
this.filter.path = gl.utils.getUrlParamsArray().join('&');
|
||||||
|
this.detail = { issue: {} };
|
||||||
},
|
},
|
||||||
addList (listObj, defaultAvatar) {
|
addList (listObj, defaultAvatar) {
|
||||||
const list = new List(listObj, defaultAvatar);
|
const list = new List(listObj, defaultAvatar);
|
||||||
|
@ -31,10 +32,14 @@ gl.issueBoards.BoardsStore = {
|
||||||
},
|
},
|
||||||
new (listObj) {
|
new (listObj) {
|
||||||
const list = this.addList(listObj);
|
const list = this.addList(listObj);
|
||||||
|
const backlogList = this.findList('type', 'backlog', 'backlog');
|
||||||
|
|
||||||
list
|
list
|
||||||
.save()
|
.save()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
// Remove any new issues from the backlog
|
||||||
|
// as they will be visible in the new list
|
||||||
|
list.issues.forEach(backlogList.removeIssue.bind(backlogList));
|
||||||
this.state.lists = _.sortBy(this.state.lists, 'position');
|
this.state.lists = _.sortBy(this.state.lists, 'position');
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
@ -47,7 +52,7 @@ gl.issueBoards.BoardsStore = {
|
||||||
},
|
},
|
||||||
shouldAddBlankState () {
|
shouldAddBlankState () {
|
||||||
// Decide whether to add the blank state
|
// Decide whether to add the blank state
|
||||||
return !(this.state.lists.filter(list => list.type !== 'closed')[0]);
|
return !(this.state.lists.filter(list => list.type !== 'backlog' && list.type !== 'closed')[0]);
|
||||||
},
|
},
|
||||||
addBlankState () {
|
addBlankState () {
|
||||||
if (!this.shouldAddBlankState() || this.welcomeIsHidden() || this.disabled) return;
|
if (!this.shouldAddBlankState() || this.welcomeIsHidden() || this.disabled) return;
|
||||||
|
@ -100,7 +105,7 @@ gl.issueBoards.BoardsStore = {
|
||||||
issueTo.removeLabel(listFrom.label);
|
issueTo.removeLabel(listFrom.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listTo.type === 'closed') {
|
if (listTo.type === 'closed' && listFrom.type !== 'backlog') {
|
||||||
issueLists.forEach((list) => {
|
issueLists.forEach((list) => {
|
||||||
list.removeIssue(issue);
|
list.removeIssue(issue);
|
||||||
});
|
});
|
||||||
|
|
36
app/assets/javascripts/branches/branches_delete_modal.js
Normal file
36
app/assets/javascripts/branches/branches_delete_modal.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
const MODAL_SELECTOR = '#modal-delete-branch';
|
||||||
|
|
||||||
|
class DeleteModal {
|
||||||
|
constructor() {
|
||||||
|
this.$modal = $(MODAL_SELECTOR);
|
||||||
|
this.$toggleBtns = $(`[data-target="${MODAL_SELECTOR}"]`);
|
||||||
|
this.$branchName = $('.js-branch-name', this.$modal);
|
||||||
|
this.$confirmInput = $('.js-delete-branch-input', this.$modal);
|
||||||
|
this.$deleteBtn = $('.js-delete-branch', this.$modal);
|
||||||
|
this.bindEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEvents() {
|
||||||
|
this.$toggleBtns.on('click', this.setModalData.bind(this));
|
||||||
|
this.$confirmInput.on('input', this.setDeleteDisabled.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
setModalData(e) {
|
||||||
|
this.branchName = e.currentTarget.dataset.branchName || '';
|
||||||
|
this.deletePath = e.currentTarget.dataset.deletePath || '';
|
||||||
|
this.updateModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
setDeleteDisabled(e) {
|
||||||
|
this.$deleteBtn.attr('disabled', e.currentTarget.value !== this.branchName);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateModal() {
|
||||||
|
this.$branchName.text(this.branchName);
|
||||||
|
this.$confirmInput.val('');
|
||||||
|
this.$deleteBtn.attr('href', this.deletePath);
|
||||||
|
this.$deleteBtn.attr('disabled', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DeleteModal;
|
|
@ -1,66 +1,19 @@
|
||||||
/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, quotes, no-shadow, prefer-arrow-callback, prefer-template, consistent-return, no-return-assign, new-parens, no-param-reassign, max-len */
|
export const breakpoints = {
|
||||||
|
lg: 1200,
|
||||||
|
md: 992,
|
||||||
|
sm: 768,
|
||||||
|
xs: 0,
|
||||||
|
};
|
||||||
|
|
||||||
var Breakpoints = (function() {
|
const BreakpointInstance = {
|
||||||
var BreakpointInstance, instance;
|
windowWidth: () => window.innerWidth,
|
||||||
|
getBreakpointSize() {
|
||||||
|
const windowWidth = this.windowWidth();
|
||||||
|
|
||||||
function Breakpoints() {}
|
const breakpoint = Object.keys(breakpoints).find(key => windowWidth > breakpoints[key]);
|
||||||
|
|
||||||
instance = null;
|
return breakpoint;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
BreakpointInstance = (function() {
|
export default BreakpointInstance;
|
||||||
var BREAKPOINTS;
|
|
||||||
|
|
||||||
BREAKPOINTS = ["xs", "sm", "md", "lg"];
|
|
||||||
|
|
||||||
function BreakpointInstance() {
|
|
||||||
this.setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
BreakpointInstance.prototype.setup = function() {
|
|
||||||
var allDeviceSelector, els;
|
|
||||||
allDeviceSelector = BREAKPOINTS.map(function(breakpoint) {
|
|
||||||
return ".device-" + breakpoint;
|
|
||||||
});
|
|
||||||
if ($(allDeviceSelector.join(",")).length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Create all the elements
|
|
||||||
els = $.map(BREAKPOINTS, function(breakpoint) {
|
|
||||||
return "<div class='device-" + breakpoint + " visible-" + breakpoint + "'></div>";
|
|
||||||
});
|
|
||||||
return $("body").append(els.join(''));
|
|
||||||
};
|
|
||||||
|
|
||||||
BreakpointInstance.prototype.visibleDevice = function() {
|
|
||||||
var allDeviceSelector;
|
|
||||||
allDeviceSelector = BREAKPOINTS.map(function(breakpoint) {
|
|
||||||
return ".device-" + breakpoint;
|
|
||||||
});
|
|
||||||
return $(allDeviceSelector.join(",")).filter(":visible");
|
|
||||||
};
|
|
||||||
|
|
||||||
BreakpointInstance.prototype.getBreakpointSize = function() {
|
|
||||||
var $visibleDevice;
|
|
||||||
$visibleDevice = this.visibleDevice;
|
|
||||||
// TODO: Consider refactoring in light of turbolinks removal.
|
|
||||||
// the page refreshed via turbolinks
|
|
||||||
if (!$visibleDevice().length) {
|
|
||||||
this.setup();
|
|
||||||
}
|
|
||||||
$visibleDevice = this.visibleDevice();
|
|
||||||
return $visibleDevice.attr("class").split("visible-")[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
return BreakpointInstance;
|
|
||||||
})();
|
|
||||||
|
|
||||||
Breakpoints.get = function() {
|
|
||||||
return instance != null ? instance : instance = new BreakpointInstance;
|
|
||||||
};
|
|
||||||
|
|
||||||
return Breakpoints;
|
|
||||||
})();
|
|
||||||
|
|
||||||
$(() => { window.bp = Breakpoints.get(); });
|
|
||||||
|
|
||||||
window.Breakpoints = Breakpoints;
|
|
||||||
|
|
|
@ -1,47 +1,38 @@
|
||||||
/* eslint-disable func-names, wrap-iife, no-use-before-define,
|
/* eslint-disable func-names, wrap-iife, no-use-before-define,
|
||||||
consistent-return, prefer-rest-params */
|
consistent-return, prefer-rest-params */
|
||||||
/* global Breakpoints */
|
import _ from 'underscore';
|
||||||
|
import bp from './breakpoints';
|
||||||
import { bytesToKiB } from './lib/utils/number_utils';
|
import { bytesToKiB } from './lib/utils/number_utils';
|
||||||
|
|
||||||
const bind = function (fn, me) { return function () { return fn.apply(me, arguments); }; };
|
|
||||||
const AUTO_SCROLL_OFFSET = 75;
|
|
||||||
const DOWN_BUILD_TRACE = '#down-build-trace';
|
|
||||||
|
|
||||||
window.Build = (function () {
|
window.Build = (function () {
|
||||||
Build.timeout = null;
|
Build.timeout = null;
|
||||||
|
|
||||||
Build.state = null;
|
Build.state = null;
|
||||||
|
|
||||||
function Build(options) {
|
function Build(options) {
|
||||||
this.options = options || $('.js-build-options').data();
|
this.options = options || $('.js-build-options').data();
|
||||||
|
|
||||||
this.pageUrl = this.options.pageUrl;
|
this.pageUrl = this.options.pageUrl;
|
||||||
this.buildUrl = this.options.buildUrl;
|
|
||||||
this.buildStatus = this.options.buildStatus;
|
this.buildStatus = this.options.buildStatus;
|
||||||
this.state = this.options.logState;
|
this.state = this.options.logState;
|
||||||
this.buildStage = this.options.buildStage;
|
this.buildStage = this.options.buildStage;
|
||||||
this.$document = $(document);
|
this.$document = $(document);
|
||||||
this.logBytes = 0;
|
this.logBytes = 0;
|
||||||
|
this.hasBeenScrolled = false;
|
||||||
|
|
||||||
this.updateDropdown = bind(this.updateDropdown, this);
|
this.updateDropdown = this.updateDropdown.bind(this);
|
||||||
|
this.getBuildTrace = this.getBuildTrace.bind(this);
|
||||||
|
|
||||||
this.$body = $('body');
|
|
||||||
this.$buildTrace = $('#build-trace');
|
this.$buildTrace = $('#build-trace');
|
||||||
this.$autoScrollContainer = $('.autoscroll-container');
|
|
||||||
this.$autoScrollStatus = $('#autoscroll-status');
|
|
||||||
this.$autoScrollStatusText = this.$autoScrollStatus.find('.status-text');
|
|
||||||
this.$upBuildTrace = $('#up-build-trace');
|
|
||||||
this.$downBuildTrace = $(DOWN_BUILD_TRACE);
|
|
||||||
this.$scrollTopBtn = $('#scroll-top');
|
|
||||||
this.$scrollBottomBtn = $('#scroll-bottom');
|
|
||||||
this.$buildRefreshAnimation = $('.js-build-refresh');
|
this.$buildRefreshAnimation = $('.js-build-refresh');
|
||||||
this.$buildScroll = $('#js-build-scroll');
|
|
||||||
this.$truncatedInfo = $('.js-truncated-info');
|
this.$truncatedInfo = $('.js-truncated-info');
|
||||||
|
this.$buildTraceOutput = $('.js-build-output');
|
||||||
|
this.$topBar = $('.js-top-bar');
|
||||||
|
|
||||||
|
// Scroll controllers
|
||||||
|
this.$scrollTopBtn = $('.js-scroll-up');
|
||||||
|
this.$scrollBottomBtn = $('.js-scroll-down');
|
||||||
|
|
||||||
clearTimeout(Build.timeout);
|
clearTimeout(Build.timeout);
|
||||||
// Init breakpoint checker
|
|
||||||
this.bp = Breakpoints.get();
|
|
||||||
|
|
||||||
this.initSidebar();
|
this.initSidebar();
|
||||||
this.populateJobs(this.buildStage);
|
this.populateJobs(this.buildStage);
|
||||||
|
@ -56,54 +47,141 @@ window.Build = (function () {
|
||||||
.off('click', '.stage-item')
|
.off('click', '.stage-item')
|
||||||
.on('click', '.stage-item', this.updateDropdown);
|
.on('click', '.stage-item', this.updateDropdown);
|
||||||
|
|
||||||
this.$document.on('scroll', this.initScrollMonitor.bind(this));
|
// add event listeners to the scroll buttons
|
||||||
|
this.$scrollTopBtn
|
||||||
|
.off('click')
|
||||||
|
.on('click', this.scrollToTop.bind(this));
|
||||||
|
|
||||||
|
this.$scrollBottomBtn
|
||||||
|
.off('click')
|
||||||
|
.on('click', this.scrollToBottom.bind(this));
|
||||||
|
|
||||||
|
this.scrollThrottled = _.throttle(this.toggleScroll.bind(this), 100);
|
||||||
|
|
||||||
|
$(window)
|
||||||
|
.off('scroll')
|
||||||
|
.on('scroll', () => {
|
||||||
|
const contentHeight = this.$buildTraceOutput.height();
|
||||||
|
if (contentHeight > this.windowSize) {
|
||||||
|
// means the user did not scroll, the content was updated.
|
||||||
|
this.windowSize = contentHeight;
|
||||||
|
} else {
|
||||||
|
// User scrolled
|
||||||
|
this.hasBeenScrolled = true;
|
||||||
|
this.toggleScrollAnimation(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollThrottled();
|
||||||
|
});
|
||||||
|
|
||||||
$(window)
|
$(window)
|
||||||
.off('resize.build')
|
.off('resize.build')
|
||||||
.on('resize.build', this.sidebarOnResize.bind(this));
|
.on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100));
|
||||||
|
|
||||||
$('a', this.$buildScroll)
|
|
||||||
.off('click.stepTrace')
|
|
||||||
.on('click.stepTrace', this.stepTrace);
|
|
||||||
|
|
||||||
this.updateArtifactRemoveDate();
|
this.updateArtifactRemoveDate();
|
||||||
this.initScrollButtonAffix();
|
this.initAffixTopArea();
|
||||||
this.invokeBuildTrace();
|
|
||||||
|
this.getBuildTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Build.prototype.initAffixTopArea = function () {
|
||||||
|
/**
|
||||||
|
If the browser does not support position sticky, it returns the position as static.
|
||||||
|
If the browser does support sticky, then we allow the browser to handle it, if not
|
||||||
|
then we default back to Bootstraps affix
|
||||||
|
**/
|
||||||
|
if (this.$topBar.css('position') !== 'static') return;
|
||||||
|
|
||||||
|
const offsetTop = this.$buildTrace.offset().top;
|
||||||
|
|
||||||
|
this.$topBar.affix({
|
||||||
|
offset: {
|
||||||
|
top: offsetTop,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Build.prototype.canScroll = function () {
|
||||||
|
return $(document).height() > $(window).height();
|
||||||
|
};
|
||||||
|
|
||||||
|
Build.prototype.toggleScroll = function () {
|
||||||
|
const currentPosition = $(document).scrollTop();
|
||||||
|
const scrollHeight = $(document).height();
|
||||||
|
|
||||||
|
const windowHeight = $(window).height();
|
||||||
|
if (this.canScroll()) {
|
||||||
|
if (currentPosition > 0 &&
|
||||||
|
(scrollHeight - currentPosition !== windowHeight)) {
|
||||||
|
// User is in the middle of the log
|
||||||
|
|
||||||
|
this.toggleDisableButton(this.$scrollTopBtn, false);
|
||||||
|
this.toggleDisableButton(this.$scrollBottomBtn, false);
|
||||||
|
} else if (currentPosition === 0) {
|
||||||
|
// User is at Top of Build Log
|
||||||
|
|
||||||
|
this.toggleDisableButton(this.$scrollTopBtn, true);
|
||||||
|
this.toggleDisableButton(this.$scrollBottomBtn, false);
|
||||||
|
} else if (scrollHeight - currentPosition === windowHeight) {
|
||||||
|
// User is at the bottom of the build log.
|
||||||
|
|
||||||
|
this.toggleDisableButton(this.$scrollTopBtn, false);
|
||||||
|
this.toggleDisableButton(this.$scrollBottomBtn, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.toggleDisableButton(this.$scrollTopBtn, true);
|
||||||
|
this.toggleDisableButton(this.$scrollBottomBtn, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Build.prototype.scrollDown = function () {
|
||||||
|
$(document).scrollTop($(document).height());
|
||||||
|
};
|
||||||
|
|
||||||
|
Build.prototype.scrollToBottom = function () {
|
||||||
|
this.scrollDown();
|
||||||
|
this.hasBeenScrolled = true;
|
||||||
|
this.toggleScroll();
|
||||||
|
};
|
||||||
|
|
||||||
|
Build.prototype.scrollToTop = function () {
|
||||||
|
$(document).scrollTop(0);
|
||||||
|
this.hasBeenScrolled = true;
|
||||||
|
this.toggleScroll();
|
||||||
|
};
|
||||||
|
|
||||||
|
Build.prototype.toggleDisableButton = function ($button, disable) {
|
||||||
|
if (disable && $button.prop('disabled')) return;
|
||||||
|
$button.prop('disabled', disable);
|
||||||
|
};
|
||||||
|
|
||||||
|
Build.prototype.toggleScrollAnimation = function (toggle) {
|
||||||
|
this.$scrollBottomBtn.toggleClass('animate', toggle);
|
||||||
|
};
|
||||||
|
|
||||||
Build.prototype.initSidebar = function () {
|
Build.prototype.initSidebar = function () {
|
||||||
this.$sidebar = $('.js-build-sidebar');
|
this.$sidebar = $('.js-build-sidebar');
|
||||||
this.$sidebar.niceScroll();
|
|
||||||
this.$document
|
|
||||||
.off('click', '.js-sidebar-build-toggle')
|
|
||||||
.on('click', '.js-sidebar-build-toggle', this.toggleSidebar);
|
|
||||||
};
|
|
||||||
|
|
||||||
Build.prototype.invokeBuildTrace = function () {
|
|
||||||
return this.getBuildTrace();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.getBuildTrace = function () {
|
Build.prototype.getBuildTrace = function () {
|
||||||
return $.ajax({
|
return $.ajax({
|
||||||
url: `${this.pageUrl}/trace.json`,
|
url: `${this.pageUrl}/trace.json`,
|
||||||
dataType: 'json',
|
data: this.state,
|
||||||
data: {
|
})
|
||||||
state: this.state,
|
.done((log) => {
|
||||||
},
|
|
||||||
success: ((log) => {
|
|
||||||
const $buildContainer = $('.js-build-output');
|
|
||||||
|
|
||||||
gl.utils.setCiStatusFavicon(`${this.pageUrl}/status.json`);
|
gl.utils.setCiStatusFavicon(`${this.pageUrl}/status.json`);
|
||||||
|
|
||||||
if (log.state) {
|
if (log.state) {
|
||||||
this.state = log.state;
|
this.state = log.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.windowSize = this.$buildTraceOutput.height();
|
||||||
|
|
||||||
if (log.append) {
|
if (log.append) {
|
||||||
$buildContainer.append(log.html);
|
this.$buildTraceOutput.append(log.html);
|
||||||
this.logBytes += log.size;
|
this.logBytes += log.size;
|
||||||
} else {
|
} else {
|
||||||
$buildContainer.html(log.html);
|
this.$buildTraceOutput.html(log.html);
|
||||||
this.logBytes = log.size;
|
this.logBytes = log.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,157 +192,62 @@ window.Build = (function () {
|
||||||
const size = bytesToKiB(this.logBytes);
|
const size = bytesToKiB(this.logBytes);
|
||||||
$('.js-truncated-info-size').html(`${size}`);
|
$('.js-truncated-info-size').html(`${size}`);
|
||||||
this.$truncatedInfo.removeClass('hidden');
|
this.$truncatedInfo.removeClass('hidden');
|
||||||
this.initAffixTruncatedInfo();
|
|
||||||
} else {
|
} else {
|
||||||
this.$truncatedInfo.addClass('hidden');
|
this.$truncatedInfo.addClass('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkAutoscroll();
|
|
||||||
|
|
||||||
if (!log.complete) {
|
if (!log.complete) {
|
||||||
|
if (!this.hasBeenScrolled) {
|
||||||
|
this.toggleScrollAnimation(true);
|
||||||
|
} else {
|
||||||
|
this.toggleScrollAnimation(false);
|
||||||
|
}
|
||||||
|
|
||||||
Build.timeout = setTimeout(() => {
|
Build.timeout = setTimeout(() => {
|
||||||
this.invokeBuildTrace();
|
this.getBuildTrace();
|
||||||
}, 4000);
|
}, 4000);
|
||||||
} else {
|
} else {
|
||||||
this.$buildRefreshAnimation.remove();
|
this.$buildRefreshAnimation.remove();
|
||||||
|
this.toggleScrollAnimation(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log.status !== this.buildStatus) {
|
if (log.status !== this.buildStatus) {
|
||||||
let pageUrl = this.pageUrl;
|
gl.utils.visitUrl(this.pageUrl);
|
||||||
|
|
||||||
if (this.$autoScrollStatus.data('state') === 'enabled') {
|
|
||||||
pageUrl += DOWN_BUILD_TRACE;
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
gl.utils.visitUrl(pageUrl);
|
.fail(() => {
|
||||||
}
|
|
||||||
}),
|
|
||||||
error: () => {
|
|
||||||
this.$buildRefreshAnimation.remove();
|
this.$buildRefreshAnimation.remove();
|
||||||
return this.initScrollMonitor();
|
})
|
||||||
},
|
.then(() => {
|
||||||
});
|
if (!this.hasBeenScrolled) {
|
||||||
};
|
this.scrollDown();
|
||||||
|
|
||||||
Build.prototype.checkAutoscroll = function () {
|
|
||||||
if (this.$autoScrollStatus.data('state') === 'enabled') {
|
|
||||||
return $('html,body').scrollTop(this.$buildTrace.height());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle a situation where user started new build
|
|
||||||
// but never scrolled a page
|
|
||||||
if (!this.$scrollTopBtn.is(':visible') &&
|
|
||||||
!this.$scrollBottomBtn.is(':visible') &&
|
|
||||||
!gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
|
||||||
this.$scrollBottomBtn.show();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Build.prototype.initScrollButtonAffix = function () {
|
|
||||||
// Hide everything initially
|
|
||||||
this.$scrollTopBtn.hide();
|
|
||||||
this.$scrollBottomBtn.hide();
|
|
||||||
this.$autoScrollContainer.hide();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Page scroll listener to detect if user has scrolling page
|
|
||||||
// and handle following cases
|
|
||||||
// 1) User is at Top of Build Log;
|
|
||||||
// - Hide Top Arrow button
|
|
||||||
// - Show Bottom Arrow button
|
|
||||||
// - Disable Autoscroll and hide indicator (when build is running)
|
|
||||||
// 2) User is at Bottom of Build Log;
|
|
||||||
// - Show Top Arrow button
|
|
||||||
// - Hide Bottom Arrow button
|
|
||||||
// - Enable Autoscroll and show indicator (when build is running)
|
|
||||||
// 3) User is somewhere in middle of Build Log;
|
|
||||||
// - Show Top Arrow button
|
|
||||||
// - Show Bottom Arrow button
|
|
||||||
// - Disable Autoscroll and hide indicator (when build is running)
|
|
||||||
Build.prototype.initScrollMonitor = function () {
|
|
||||||
if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) &&
|
|
||||||
!gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
|
||||||
// User is somewhere in middle of Build Log
|
|
||||||
|
|
||||||
this.$scrollTopBtn.show();
|
|
||||||
|
|
||||||
if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed
|
|
||||||
this.$scrollBottomBtn.show();
|
|
||||||
} else if (this.$buildRefreshAnimation.is(':visible') &&
|
|
||||||
!gl.utils.isInViewport(this.$buildRefreshAnimation.get(0))) {
|
|
||||||
this.$scrollBottomBtn.show();
|
|
||||||
} else {
|
|
||||||
this.$scrollBottomBtn.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide Autoscroll Status Indicator
|
|
||||||
if (this.$scrollBottomBtn.is(':visible')) {
|
|
||||||
this.$autoScrollContainer.hide();
|
|
||||||
this.$autoScrollStatusText.removeClass('animate');
|
|
||||||
} else {
|
|
||||||
this.$autoScrollContainer.css({
|
|
||||||
top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET,
|
|
||||||
}).show();
|
|
||||||
this.$autoScrollStatusText.addClass('animate');
|
|
||||||
}
|
|
||||||
} else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) &&
|
|
||||||
!gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
|
||||||
// User is at Top of Build Log
|
|
||||||
|
|
||||||
this.$scrollTopBtn.hide();
|
|
||||||
this.$scrollBottomBtn.show();
|
|
||||||
|
|
||||||
this.$autoScrollContainer.hide();
|
|
||||||
this.$autoScrollStatusText.removeClass('animate');
|
|
||||||
} else if ((!gl.utils.isInViewport(this.$upBuildTrace.get(0)) &&
|
|
||||||
gl.utils.isInViewport(this.$downBuildTrace.get(0))) ||
|
|
||||||
(this.$buildRefreshAnimation.is(':visible') &&
|
|
||||||
gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) {
|
|
||||||
// User is at Bottom of Build Log
|
|
||||||
|
|
||||||
this.$scrollTopBtn.show();
|
|
||||||
this.$scrollBottomBtn.hide();
|
|
||||||
|
|
||||||
// Show and Reposition Autoscroll Status Indicator
|
|
||||||
this.$autoScrollContainer.css({
|
|
||||||
top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET,
|
|
||||||
}).show();
|
|
||||||
this.$autoScrollStatusText.addClass('animate');
|
|
||||||
} else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) &&
|
|
||||||
gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
|
|
||||||
// Build Log height is small
|
|
||||||
|
|
||||||
this.$scrollTopBtn.hide();
|
|
||||||
this.$scrollBottomBtn.hide();
|
|
||||||
|
|
||||||
// Hide Autoscroll Status Indicator
|
|
||||||
this.$autoScrollContainer.hide();
|
|
||||||
this.$autoScrollStatusText.removeClass('animate');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.buildStatus === 'running' || this.buildStatus === 'pending') {
|
|
||||||
// Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise.
|
|
||||||
this.$autoScrollStatus.data(
|
|
||||||
'state',
|
|
||||||
gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)) ? 'enabled' : 'disabled',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.then(() => this.toggleScroll());
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.shouldHideSidebarForViewport = function () {
|
Build.prototype.shouldHideSidebarForViewport = function () {
|
||||||
const bootstrapBreakpoint = this.bp.getBreakpointSize();
|
const bootstrapBreakpoint = bp.getBreakpointSize();
|
||||||
return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
|
return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.toggleSidebar = function (shouldHide) {
|
Build.prototype.toggleSidebar = function (shouldHide) {
|
||||||
const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
|
const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
|
||||||
|
const $toggleButton = $('.js-sidebar-build-toggle-header');
|
||||||
|
|
||||||
this.$buildScroll.toggleClass('sidebar-expanded', shouldShow)
|
this.$sidebar
|
||||||
.toggleClass('sidebar-collapsed', shouldHide);
|
.toggleClass('right-sidebar-expanded', shouldShow)
|
||||||
this.$truncatedInfo.toggleClass('sidebar-expanded', shouldShow)
|
|
||||||
.toggleClass('sidebar-collapsed', shouldHide);
|
|
||||||
this.$sidebar.toggleClass('right-sidebar-expanded', shouldShow)
|
|
||||||
.toggleClass('right-sidebar-collapsed', shouldHide);
|
.toggleClass('right-sidebar-collapsed', shouldHide);
|
||||||
|
|
||||||
|
this.$topBar
|
||||||
|
.toggleClass('sidebar-expanded', shouldShow)
|
||||||
|
.toggleClass('sidebar-collapsed', shouldHide);
|
||||||
|
|
||||||
|
if (this.$sidebar.hasClass('right-sidebar-expanded')) {
|
||||||
|
$toggleButton.addClass('hidden');
|
||||||
|
} else {
|
||||||
|
$toggleButton.removeClass('hidden');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.sidebarOnResize = function () {
|
Build.prototype.sidebarOnResize = function () {
|
||||||
|
@ -301,24 +284,5 @@ window.Build = (function () {
|
||||||
this.populateJobs(stage);
|
this.populateJobs(stage);
|
||||||
};
|
};
|
||||||
|
|
||||||
Build.prototype.stepTrace = function (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const $currentTarget = $(e.currentTarget);
|
|
||||||
$.scrollTo($currentTarget.attr('href'), {
|
|
||||||
offset: 0,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Build.prototype.initAffixTruncatedInfo = function () {
|
|
||||||
const offsetTop = this.$buildTrace.offset().top;
|
|
||||||
|
|
||||||
this.$truncatedInfo.affix({
|
|
||||||
offset: {
|
|
||||||
top: offsetTop,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return Build;
|
return Build;
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
$('.reveal-variables').off('click').on('click', function() {
|
$('.reveal-variables').off('click').on('click', function() {
|
||||||
$('.js-build').toggle().niceScroll();
|
$('.js-build-variables').toggle();
|
||||||
$(this).hide();
|
$(this).hide();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
97
app/assets/javascripts/close_reopen_report_toggle.js
Normal file
97
app/assets/javascripts/close_reopen_report_toggle.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import DropLab from './droplab/drop_lab';
|
||||||
|
import ISetter from './droplab/plugins/input_setter';
|
||||||
|
|
||||||
|
// Todo: Remove this when fixing issue in input_setter plugin
|
||||||
|
const InputSetter = Object.assign({}, ISetter);
|
||||||
|
|
||||||
|
class CloseReopenReportToggle {
|
||||||
|
constructor(opts = {}) {
|
||||||
|
this.dropdownTrigger = opts.dropdownTrigger;
|
||||||
|
this.dropdownList = opts.dropdownList;
|
||||||
|
this.button = opts.button;
|
||||||
|
}
|
||||||
|
|
||||||
|
initDroplab() {
|
||||||
|
this.reopenItem = this.dropdownList.querySelector('.reopen-item');
|
||||||
|
this.closeItem = this.dropdownList.querySelector('.close-item');
|
||||||
|
|
||||||
|
this.droplab = new DropLab();
|
||||||
|
|
||||||
|
const config = this.setConfig();
|
||||||
|
|
||||||
|
this.droplab.init(this.dropdownTrigger, this.dropdownList, [InputSetter], config);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateButton(isClosed) {
|
||||||
|
this.toggleButtonType(isClosed);
|
||||||
|
|
||||||
|
this.button.blur();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleButtonType(isClosed) {
|
||||||
|
const [showItem, hideItem] = this.getButtonTypes(isClosed);
|
||||||
|
|
||||||
|
showItem.classList.remove('hidden');
|
||||||
|
showItem.classList.add('droplab-item-selected');
|
||||||
|
|
||||||
|
hideItem.classList.add('hidden');
|
||||||
|
hideItem.classList.remove('droplab-item-selected');
|
||||||
|
|
||||||
|
showItem.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
getButtonTypes(isClosed) {
|
||||||
|
return isClosed ? [this.reopenItem, this.closeItem] : [this.closeItem, this.reopenItem];
|
||||||
|
}
|
||||||
|
|
||||||
|
setDisable(shouldDisable = true) {
|
||||||
|
if (shouldDisable) {
|
||||||
|
this.button.setAttribute('disabled', 'true');
|
||||||
|
this.dropdownTrigger.setAttribute('disabled', 'true');
|
||||||
|
} else {
|
||||||
|
this.button.removeAttribute('disabled');
|
||||||
|
this.dropdownTrigger.removeAttribute('disabled');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig() {
|
||||||
|
const config = {
|
||||||
|
InputSetter: [
|
||||||
|
{
|
||||||
|
input: this.button,
|
||||||
|
valueAttribute: 'data-text',
|
||||||
|
inputAttribute: 'data-value',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: this.button,
|
||||||
|
valueAttribute: 'data-text',
|
||||||
|
inputAttribute: 'title',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: this.button,
|
||||||
|
valueAttribute: 'data-button-class',
|
||||||
|
inputAttribute: 'class',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: this.dropdownTrigger,
|
||||||
|
valueAttribute: 'data-toggle-class',
|
||||||
|
inputAttribute: 'class',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: this.button,
|
||||||
|
valueAttribute: 'data-url',
|
||||||
|
inputAttribute: 'href',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: this.button,
|
||||||
|
valueAttribute: 'data-method',
|
||||||
|
inputAttribute: 'data-method',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CloseReopenReportToggle;
|
|
@ -1,5 +1,8 @@
|
||||||
import DropLab from './droplab/drop_lab';
|
import DropLab from './droplab/drop_lab';
|
||||||
import InputSetter from './droplab/plugins/input_setter';
|
import ISetter from './droplab/plugins/input_setter';
|
||||||
|
|
||||||
|
// Todo: Remove this when fixing issue in input_setter plugin
|
||||||
|
const InputSetter = Object.assign({}, ISetter);
|
||||||
|
|
||||||
class CommentTypeToggle {
|
class CommentTypeToggle {
|
||||||
constructor(opts = {}) {
|
constructor(opts = {}) {
|
||||||
|
|
|
@ -1,29 +1,43 @@
|
||||||
/* eslint-disable no-param-reassign */
|
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VueResource from 'vue-resource';
|
import commitPipelinesTable from './pipelines_table.vue';
|
||||||
import CommitPipelinesTable from './pipelines_table';
|
|
||||||
|
|
||||||
Vue.use(VueResource);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commits View > Pipelines Tab > Pipelines Table.
|
* Used in:
|
||||||
*
|
* - Commit details View > Pipelines Tab > Pipelines Table.
|
||||||
* Renders Pipelines table in pipelines tab in the commits show view.
|
* - Merge Request details View > Pipelines Tab > Pipelines Table.
|
||||||
|
* - New Merge Request View > Pipelines Tab > Pipelines Table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// export for use in merge_request_tabs.js (TODO: remove this hack)
|
const CommitPipelinesTable = Vue.extend(commitPipelinesTable);
|
||||||
|
|
||||||
|
// export for use in merge_request_tabs.js (TODO: remove this hack when we understand how to load
|
||||||
|
// vue.js in merge_request_tabs.js)
|
||||||
window.gl = window.gl || {};
|
window.gl = window.gl || {};
|
||||||
window.gl.CommitPipelinesTable = CommitPipelinesTable;
|
window.gl.CommitPipelinesTable = CommitPipelinesTable;
|
||||||
|
|
||||||
$(() => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
gl.commits = gl.commits || {};
|
|
||||||
gl.commits.pipelines = gl.commits.pipelines || {};
|
|
||||||
|
|
||||||
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
|
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
|
||||||
|
|
||||||
if (pipelineTableViewEl && pipelineTableViewEl.dataset.disableInitialization === undefined) {
|
if (pipelineTableViewEl) {
|
||||||
gl.commits.pipelines.PipelinesTableBundle = new CommitPipelinesTable().$mount();
|
// Update MR and Commits tabs
|
||||||
pipelineTableViewEl.appendChild(gl.commits.pipelines.PipelinesTableBundle.$el);
|
pipelineTableViewEl.addEventListener('update-pipelines-count', (event) => {
|
||||||
|
if (event.detail.pipelines &&
|
||||||
|
event.detail.pipelines.count &&
|
||||||
|
event.detail.pipelines.count.all) {
|
||||||
|
const badge = document.querySelector('.js-pipelines-mr-count');
|
||||||
|
|
||||||
|
badge.textContent = event.detail.pipelines.count.all;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (pipelineTableViewEl.dataset.disableInitialization === undefined) {
|
||||||
|
const table = new CommitPipelinesTable({
|
||||||
|
propsData: {
|
||||||
|
endpoint: pipelineTableViewEl.dataset.endpoint,
|
||||||
|
helpPagePath: pipelineTableViewEl.dataset.helpPagePath,
|
||||||
|
},
|
||||||
|
}).$mount();
|
||||||
|
pipelineTableViewEl.appendChild(table.$el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,179 +0,0 @@
|
||||||
import Vue from 'vue';
|
|
||||||
import Visibility from 'visibilityjs';
|
|
||||||
import PipelinesTableComponent from '../../vue_shared/components/pipelines_table';
|
|
||||||
import PipelinesService from '../../pipelines/services/pipelines_service';
|
|
||||||
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
|
||||||
import eventHub from '../../pipelines/event_hub';
|
|
||||||
import EmptyState from '../../pipelines/components/empty_state.vue';
|
|
||||||
import ErrorState from '../../pipelines/components/error_state.vue';
|
|
||||||
import '../../lib/utils/common_utils';
|
|
||||||
import '../../vue_shared/vue_resource_interceptor';
|
|
||||||
import Poll from '../../lib/utils/poll';
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Uses `pipelines-table-component` to render Pipelines table with an API call.
|
|
||||||
* Endpoint is provided in HTML and passed as `endpoint`.
|
|
||||||
* We need a store to store the received environemnts.
|
|
||||||
* We need a service to communicate with the server.
|
|
||||||
*
|
|
||||||
* Necessary SVG in the table are provided as props. This should be refactored
|
|
||||||
* as soon as we have Webpack and can load them directly into JS files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default Vue.component('pipelines-table', {
|
|
||||||
|
|
||||||
components: {
|
|
||||||
'pipelines-table-component': PipelinesTableComponent,
|
|
||||||
'error-state': ErrorState,
|
|
||||||
'empty-state': EmptyState,
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accesses the DOM to provide the needed data.
|
|
||||||
* Returns the necessary props to render `pipelines-table-component` component.
|
|
||||||
*
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
data() {
|
|
||||||
const store = new PipelineStore();
|
|
||||||
|
|
||||||
return {
|
|
||||||
endpoint: null,
|
|
||||||
helpPagePath: null,
|
|
||||||
store,
|
|
||||||
state: store.state,
|
|
||||||
isLoading: false,
|
|
||||||
hasError: false,
|
|
||||||
isMakingRequest: false,
|
|
||||||
updateGraphDropdown: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
shouldRenderErrorState() {
|
|
||||||
return this.hasError && !this.isLoading;
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldRenderEmptyState() {
|
|
||||||
return !this.state.pipelines.length &&
|
|
||||||
!this.isLoading &&
|
|
||||||
!this.hasError;
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldRenderTable() {
|
|
||||||
return !this.isLoading &&
|
|
||||||
this.state.pipelines.length > 0 &&
|
|
||||||
!this.hasError;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When the component is about to be mounted, tell the service to fetch the data
|
|
||||||
*
|
|
||||||
* A request to fetch the pipelines will be made.
|
|
||||||
* In case of a successfull response we will store the data in the provided
|
|
||||||
* store, in case of a failed response we need to warn the user.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
beforeMount() {
|
|
||||||
const element = document.querySelector('#commit-pipeline-table-view');
|
|
||||||
|
|
||||||
this.endpoint = element.dataset.endpoint;
|
|
||||||
this.helpPagePath = element.dataset.helpPagePath;
|
|
||||||
this.service = new PipelinesService(this.endpoint);
|
|
||||||
|
|
||||||
this.poll = new Poll({
|
|
||||||
resource: this.service,
|
|
||||||
method: 'getPipelines',
|
|
||||||
successCallback: this.successCallback,
|
|
||||||
errorCallback: this.errorCallback,
|
|
||||||
notificationCallback: this.setIsMakingRequest,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!Visibility.hidden()) {
|
|
||||||
this.isLoading = true;
|
|
||||||
this.poll.makeRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
Visibility.change(() => {
|
|
||||||
if (!Visibility.hidden()) {
|
|
||||||
this.poll.restart();
|
|
||||||
} else {
|
|
||||||
this.poll.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
eventHub.$on('refreshPipelines', this.fetchPipelines);
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroyed() {
|
|
||||||
eventHub.$off('refreshPipelines');
|
|
||||||
},
|
|
||||||
|
|
||||||
destroyed() {
|
|
||||||
this.poll.stop();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
fetchPipelines() {
|
|
||||||
this.isLoading = true;
|
|
||||||
|
|
||||||
return this.service.getPipelines()
|
|
||||||
.then(response => this.successCallback(response))
|
|
||||||
.catch(() => this.errorCallback());
|
|
||||||
},
|
|
||||||
|
|
||||||
successCallback(resp) {
|
|
||||||
const response = resp.json();
|
|
||||||
|
|
||||||
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
|
||||||
const pipelines = response.pipelines || response;
|
|
||||||
this.store.storePipelines(pipelines);
|
|
||||||
this.isLoading = false;
|
|
||||||
this.updateGraphDropdown = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
errorCallback() {
|
|
||||||
this.hasError = true;
|
|
||||||
this.isLoading = false;
|
|
||||||
this.updateGraphDropdown = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
setIsMakingRequest(isMakingRequest) {
|
|
||||||
this.isMakingRequest = isMakingRequest;
|
|
||||||
|
|
||||||
if (isMakingRequest) {
|
|
||||||
this.updateGraphDropdown = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
template: `
|
|
||||||
<div class="content-list pipelines">
|
|
||||||
<div
|
|
||||||
class="realtime-loading"
|
|
||||||
v-if="isLoading">
|
|
||||||
<i
|
|
||||||
class="fa fa-spinner fa-spin"
|
|
||||||
aria-hidden="true" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<empty-state
|
|
||||||
v-if="shouldRenderEmptyState"
|
|
||||||
:help-page-path="helpPagePath" />
|
|
||||||
|
|
||||||
<error-state v-if="shouldRenderErrorState" />
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="table-holder"
|
|
||||||
v-if="shouldRenderTable">
|
|
||||||
<pipelines-table-component
|
|
||||||
:pipelines="state.pipelines"
|
|
||||||
:service="service"
|
|
||||||
:update-graph-dropdown="updateGraphDropdown"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`,
|
|
||||||
});
|
|
101
app/assets/javascripts/commit/pipelines/pipelines_table.vue
Normal file
101
app/assets/javascripts/commit/pipelines/pipelines_table.vue
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
<script>
|
||||||
|
import PipelinesService from '../../pipelines/services/pipelines_service';
|
||||||
|
import PipelineStore from '../../pipelines/stores/pipelines_store';
|
||||||
|
import pipelinesMixin from '../../pipelines/mixins/pipelines';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
endpoint: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
helpPagePath: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mixins: [
|
||||||
|
pipelinesMixin,
|
||||||
|
],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
const store = new PipelineStore();
|
||||||
|
|
||||||
|
return {
|
||||||
|
store,
|
||||||
|
state: store.state,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
/**
|
||||||
|
* Empty state is only rendered if after the first request we receive no pipelines.
|
||||||
|
*
|
||||||
|
* @return {Boolean}
|
||||||
|
*/
|
||||||
|
shouldRenderEmptyState() {
|
||||||
|
return !this.state.pipelines.length &&
|
||||||
|
!this.isLoading &&
|
||||||
|
this.hasMadeRequest &&
|
||||||
|
!this.hasError;
|
||||||
|
},
|
||||||
|
|
||||||
|
shouldRenderTable() {
|
||||||
|
return !this.isLoading &&
|
||||||
|
this.state.pipelines.length > 0 &&
|
||||||
|
!this.hasError;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.service = new PipelinesService(this.endpoint);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
successCallback(resp) {
|
||||||
|
return resp.json().then((response) => {
|
||||||
|
// depending of the endpoint the response can either bring a `pipelines` key or not.
|
||||||
|
const pipelines = response.pipelines || response;
|
||||||
|
this.setCommonData(pipelines);
|
||||||
|
|
||||||
|
const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
|
||||||
|
detail: {
|
||||||
|
pipelines: response,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// notifiy to update the count in tabs
|
||||||
|
if (this.$el.parentElement) {
|
||||||
|
this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="content-list pipelines">
|
||||||
|
|
||||||
|
<loading-icon
|
||||||
|
label="Loading pipelines"
|
||||||
|
size="3"
|
||||||
|
v-if="isLoading"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<empty-state
|
||||||
|
v-if="shouldRenderEmptyState"
|
||||||
|
:help-page-path="helpPagePath"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<error-state
|
||||||
|
v-if="shouldRenderErrorState"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="table-holder"
|
||||||
|
v-if="shouldRenderTable">
|
||||||
|
<pipelines-table-component
|
||||||
|
:pipelines="state.pipelines"
|
||||||
|
:update-graph-dropdown="updateGraphDropdown"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -7,6 +7,8 @@ window.CommitsList = (function() {
|
||||||
CommitsList.timer = null;
|
CommitsList.timer = null;
|
||||||
|
|
||||||
CommitsList.init = function(limit) {
|
CommitsList.init = function(limit) {
|
||||||
|
this.$contentList = $('.content_list');
|
||||||
|
|
||||||
$("body").on("click", ".day-commits-table li.commit", function(e) {
|
$("body").on("click", ".day-commits-table li.commit", function(e) {
|
||||||
if (e.target.nodeName !== "A") {
|
if (e.target.nodeName !== "A") {
|
||||||
location.href = $(this).attr("url");
|
location.href = $(this).attr("url");
|
||||||
|
@ -14,9 +16,9 @@ window.CommitsList = (function() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Pager.init(limit, false, false, function() {
|
|
||||||
gl.utils.localTimeAgo($('.js-timeago'));
|
Pager.init(parseInt(limit, 10), false, false, this.processCommits);
|
||||||
});
|
|
||||||
this.content = $("#commits-list");
|
this.content = $("#commits-list");
|
||||||
this.searchField = $("#commits-search");
|
this.searchField = $("#commits-search");
|
||||||
this.lastSearch = this.searchField.val();
|
this.lastSearch = this.searchField.val();
|
||||||
|
@ -62,5 +64,34 @@ window.CommitsList = (function() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Prepare loaded data.
|
||||||
|
CommitsList.processCommits = (data) => {
|
||||||
|
let processedData = data;
|
||||||
|
const $processedData = $(processedData);
|
||||||
|
const $commitsHeadersLast = CommitsList.$contentList.find('li.js-commit-header').last();
|
||||||
|
const lastShownDay = $commitsHeadersLast.data('day');
|
||||||
|
const $loadedCommitsHeadersFirst = $processedData.filter('li.js-commit-header').first();
|
||||||
|
const loadedShownDayFirst = $loadedCommitsHeadersFirst.data('day');
|
||||||
|
let commitsCount;
|
||||||
|
|
||||||
|
// If commits headers show the same date,
|
||||||
|
// remove the last header and change the previous one.
|
||||||
|
if (lastShownDay === loadedShownDayFirst) {
|
||||||
|
// Last shown commits count under the last commits header.
|
||||||
|
commitsCount = $commitsHeadersLast.nextUntil('li.js-commit-header').find('li.commit').length;
|
||||||
|
|
||||||
|
// Remove duplicate of commits header.
|
||||||
|
processedData = $processedData.not(`li.js-commit-header[data-day="${loadedShownDayFirst}"]`);
|
||||||
|
|
||||||
|
// Update commits count in the previous commits header.
|
||||||
|
commitsCount += Number($(processedData).nextUntil('li.js-commit-header').first().find('li.commit').length);
|
||||||
|
$commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${gl.text.pluralize('commit', commitsCount)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.utils.localTimeAgo($processedData.find('.js-timeago'));
|
||||||
|
|
||||||
|
return processedData;
|
||||||
|
};
|
||||||
|
|
||||||
return CommitsList;
|
return CommitsList;
|
||||||
})();
|
})();
|
||||||
|
|
2
app/assets/javascripts/commons/bootstrap.js
vendored
2
app/assets/javascripts/commons/bootstrap.js
vendored
|
@ -3,11 +3,13 @@ import $ from 'jquery';
|
||||||
// bootstrap jQuery plugins
|
// bootstrap jQuery plugins
|
||||||
import 'bootstrap-sass/assets/javascripts/bootstrap/affix';
|
import 'bootstrap-sass/assets/javascripts/bootstrap/affix';
|
||||||
import 'bootstrap-sass/assets/javascripts/bootstrap/alert';
|
import 'bootstrap-sass/assets/javascripts/bootstrap/alert';
|
||||||
|
import 'bootstrap-sass/assets/javascripts/bootstrap/button';
|
||||||
import 'bootstrap-sass/assets/javascripts/bootstrap/dropdown';
|
import 'bootstrap-sass/assets/javascripts/bootstrap/dropdown';
|
||||||
import 'bootstrap-sass/assets/javascripts/bootstrap/modal';
|
import 'bootstrap-sass/assets/javascripts/bootstrap/modal';
|
||||||
import 'bootstrap-sass/assets/javascripts/bootstrap/tab';
|
import 'bootstrap-sass/assets/javascripts/bootstrap/tab';
|
||||||
import 'bootstrap-sass/assets/javascripts/bootstrap/transition';
|
import 'bootstrap-sass/assets/javascripts/bootstrap/transition';
|
||||||
import 'bootstrap-sass/assets/javascripts/bootstrap/tooltip';
|
import 'bootstrap-sass/assets/javascripts/bootstrap/tooltip';
|
||||||
|
import 'bootstrap-sass/assets/javascripts/bootstrap/popover';
|
||||||
|
|
||||||
// custom jQuery functions
|
// custom jQuery functions
|
||||||
$.fn.extend({
|
$.fn.extend({
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'underscore';
|
||||||
import './polyfills';
|
import './polyfills';
|
||||||
import './jquery';
|
import './jquery';
|
||||||
import './bootstrap';
|
import './bootstrap';
|
||||||
|
|
1
app/assets/javascripts/commons/jquery.js
vendored
1
app/assets/javascripts/commons/jquery.js
vendored
|
@ -6,6 +6,5 @@ import 'vendor/jquery.endless-scroll';
|
||||||
import 'vendor/jquery.caret';
|
import 'vendor/jquery.caret';
|
||||||
import 'vendor/jquery.atwho';
|
import 'vendor/jquery.atwho';
|
||||||
import 'vendor/jquery.scrollTo';
|
import 'vendor/jquery.scrollTo';
|
||||||
import 'vendor/jquery.nicescroll';
|
|
||||||
import 'vendor/jquery.waitforimages';
|
import 'vendor/jquery.waitforimages';
|
||||||
import 'select2/select2';
|
import 'select2/select2';
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// ECMAScript polyfills
|
// ECMAScript polyfills
|
||||||
import 'core-js/fn/array/find';
|
import 'core-js/fn/array/find';
|
||||||
|
import 'core-js/fn/array/find-index';
|
||||||
import 'core-js/fn/array/from';
|
import 'core-js/fn/array/from';
|
||||||
import 'core-js/fn/array/includes';
|
import 'core-js/fn/array/includes';
|
||||||
import 'core-js/fn/object/assign';
|
import 'core-js/fn/object/assign';
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, no-restricted-syntax, guard-for-in, no-continue */
|
/* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, no-restricted-syntax, guard-for-in, no-continue */
|
||||||
|
import _ from 'underscore';
|
||||||
require('./lib/utils/common_utils');
|
import './lib/utils/common_utils';
|
||||||
|
import { placeholderImage } from './lazy_loader';
|
||||||
|
|
||||||
const gfmRules = {
|
const gfmRules = {
|
||||||
// The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb convert
|
// The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb convert
|
||||||
|
@ -18,12 +19,12 @@ const gfmRules = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TaskListFilter: {
|
TaskListFilter: {
|
||||||
'input[type=checkbox].task-list-item-checkbox'(el, text) {
|
'input[type=checkbox].task-list-item-checkbox'(el) {
|
||||||
return `[${el.checked ? 'x' : ' '}]`;
|
return `[${el.checked ? 'x' : ' '}]`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ReferenceFilter: {
|
ReferenceFilter: {
|
||||||
'.tooltip'(el, text) {
|
'.tooltip'(el) {
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
'a.gfm:not([data-link=true])'(el, text) {
|
'a.gfm:not([data-link=true])'(el, text) {
|
||||||
|
@ -39,15 +40,15 @@ const gfmRules = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TableOfContentsFilter: {
|
TableOfContentsFilter: {
|
||||||
'ul.section-nav'(el, text) {
|
'ul.section-nav'(el) {
|
||||||
return '[[_TOC_]]';
|
return '[[_TOC_]]';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EmojiFilter: {
|
EmojiFilter: {
|
||||||
'img.emoji'(el, text) {
|
'img.emoji'(el) {
|
||||||
return el.getAttribute('alt');
|
return el.getAttribute('alt');
|
||||||
},
|
},
|
||||||
'gl-emoji'(el, text) {
|
'gl-emoji'(el) {
|
||||||
return `:${el.getAttribute('data-name')}:`;
|
return `:${el.getAttribute('data-name')}:`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -56,14 +57,19 @@ const gfmRules = {
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ImageLazyLoadFilter: {
|
||||||
|
'img'(el, text) {
|
||||||
|
return `![${el.getAttribute('alt')}](${el.getAttribute('src')})`;
|
||||||
|
},
|
||||||
|
},
|
||||||
VideoLinkFilter: {
|
VideoLinkFilter: {
|
||||||
'.video-container'(el, text) {
|
'.video-container'(el) {
|
||||||
const videoEl = el.querySelector('video');
|
const videoEl = el.querySelector('video');
|
||||||
if (!videoEl) return false;
|
if (!videoEl) return false;
|
||||||
|
|
||||||
return CopyAsGFM.nodeToGFM(videoEl);
|
return CopyAsGFM.nodeToGFM(videoEl);
|
||||||
},
|
},
|
||||||
'video'(el, text) {
|
'video'(el) {
|
||||||
return `![${el.dataset.title}](${el.getAttribute('src')})`;
|
return `![${el.dataset.title}](${el.getAttribute('src')})`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -74,19 +80,19 @@ const gfmRules = {
|
||||||
'code.code.math[data-math-style=inline]'(el, text) {
|
'code.code.math[data-math-style=inline]'(el, text) {
|
||||||
return `$\`${text}\`$`;
|
return `$\`${text}\`$`;
|
||||||
},
|
},
|
||||||
'span.katex-display span.katex-mathml'(el, text) {
|
'span.katex-display span.katex-mathml'(el) {
|
||||||
const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
|
const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
|
||||||
if (!mathAnnotation) return false;
|
if (!mathAnnotation) return false;
|
||||||
|
|
||||||
return `\`\`\`math\n${CopyAsGFM.nodeToGFM(mathAnnotation)}\n\`\`\``;
|
return `\`\`\`math\n${CopyAsGFM.nodeToGFM(mathAnnotation)}\n\`\`\``;
|
||||||
},
|
},
|
||||||
'span.katex-mathml'(el, text) {
|
'span.katex-mathml'(el) {
|
||||||
const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
|
const mathAnnotation = el.querySelector('annotation[encoding="application/x-tex"]');
|
||||||
if (!mathAnnotation) return false;
|
if (!mathAnnotation) return false;
|
||||||
|
|
||||||
return `$\`${CopyAsGFM.nodeToGFM(mathAnnotation)}\`$`;
|
return `$\`${CopyAsGFM.nodeToGFM(mathAnnotation)}\`$`;
|
||||||
},
|
},
|
||||||
'span.katex-html'(el, text) {
|
'span.katex-html'(el) {
|
||||||
// We don't want to include the content of this element in the copied text.
|
// We don't want to include the content of this element in the copied text.
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
|
@ -95,7 +101,7 @@ const gfmRules = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
SanitizationFilter: {
|
SanitizationFilter: {
|
||||||
'a[name]:not([href]):empty'(el, text) {
|
'a[name]:not([href]):empty'(el) {
|
||||||
return el.outerHTML;
|
return el.outerHTML;
|
||||||
},
|
},
|
||||||
'dl'(el, text) {
|
'dl'(el, text) {
|
||||||
|
@ -143,7 +149,7 @@ const gfmRules = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MarkdownFilter: {
|
MarkdownFilter: {
|
||||||
'br'(el, text) {
|
'br'(el) {
|
||||||
// Two spaces at the end of a line are turned into a BR
|
// Two spaces at the end of a line are turned into a BR
|
||||||
return ' ';
|
return ' ';
|
||||||
},
|
},
|
||||||
|
@ -162,8 +168,10 @@ const gfmRules = {
|
||||||
'blockquote'(el, text) {
|
'blockquote'(el, text) {
|
||||||
return text.trim().split('\n').map(s => `> ${s}`.trim()).join('\n');
|
return text.trim().split('\n').map(s => `> ${s}`.trim()).join('\n');
|
||||||
},
|
},
|
||||||
'img'(el, text) {
|
'img'(el) {
|
||||||
return `![${el.getAttribute('alt')}](${el.getAttribute('src')})`;
|
const imageSrc = el.src;
|
||||||
|
const imageUrl = imageSrc && imageSrc !== placeholderImage ? imageSrc : (el.dataset.src || '');
|
||||||
|
return `![${el.getAttribute('alt')}](${imageUrl})`;
|
||||||
},
|
},
|
||||||
'a.anchor'(el, text) {
|
'a.anchor'(el, text) {
|
||||||
// Don't render a Markdown link for the anchor link inside a heading
|
// Don't render a Markdown link for the anchor link inside a heading
|
||||||
|
@ -222,10 +230,10 @@ const gfmRules = {
|
||||||
'sup'(el, text) {
|
'sup'(el, text) {
|
||||||
return `^${text}`;
|
return `^${text}`;
|
||||||
},
|
},
|
||||||
'hr'(el, text) {
|
'hr'(el) {
|
||||||
return '-----';
|
return '-----';
|
||||||
},
|
},
|
||||||
'table'(el, text) {
|
'table'(el) {
|
||||||
const theadEl = el.querySelector('thead');
|
const theadEl = el.querySelector('thead');
|
||||||
const tbodyEl = el.querySelector('tbody');
|
const tbodyEl = el.querySelector('tbody');
|
||||||
if (!theadEl || !tbodyEl) return false;
|
if (!theadEl || !tbodyEl) return false;
|
||||||
|
@ -233,11 +241,11 @@ const gfmRules = {
|
||||||
const theadText = CopyAsGFM.nodeToGFM(theadEl);
|
const theadText = CopyAsGFM.nodeToGFM(theadEl);
|
||||||
const tbodyText = CopyAsGFM.nodeToGFM(tbodyEl);
|
const tbodyText = CopyAsGFM.nodeToGFM(tbodyEl);
|
||||||
|
|
||||||
return theadText + tbodyText;
|
return [theadText, tbodyText].join('\n');
|
||||||
},
|
},
|
||||||
'thead'(el, text) {
|
'thead'(el, text) {
|
||||||
const cells = _.map(el.querySelectorAll('th'), (cell) => {
|
const cells = _.map(el.querySelectorAll('th'), (cell) => {
|
||||||
let chars = CopyAsGFM.nodeToGFM(cell).trim().length + 2;
|
let chars = CopyAsGFM.nodeToGFM(cell).length + 2;
|
||||||
|
|
||||||
let before = '';
|
let before = '';
|
||||||
let after = '';
|
let after = '';
|
||||||
|
@ -262,10 +270,15 @@ const gfmRules = {
|
||||||
return before + middle + after;
|
return before + middle + after;
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${text}|${cells.join('|')}|`;
|
const separatorRow = `|${cells.join('|')}|`;
|
||||||
|
|
||||||
|
return [text, separatorRow].join('\n');
|
||||||
},
|
},
|
||||||
'tr'(el, text) {
|
'tr'(el) {
|
||||||
const cells = _.map(el.querySelectorAll('td, th'), cell => CopyAsGFM.nodeToGFM(cell).trim());
|
const cellEls = el.querySelectorAll('td, th');
|
||||||
|
if (cellEls.length === 0) return false;
|
||||||
|
|
||||||
|
const cells = _.map(cellEls, cell => CopyAsGFM.nodeToGFM(cell));
|
||||||
return `| ${cells.join(' | ')} |`;
|
return `| ${cells.join(' | ')} |`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -273,12 +286,12 @@ const gfmRules = {
|
||||||
|
|
||||||
class CopyAsGFM {
|
class CopyAsGFM {
|
||||||
constructor() {
|
constructor() {
|
||||||
$(document).on('copy', '.md, .wiki', (e) => { this.copyAsGFM(e, CopyAsGFM.transformGFMSelection); });
|
$(document).on('copy', '.md, .wiki', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection); });
|
||||||
$(document).on('copy', 'pre.code.highlight, .diff-content .line_content', (e) => { this.copyAsGFM(e, CopyAsGFM.transformCodeSelection); });
|
$(document).on('copy', 'pre.code.highlight, .diff-content .line_content', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformCodeSelection); });
|
||||||
$(document).on('paste', '.js-gfm-input', this.pasteGFM.bind(this));
|
$(document).on('paste', '.js-gfm-input', CopyAsGFM.pasteGFM);
|
||||||
}
|
}
|
||||||
|
|
||||||
copyAsGFM(e, transformer) {
|
static copyAsGFM(e, transformer) {
|
||||||
const clipboardData = e.originalEvent.clipboardData;
|
const clipboardData = e.originalEvent.clipboardData;
|
||||||
if (!clipboardData) return;
|
if (!clipboardData) return;
|
||||||
|
|
||||||
|
@ -292,27 +305,60 @@ class CopyAsGFM {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
clipboardData.setData('text/plain', el.textContent);
|
clipboardData.setData('text/plain', el.textContent);
|
||||||
clipboardData.setData('text/x-gfm', CopyAsGFM.nodeToGFM(el));
|
clipboardData.setData('text/x-gfm', this.nodeToGFM(el));
|
||||||
}
|
}
|
||||||
|
|
||||||
pasteGFM(e) {
|
static pasteGFM(e) {
|
||||||
const clipboardData = e.originalEvent.clipboardData;
|
const clipboardData = e.originalEvent.clipboardData;
|
||||||
if (!clipboardData) return;
|
if (!clipboardData) return;
|
||||||
|
|
||||||
|
const text = clipboardData.getData('text/plain');
|
||||||
const gfm = clipboardData.getData('text/x-gfm');
|
const gfm = clipboardData.getData('text/x-gfm');
|
||||||
if (!gfm) return;
|
if (!gfm) return;
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
window.gl.utils.insertText(e.target, gfm);
|
window.gl.utils.insertText(e.target, (textBefore, textAfter) => {
|
||||||
|
// If the text before the cursor contains an odd number of backticks,
|
||||||
|
// we are either inside an inline code span that starts with 1 backtick
|
||||||
|
// or a code block that starts with 3 backticks.
|
||||||
|
// This logic still holds when there are one or more _closed_ code spans
|
||||||
|
// or blocks that will have 2 or 6 backticks.
|
||||||
|
// This will break down when the actual code block contains an uneven
|
||||||
|
// number of backticks, but this is a rare edge case.
|
||||||
|
const backtickMatch = textBefore.match(/`/g);
|
||||||
|
const insideCodeBlock = backtickMatch && (backtickMatch.length % 2) === 1;
|
||||||
|
|
||||||
|
if (insideCodeBlock) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gfm;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static transformGFMSelection(documentFragment) {
|
static transformGFMSelection(documentFragment) {
|
||||||
// If the documentFragment contains more than just Markdown, don't copy as GFM.
|
const gfmEls = documentFragment.querySelectorAll('.md, .wiki');
|
||||||
if (documentFragment.querySelector('.md, .wiki')) return null;
|
switch (gfmEls.length) {
|
||||||
|
case 0: {
|
||||||
return documentFragment;
|
return documentFragment;
|
||||||
}
|
}
|
||||||
|
case 1: {
|
||||||
|
return gfmEls[0];
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
const allGfmEl = document.createElement('div');
|
||||||
|
|
||||||
|
for (let i = 0; i < gfmEls.length; i += 1) {
|
||||||
|
const lineEl = gfmEls[i];
|
||||||
|
allGfmEl.appendChild(lineEl);
|
||||||
|
allGfmEl.appendChild(document.createTextNode('\n\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return allGfmEl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static transformCodeSelection(documentFragment) {
|
static transformCodeSelection(documentFragment) {
|
||||||
const lineEls = documentFragment.querySelectorAll('.line');
|
const lineEls = documentFragment.querySelectorAll('.line');
|
||||||
|
@ -343,7 +389,7 @@ class CopyAsGFM {
|
||||||
return codeEl;
|
return codeEl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nodeToGFM(node) {
|
static nodeToGFM(node, respectWhitespaceParam = false) {
|
||||||
if (node.nodeType === Node.COMMENT_NODE) {
|
if (node.nodeType === Node.COMMENT_NODE) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -352,7 +398,9 @@ class CopyAsGFM {
|
||||||
return node.textContent;
|
return node.textContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = this.innerGFM(node);
|
const respectWhitespace = respectWhitespaceParam || (node.nodeName === 'PRE' || node.nodeName === 'CODE');
|
||||||
|
|
||||||
|
const text = this.innerGFM(node, respectWhitespace);
|
||||||
|
|
||||||
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
||||||
return text;
|
return text;
|
||||||
|
@ -366,7 +414,17 @@ class CopyAsGFM {
|
||||||
|
|
||||||
if (!window.gl.utils.nodeMatchesSelector(node, selector)) continue;
|
if (!window.gl.utils.nodeMatchesSelector(node, selector)) continue;
|
||||||
|
|
||||||
const result = func(node, text);
|
let result;
|
||||||
|
if (func.length === 2) {
|
||||||
|
// if `func` takes 2 arguments, it depends on text.
|
||||||
|
// if there is no text, we don't need to generate GFM for this node.
|
||||||
|
if (text.length === 0) continue;
|
||||||
|
|
||||||
|
result = func(node, text);
|
||||||
|
} else {
|
||||||
|
result = func(node);
|
||||||
|
}
|
||||||
|
|
||||||
if (result === false) continue;
|
if (result === false) continue;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -376,7 +434,7 @@ class CopyAsGFM {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
static innerGFM(parentNode) {
|
static innerGFM(parentNode, respectWhitespace = false) {
|
||||||
const nodes = parentNode.childNodes;
|
const nodes = parentNode.childNodes;
|
||||||
|
|
||||||
const clonedParentNode = parentNode.cloneNode(true);
|
const clonedParentNode = parentNode.cloneNode(true);
|
||||||
|
@ -386,13 +444,19 @@ class CopyAsGFM {
|
||||||
const node = nodes[i];
|
const node = nodes[i];
|
||||||
const clonedNode = clonedNodes[i];
|
const clonedNode = clonedNodes[i];
|
||||||
|
|
||||||
const text = this.nodeToGFM(node);
|
const text = this.nodeToGFM(node, respectWhitespace);
|
||||||
|
|
||||||
// `clonedNode.replaceWith(text)` is not yet widely supported
|
// `clonedNode.replaceWith(text)` is not yet widely supported
|
||||||
clonedNode.parentNode.replaceChild(document.createTextNode(text), clonedNode);
|
clonedNode.parentNode.replaceChild(document.createTextNode(text), clonedNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clonedParentNode.innerText || clonedParentNode.textContent;
|
let nodeText = clonedParentNode.innerText || clonedParentNode.textContent;
|
||||||
|
|
||||||
|
if (!respectWhitespace) {
|
||||||
|
nodeText = nodeText.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, comma-dangle, prefer-template, quotes, no-param-reassign, wrap-iife, max-len */
|
/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, comma-dangle, prefer-template, quotes, no-param-reassign, wrap-iife, max-len */
|
||||||
/* global Api */
|
import Api from './api';
|
||||||
|
|
||||||
class CreateLabelDropdown {
|
class CreateLabelDropdown {
|
||||||
constructor ($el, namespacePath, projectPath) {
|
constructor ($el, namespacePath, projectPath) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
|
|
||||||
const global = window.gl || (window.gl = {});
|
const global = window.gl || (window.gl = {});
|
||||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||||
|
@ -10,6 +11,9 @@ global.cycleAnalytics.StageCodeComponent = Vue.extend({
|
||||||
items: Array,
|
items: Array,
|
||||||
stage: Object,
|
stage: Object,
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
userAvatarImage,
|
||||||
|
},
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<div class="events-description">
|
<div class="events-description">
|
||||||
|
@ -19,7 +23,8 @@ global.cycleAnalytics.StageCodeComponent = Vue.extend({
|
||||||
<ul class="stage-event-list">
|
<ul class="stage-event-list">
|
||||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||||
<div class="item-details">
|
<div class="item-details">
|
||||||
<img class="avatar" :src="mergeRequest.author.avatarUrl">
|
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||||
|
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||||
<h5 class="item-title merge-merquest-title">
|
<h5 class="item-title merge-merquest-title">
|
||||||
<a :href="mergeRequest.url">
|
<a :href="mergeRequest.url">
|
||||||
{{ mergeRequest.title }}
|
{{ mergeRequest.title }}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
|
|
||||||
const global = window.gl || (window.gl = {});
|
const global = window.gl || (window.gl = {});
|
||||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||||
|
@ -10,6 +10,9 @@ global.cycleAnalytics.StageIssueComponent = Vue.extend({
|
||||||
items: Array,
|
items: Array,
|
||||||
stage: Object,
|
stage: Object,
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
userAvatarImage,
|
||||||
|
},
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<div class="events-description">
|
<div class="events-description">
|
||||||
|
@ -19,7 +22,8 @@ global.cycleAnalytics.StageIssueComponent = Vue.extend({
|
||||||
<ul class="stage-event-list">
|
<ul class="stage-event-list">
|
||||||
<li v-for="issue in items" class="stage-event-item">
|
<li v-for="issue in items" class="stage-event-item">
|
||||||
<div class="item-details">
|
<div class="item-details">
|
||||||
<img class="avatar" :src="issue.author.avatarUrl">
|
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||||
|
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||||
<h5 class="item-title issue-title">
|
<h5 class="item-title issue-title">
|
||||||
<a class="issue-title" :href="issue.url">
|
<a class="issue-title" :href="issue.url">
|
||||||
{{ issue.title }}
|
{{ issue.title }}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
import iconCommit from '../svg/icon_commit.svg';
|
import iconCommit from '../svg/icon_commit.svg';
|
||||||
|
|
||||||
const global = window.gl || (window.gl = {});
|
const global = window.gl || (window.gl = {});
|
||||||
|
@ -10,11 +11,12 @@ global.cycleAnalytics.StagePlanComponent = Vue.extend({
|
||||||
items: Array,
|
items: Array,
|
||||||
stage: Object,
|
stage: Object,
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
userAvatarImage,
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return { iconCommit };
|
return { iconCommit };
|
||||||
},
|
},
|
||||||
|
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<div class="events-description">
|
<div class="events-description">
|
||||||
|
@ -24,7 +26,8 @@ global.cycleAnalytics.StagePlanComponent = Vue.extend({
|
||||||
<ul class="stage-event-list">
|
<ul class="stage-event-list">
|
||||||
<li v-for="commit in items" class="stage-event-item">
|
<li v-for="commit in items" class="stage-event-item">
|
||||||
<div class="item-details item-conmmit-component">
|
<div class="item-details item-conmmit-component">
|
||||||
<img class="avatar" :src="commit.author.avatarUrl">
|
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||||
|
<user-avatar-image :img-src="commit.author.avatarUrl"/>
|
||||||
<h5 class="item-title commit-title">
|
<h5 class="item-title commit-title">
|
||||||
<a :href="commit.commitUrl">
|
<a :href="commit.commitUrl">
|
||||||
{{ commit.title }}
|
{{ commit.title }}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
|
|
||||||
const global = window.gl || (window.gl = {});
|
const global = window.gl || (window.gl = {});
|
||||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||||
|
@ -10,6 +10,9 @@ global.cycleAnalytics.StageProductionComponent = Vue.extend({
|
||||||
items: Array,
|
items: Array,
|
||||||
stage: Object,
|
stage: Object,
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
userAvatarImage,
|
||||||
|
},
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<div class="events-description">
|
<div class="events-description">
|
||||||
|
@ -19,7 +22,8 @@ global.cycleAnalytics.StageProductionComponent = Vue.extend({
|
||||||
<ul class="stage-event-list">
|
<ul class="stage-event-list">
|
||||||
<li v-for="issue in items" class="stage-event-item">
|
<li v-for="issue in items" class="stage-event-item">
|
||||||
<div class="item-details">
|
<div class="item-details">
|
||||||
<img class="avatar" :src="issue.author.avatarUrl">
|
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||||
|
<user-avatar-image :img-src="issue.author.avatarUrl"/>
|
||||||
<h5 class="item-title issue-title">
|
<h5 class="item-title issue-title">
|
||||||
<a class="issue-title" :href="issue.url">
|
<a class="issue-title" :href="issue.url">
|
||||||
{{ issue.title }}
|
{{ issue.title }}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
|
|
||||||
const global = window.gl || (window.gl = {});
|
const global = window.gl || (window.gl = {});
|
||||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||||
|
@ -10,6 +10,9 @@ global.cycleAnalytics.StageReviewComponent = Vue.extend({
|
||||||
items: Array,
|
items: Array,
|
||||||
stage: Object,
|
stage: Object,
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
userAvatarImage,
|
||||||
|
},
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<div class="events-description">
|
<div class="events-description">
|
||||||
|
@ -19,7 +22,8 @@ global.cycleAnalytics.StageReviewComponent = Vue.extend({
|
||||||
<ul class="stage-event-list">
|
<ul class="stage-event-list">
|
||||||
<li v-for="mergeRequest in items" class="stage-event-item">
|
<li v-for="mergeRequest in items" class="stage-event-item">
|
||||||
<div class="item-details">
|
<div class="item-details">
|
||||||
<img class="avatar" :src="mergeRequest.author.avatarUrl">
|
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||||
|
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
|
||||||
<h5 class="item-title merge-merquest-title">
|
<h5 class="item-title merge-merquest-title">
|
||||||
<a :href="mergeRequest.url">
|
<a :href="mergeRequest.url">
|
||||||
{{ mergeRequest.title }}
|
{{ mergeRequest.title }}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
import iconBranch from '../svg/icon_branch.svg';
|
import iconBranch from '../svg/icon_branch.svg';
|
||||||
|
|
||||||
const global = window.gl || (window.gl = {});
|
const global = window.gl || (window.gl = {});
|
||||||
|
@ -13,6 +14,9 @@ global.cycleAnalytics.StageStagingComponent = Vue.extend({
|
||||||
data() {
|
data() {
|
||||||
return { iconBranch };
|
return { iconBranch };
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
userAvatarImage,
|
||||||
|
},
|
||||||
template: `
|
template: `
|
||||||
<div>
|
<div>
|
||||||
<div class="events-description">
|
<div class="events-description">
|
||||||
|
@ -22,13 +26,14 @@ global.cycleAnalytics.StageStagingComponent = Vue.extend({
|
||||||
<ul class="stage-event-list">
|
<ul class="stage-event-list">
|
||||||
<li v-for="build in items" class="stage-event-item item-build-component">
|
<li v-for="build in items" class="stage-event-item item-build-component">
|
||||||
<div class="item-details">
|
<div class="item-details">
|
||||||
<img class="avatar" :src="build.author.avatarUrl">
|
<!-- FIXME: Pass an alt attribute here for accessibility -->
|
||||||
|
<user-avatar-image :img-src="build.author.avatarUrl"/>
|
||||||
<h5 class="item-title">
|
<h5 class="item-title">
|
||||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||||
<i class="fa fa-code-fork"></i>
|
<i class="fa fa-code-fork"></i>
|
||||||
<a :href="build.branch.url" class="branch-name monospace">{{ build.branch.name }}</a>
|
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||||
<span class="icon-branch">${iconBranch}</span>
|
<span class="icon-branch">${iconBranch}</span>
|
||||||
<a :href="build.commitUrl" class="short-sha monospace">{{ build.shortSha }}</a>
|
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||||
</h5>
|
</h5>
|
||||||
<span>
|
<span>
|
||||||
<a :href="build.url" class="build-date">{{ build.date }}</a>
|
<a :href="build.url" class="build-date">{{ build.date }}</a>
|
||||||
|
|
|
@ -29,9 +29,9 @@ global.cycleAnalytics.StageTestComponent = Vue.extend({
|
||||||
·
|
·
|
||||||
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
|
||||||
<i class="fa fa-code-fork"></i>
|
<i class="fa fa-code-fork"></i>
|
||||||
<a :href="build.branch.url" class="branch-name monospace">{{ build.branch.name }}</a>
|
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
|
||||||
<span class="icon-branch">${iconBranch}</span>
|
<span class="icon-branch">${iconBranch}</span>
|
||||||
<a :href="build.commitUrl" class="short-sha monospace">{{ build.shortSha }}</a>
|
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
|
||||||
</h5>
|
</h5>
|
||||||
<span>
|
<span>
|
||||||
<a :href="build.url" class="issue-date">
|
<a :href="build.url" class="issue-date">
|
||||||
|
|
|
@ -4,18 +4,16 @@ import Vue from 'vue';
|
||||||
import Cookies from 'js-cookie';
|
import Cookies from 'js-cookie';
|
||||||
import Translate from '../vue_shared/translate';
|
import Translate from '../vue_shared/translate';
|
||||||
import LimitWarningComponent from './components/limit_warning_component';
|
import LimitWarningComponent from './components/limit_warning_component';
|
||||||
|
import './components/stage_code_component';
|
||||||
require('./components/stage_code_component');
|
import './components/stage_issue_component';
|
||||||
require('./components/stage_issue_component');
|
import './components/stage_plan_component';
|
||||||
require('./components/stage_plan_component');
|
import './components/stage_production_component';
|
||||||
require('./components/stage_production_component');
|
import './components/stage_review_component';
|
||||||
require('./components/stage_review_component');
|
import './components/stage_staging_component';
|
||||||
require('./components/stage_staging_component');
|
import './components/stage_test_component';
|
||||||
require('./components/stage_test_component');
|
import './components/total_time_component';
|
||||||
require('./components/total_time_component');
|
import './cycle_analytics_service';
|
||||||
require('./cycle_analytics_service');
|
import './cycle_analytics_store';
|
||||||
require('./cycle_analytics_store');
|
|
||||||
require('./default_event_objects');
|
|
||||||
|
|
||||||
Vue.use(Translate);
|
Vue.use(Translate);
|
||||||
|
|
||||||
|
@ -94,7 +92,7 @@ $(() => {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
selectDefaultStage() {
|
selectDefaultStage() {
|
||||||
const stage = this.state.stages.first();
|
const stage = this.state.stages[0];
|
||||||
this.selectStage(stage);
|
this.selectStage(stage);
|
||||||
},
|
},
|
||||||
selectStage(stage) {
|
selectStage(stage) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
import { __ } from '../locale';
|
|
||||||
|
|
||||||
require('../lib/utils/text_utility');
|
import { __ } from '../locale';
|
||||||
const DEFAULT_EVENT_OBJECTS = require('./default_event_objects');
|
import '../lib/utils/text_utility';
|
||||||
|
import DEFAULT_EVENT_OBJECTS from './default_event_objects';
|
||||||
|
|
||||||
const global = window.gl || (window.gl = {});
|
const global = window.gl || (window.gl = {});
|
||||||
global.cycleAnalytics = global.cycleAnalytics || {};
|
global.cycleAnalytics = global.cycleAnalytics || {};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
module.exports = {
|
export default {
|
||||||
issue: {
|
issue: {
|
||||||
created_at: '',
|
created_at: '',
|
||||||
url: '',
|
url: '',
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import eventHub from '../eventhub';
|
import eventHub from '../eventhub';
|
||||||
|
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
@ -22,6 +23,11 @@
|
||||||
default: 'btn-default',
|
default: 'btn-default',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
loadingIcon,
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
doAction() {
|
doAction() {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
@ -44,11 +50,6 @@
|
||||||
:disabled="isLoading"
|
:disabled="isLoading"
|
||||||
@click="doAction">
|
@click="doAction">
|
||||||
{{ text }}
|
{{ text }}
|
||||||
<i
|
<loading-icon v-if="isLoading" />
|
||||||
v-if="isLoading"
|
|
||||||
class="fa fa-spinner fa-spin"
|
|
||||||
aria-hidden="true"
|
|
||||||
aria-label="Loading">
|
|
||||||
</i>
|
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue