Commit 03b87ec9 authored by Filipe Freire's avatar Filipe Freire

Merge branch 'master' of https://gitlab.com/filipefreire/gitlab-ce into filipefreire_155

parents 350dbca4 10d8026f
...@@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.6-golang-1.9-git ...@@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.6-golang-1.9-git
- gitlab-org - gitlab-org
.default-cache: &default-cache .default-cache: &default-cache
key: "ruby-235-with-yarn" key: "ruby-2.3.6-with-yarn"
paths: paths:
- vendor/ruby - vendor/ruby
- .yarn-cache/ - .yarn-cache/
...@@ -290,7 +290,7 @@ flaky-examples-check: ...@@ -290,7 +290,7 @@ flaky-examples-check:
- scripts/merge-reports ${NEW_FLAKY_SPECS_REPORT} rspec_flaky/new_*_*.json - scripts/merge-reports ${NEW_FLAKY_SPECS_REPORT} rspec_flaky/new_*_*.json
- scripts/detect-new-flaky-examples $NEW_FLAKY_SPECS_REPORT - scripts/detect-new-flaky-examples $NEW_FLAKY_SPECS_REPORT
setup-test-env: compile-assets:
<<: *dedicated-runner <<: *dedicated-runner
<<: *except-docs <<: *except-docs
<<: *use-pg <<: *use-pg
...@@ -301,82 +301,93 @@ setup-test-env: ...@@ -301,82 +301,93 @@ setup-test-env:
- node --version - node --version
- yarn install --frozen-lockfile --cache-folder .yarn-cache - yarn install --frozen-lockfile --cache-folder .yarn-cache
- bundle exec rake gitlab:assets:compile - bundle exec rake gitlab:assets:compile
- 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:
- node_modules - node_modules
- public/assets - public/assets
setup-test-env:
<<: *dedicated-runner
<<: *except-docs
<<: *use-pg
stage: prepare
cache:
<<: *default-cache
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- scripts/gitaly-test-build # Do not use 'bundle exec' here
artifacts:
expire_in: 7d
paths:
- tmp/tests - tmp/tests
rspec-pg 0 26: *rspec-metadata-pg rspec-pg 0 27: *rspec-metadata-pg
rspec-pg 1 26: *rspec-metadata-pg rspec-pg 1 27: *rspec-metadata-pg
rspec-pg 2 26: *rspec-metadata-pg rspec-pg 2 27: *rspec-metadata-pg
rspec-pg 3 26: *rspec-metadata-pg rspec-pg 3 27: *rspec-metadata-pg
rspec-pg 4 26: *rspec-metadata-pg rspec-pg 4 27: *rspec-metadata-pg
rspec-pg 5 26: *rspec-metadata-pg rspec-pg 5 27: *rspec-metadata-pg
rspec-pg 6 26: *rspec-metadata-pg rspec-pg 6 27: *rspec-metadata-pg
rspec-pg 7 26: *rspec-metadata-pg rspec-pg 7 27: *rspec-metadata-pg
rspec-pg 8 26: *rspec-metadata-pg rspec-pg 8 27: *rspec-metadata-pg
rspec-pg 9 26: *rspec-metadata-pg rspec-pg 9 27: *rspec-metadata-pg
rspec-pg 10 26: *rspec-metadata-pg rspec-pg 10 27: *rspec-metadata-pg
rspec-pg 11 26: *rspec-metadata-pg rspec-pg 11 27: *rspec-metadata-pg
rspec-pg 12 26: *rspec-metadata-pg rspec-pg 12 27: *rspec-metadata-pg
rspec-pg 13 26: *rspec-metadata-pg rspec-pg 13 27: *rspec-metadata-pg
rspec-pg 14 26: *rspec-metadata-pg rspec-pg 14 27: *rspec-metadata-pg
rspec-pg 15 26: *rspec-metadata-pg rspec-pg 15 27: *rspec-metadata-pg
rspec-pg 16 26: *rspec-metadata-pg rspec-pg 16 27: *rspec-metadata-pg
rspec-pg 17 26: *rspec-metadata-pg rspec-pg 17 27: *rspec-metadata-pg
rspec-pg 18 26: *rspec-metadata-pg rspec-pg 18 27: *rspec-metadata-pg
rspec-pg 19 26: *rspec-metadata-pg rspec-pg 19 27: *rspec-metadata-pg
rspec-pg 20 26: *rspec-metadata-pg rspec-pg 20 27: *rspec-metadata-pg
rspec-pg 21 26: *rspec-metadata-pg rspec-pg 21 27: *rspec-metadata-pg
rspec-pg 22 26: *rspec-metadata-pg rspec-pg 22 27: *rspec-metadata-pg
rspec-pg 23 26: *rspec-metadata-pg rspec-pg 23 27: *rspec-metadata-pg
rspec-pg 24 26: *rspec-metadata-pg rspec-pg 24 27: *rspec-metadata-pg
rspec-pg 25 26: *rspec-metadata-pg rspec-pg 25 27: *rspec-metadata-pg
rspec-pg 26 27: *rspec-metadata-pg
rspec-mysql 0 26: *rspec-metadata-mysql
rspec-mysql 1 26: *rspec-metadata-mysql rspec-mysql 0 27: *rspec-metadata-mysql
rspec-mysql 2 26: *rspec-metadata-mysql rspec-mysql 1 27: *rspec-metadata-mysql
rspec-mysql 3 26: *rspec-metadata-mysql rspec-mysql 2 27: *rspec-metadata-mysql
rspec-mysql 4 26: *rspec-metadata-mysql rspec-mysql 3 27: *rspec-metadata-mysql
rspec-mysql 5 26: *rspec-metadata-mysql rspec-mysql 4 27: *rspec-metadata-mysql
rspec-mysql 6 26: *rspec-metadata-mysql rspec-mysql 5 27: *rspec-metadata-mysql
rspec-mysql 7 26: *rspec-metadata-mysql rspec-mysql 6 27: *rspec-metadata-mysql
rspec-mysql 8 26: *rspec-metadata-mysql rspec-mysql 7 27: *rspec-metadata-mysql
rspec-mysql 9 26: *rspec-metadata-mysql rspec-mysql 8 27: *rspec-metadata-mysql
rspec-mysql 10 26: *rspec-metadata-mysql rspec-mysql 9 27: *rspec-metadata-mysql
rspec-mysql 11 26: *rspec-metadata-mysql rspec-mysql 10 27: *rspec-metadata-mysql
rspec-mysql 12 26: *rspec-metadata-mysql rspec-mysql 11 27: *rspec-metadata-mysql
rspec-mysql 13 26: *rspec-metadata-mysql rspec-mysql 12 27: *rspec-metadata-mysql
rspec-mysql 14 26: *rspec-metadata-mysql rspec-mysql 13 27: *rspec-metadata-mysql
rspec-mysql 15 26: *rspec-metadata-mysql rspec-mysql 14 27: *rspec-metadata-mysql
rspec-mysql 16 26: *rspec-metadata-mysql rspec-mysql 15 27: *rspec-metadata-mysql
rspec-mysql 17 26: *rspec-metadata-mysql rspec-mysql 16 27: *rspec-metadata-mysql
rspec-mysql 18 26: *rspec-metadata-mysql rspec-mysql 17 27: *rspec-metadata-mysql
rspec-mysql 19 26: *rspec-metadata-mysql rspec-mysql 18 27: *rspec-metadata-mysql
rspec-mysql 20 26: *rspec-metadata-mysql rspec-mysql 19 27: *rspec-metadata-mysql
rspec-mysql 21 26: *rspec-metadata-mysql rspec-mysql 20 27: *rspec-metadata-mysql
rspec-mysql 22 26: *rspec-metadata-mysql rspec-mysql 21 27: *rspec-metadata-mysql
rspec-mysql 23 26: *rspec-metadata-mysql rspec-mysql 22 27: *rspec-metadata-mysql
rspec-mysql 24 26: *rspec-metadata-mysql rspec-mysql 23 27: *rspec-metadata-mysql
rspec-mysql 25 26: *rspec-metadata-mysql rspec-mysql 24 27: *rspec-metadata-mysql
rspec-mysql 25 27: *rspec-metadata-mysql
spinach-pg 0 4: *spinach-metadata-pg rspec-mysql 26 27: *rspec-metadata-mysql
spinach-pg 1 4: *spinach-metadata-pg
spinach-pg 2 4: *spinach-metadata-pg spinach-pg 0 3: *spinach-metadata-pg
spinach-pg 3 4: *spinach-metadata-pg spinach-pg 1 3: *spinach-metadata-pg
spinach-pg 2 3: *spinach-metadata-pg
spinach-mysql 0 4: *spinach-metadata-mysql
spinach-mysql 1 4: *spinach-metadata-mysql spinach-mysql 0 3: *spinach-metadata-mysql
spinach-mysql 2 4: *spinach-metadata-mysql spinach-mysql 1 3: *spinach-metadata-mysql
spinach-mysql 3 4: *spinach-metadata-mysql spinach-mysql 2 3: *spinach-metadata-mysql
# Static analysis jobs # 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"
...@@ -397,6 +408,12 @@ static-analysis: ...@@ -397,6 +408,12 @@ static-analysis:
stage: test stage: test
script: script:
- scripts/static-analysis - scripts/static-analysis
cache:
key: "ruby-2.3.6-with-yarn-and-rubocop"
paths:
- vendor/ruby
- .yarn-cache/
- tmp/rubocop_cache
# Documentation checks: # Documentation checks:
# - Check validity of relative links # - Check validity of relative links
...@@ -664,6 +681,7 @@ lint:javascript:report: ...@@ -664,6 +681,7 @@ lint:javascript:report:
<<: *pull-cache <<: *pull-cache
stage: post-test stage: post-test
dependencies: dependencies:
- compile-assets
- setup-test-env - setup-test-env
before_script: [] before_script: []
script: script:
...@@ -704,8 +722,6 @@ pages: ...@@ -704,8 +722,6 @@ pages:
cache gems: cache gems:
<<: *dedicated-runner <<: *dedicated-runner
<<: *pull-cache <<: *pull-cache
only:
- tags
variables: variables:
SETUP_DB: "false" SETUP_DB: "false"
script: script:
...@@ -716,6 +732,7 @@ cache gems: ...@@ -716,6 +732,7 @@ cache gems:
only: only:
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee - master@gitlab-org/gitlab-ee
- tags
gitlab_git_test: gitlab_git_test:
<<: *dedicated-runner <<: *dedicated-runner
......
...@@ -17,6 +17,7 @@ AllCops: ...@@ -17,6 +17,7 @@ AllCops:
- 'bin/**/*' - 'bin/**/*'
- 'generator_templates/**/*' - 'generator_templates/**/*'
- 'builds/**/*' - 'builds/**/*'
CacheRootDirectory: tmp
# Gitlab ################################################################### # Gitlab ###################################################################
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -115,7 +115,7 @@ gem 'google-api-client', '~> 0.13.6' ...@@ -115,7 +115,7 @@ gem 'google-api-client', '~> 0.13.6'
gem 'unf', '~> 0.1.4' gem 'unf', '~> 0.1.4'
# Seed data # Seed data
gem 'seed-fu', '2.3.6' # Upgrade to > 2.3.7 once https://github.com/mbleigh/seed-fu/issues/123 is solved gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing # Markdown and HTML processing
gem 'html-pipeline', '~> 1.11.0' gem 'html-pipeline', '~> 1.11.0'
...@@ -233,6 +233,9 @@ gem 'charlock_holmes', '~> 0.7.5' ...@@ -233,6 +233,9 @@ gem 'charlock_holmes', '~> 0.7.5'
# Faster JSON # Faster JSON
gem 'oj', '~> 2.17.4' gem 'oj', '~> 2.17.4'
# Faster blank
gem 'fast_blank'
# Parse time & duration # Parse time & duration
gem 'chronic', '~> 0.10.2' gem 'chronic', '~> 0.10.2'
gem 'chronic_duration', '~> 0.10.6' gem 'chronic_duration', '~> 0.10.6'
...@@ -338,10 +341,10 @@ group :development, :test do ...@@ -338,10 +341,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 'gitlab-styles', '~> 2.2.0', require: false gem 'gitlab-styles', '~> 2.3', require: false
# Pin these dependencies, otherwise a new rule could break the CI pipelines # Pin these dependencies, otherwise a new rule could break the CI pipelines
gem 'rubocop', '~> 0.52.0' gem 'rubocop', '~> 0.52.1'
gem 'rubocop-rspec', '~> 1.20.1' gem 'rubocop-rspec', '~> 1.22.1'
gem 'scss_lint', '~> 0.56.0', require: false gem 'scss_lint', '~> 0.56.0', require: false
gem 'haml_lint', '~> 0.26.0', require: false gem 'haml_lint', '~> 0.26.0', require: false
...@@ -403,7 +406,7 @@ group :ed25519 do ...@@ -403,7 +406,7 @@ group :ed25519 do
end end
# Gitaly GRPC client # Gitaly GRPC client
gem 'gitaly-proto', '~> 0.73.0', require: 'gitaly' gem 'gitaly-proto', '~> 0.78.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false gem 'toml-rb', '~> 0.3.15', require: false
......
...@@ -207,6 +207,7 @@ GEM ...@@ -207,6 +207,7 @@ GEM
faraday_middleware-multi_json (0.0.6) faraday_middleware-multi_json (0.0.6)
faraday_middleware faraday_middleware
multi_json multi_json
fast_blank (1.0.0)
fast_gettext (1.4.0) fast_gettext (1.4.0)
ffaker (2.4.0) ffaker (2.4.0)
ffi (1.9.18) ffi (1.9.18)
...@@ -284,7 +285,7 @@ GEM ...@@ -284,7 +285,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-proto (0.73.0) gitaly-proto (0.78.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)
...@@ -303,7 +304,7 @@ GEM ...@@ -303,7 +304,7 @@ GEM
mime-types (>= 1.16) mime-types (>= 1.16)
posix-spawn (~> 0.3) posix-spawn (~> 0.3)
gitlab-markup (1.6.3) gitlab-markup (1.6.3)
gitlab-styles (2.2.0) gitlab-styles (2.3.1)
rubocop (~> 0.51) rubocop (~> 0.51)
rubocop-gitlab-security (~> 0.1.0) rubocop-gitlab-security (~> 0.1.0)
rubocop-rspec (~> 1.19) rubocop-rspec (~> 1.19)
...@@ -582,7 +583,7 @@ GEM ...@@ -582,7 +583,7 @@ 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)
parallel (1.12.0) parallel (1.12.1)
parser (2.4.0.2) parser (2.4.0.2)
ast (~> 2.3) ast (~> 2.3)
parslet (1.5.0) parslet (1.5.0)
...@@ -785,7 +786,7 @@ GEM ...@@ -785,7 +786,7 @@ GEM
pg pg
rails rails
sqlite3 sqlite3
rubocop (0.52.0) rubocop (0.52.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.4.0.2, < 3.0) parser (>= 2.4.0.2, < 3.0)
powerpack (~> 0.1) powerpack (~> 0.1)
...@@ -794,8 +795,8 @@ GEM ...@@ -794,8 +795,8 @@ GEM
unicode-display_width (~> 1.0, >= 1.0.1) unicode-display_width (~> 1.0, >= 1.0.1)
rubocop-gitlab-security (0.1.1) rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51) rubocop (>= 0.51)
rubocop-rspec (1.20.1) rubocop-rspec (1.22.1)
rubocop (>= 0.51.0) rubocop (>= 0.52.1)
ruby-fogbugz (0.2.1) ruby-fogbugz (0.2.1)
crack (~> 0.4) crack (~> 0.4)
ruby-prof (0.16.2) ruby-prof (0.16.2)
...@@ -831,7 +832,7 @@ GEM ...@@ -831,7 +832,7 @@ GEM
rake (>= 0.9, < 13) rake (>= 0.9, < 13)
sass (~> 3.5.3) sass (~> 3.5.3)
securecompare (1.0.0) securecompare (1.0.0)
seed-fu (2.3.6) seed-fu (2.3.7)
activerecord (>= 3.1) activerecord (>= 3.1)
activesupport (>= 3.1) activesupport (>= 3.1)
select2-rails (3.5.9.3) select2-rails (3.5.9.3)
...@@ -1034,6 +1035,7 @@ DEPENDENCIES ...@@ -1034,6 +1035,7 @@ DEPENDENCIES
email_spec (~> 1.6.0) email_spec (~> 1.6.0)
factory_bot_rails (~> 4.8.2) factory_bot_rails (~> 4.8.2)
faraday (~> 0.12) faraday (~> 0.12)
fast_blank
ffaker (~> 2.4) ffaker (~> 2.4)
flay (~> 2.8.0) flay (~> 2.8.0)
flipper (~> 0.11.0) flipper (~> 0.11.0)
...@@ -1054,11 +1056,11 @@ DEPENDENCIES ...@@ -1054,11 +1056,11 @@ DEPENDENCIES
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-proto (~> 0.73.0) gitaly-proto (~> 0.78.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.6.2) gitlab-markup (~> 1.6.2)
gitlab-styles (~> 2.2.0) gitlab-styles (~> 2.3)
gitlab_omniauth-ldap (~> 2.0.4) gitlab_omniauth-ldap (~> 2.0.4)
gollum-lib (~> 4.2) gollum-lib (~> 4.2)
gollum-rugged_adapter (~> 0.4.4) gollum-rugged_adapter (~> 0.4.4)
...@@ -1160,8 +1162,8 @@ DEPENDENCIES ...@@ -1160,8 +1162,8 @@ DEPENDENCIES
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.52.0) rubocop (~> 0.52.1)
rubocop-rspec (~> 1.20.1) rubocop-rspec (~> 1.22.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) ruby_parser (~> 3.8)
...@@ -1170,7 +1172,7 @@ DEPENDENCIES ...@@ -1170,7 +1172,7 @@ DEPENDENCIES
sanitize (~> 2.0) sanitize (~> 2.0)
sass-rails (~> 5.0.6) sass-rails (~> 5.0.6)
scss_lint (~> 0.56.0) scss_lint (~> 0.56.0)
seed-fu (= 2.3.6) seed-fu (~> 2.3.7)
select2-rails (~> 3.5.9) select2-rails (~> 3.5.9)
selenium-webdriver (~> 3.5) selenium-webdriver (~> 3.5)
sentry-raven (~> 2.5.3) sentry-raven (~> 2.5.3)
......
...@@ -85,7 +85,8 @@ These types of merge requests for the upcoming release need special consideratio ...@@ -85,7 +85,8 @@ These types of merge requests for the upcoming release need special consideratio
and a dedicated team with front-end, back-end, and UX. and a dedicated team with front-end, back-end, and UX.
* **Small features**: any other feature request. * **Small features**: any other feature request.
**Large features** must be with a maintainer **by the 1st**. This means that: It is strongly recommended that **large features** be with a maintainer **by the
1st**. This means that:
* There is a merge request (even if it's WIP). * There is a merge request (even if it's WIP).
* The person (or people, if it needs a frontend and backend maintainer) who will * The person (or people, if it needs a frontend and backend maintainer) who will
...@@ -100,14 +101,37 @@ The maintainer can also choose to assign a reviewer to perform an initial ...@@ -100,14 +101,37 @@ The maintainer can also choose to assign a reviewer to perform an initial
review, but this way the maintainer is unlikely to be surprised by receiving an review, but this way the maintainer is unlikely to be surprised by receiving an
MR later in the cycle. MR later in the cycle.
**Small features** must be with a reviewer (not necessarily maintainer) **by the It is strongly recommended that **small features** be with a reviewer (not
3rd**. necessarily a maintainer) **by the 3rd**.
Most merge requests from the community do not have a specific release Most merge requests from the community do not have a specific release
target. However, if one does and falls into either of the above categories, it's target. However, if one does and falls into either of the above categories, it's
the reviewer's responsibility to manage the above communication and assignment the reviewer's responsibility to manage the above communication and assignment
on behalf of the community member. on behalf of the community member.
#### What happens if these deadlines are missed?
If a small or large feature is _not_ with a maintainer or reviewer by the
recommended date, this does _not_ mean that maintainers or reviewers will refuse
to review or merge it, or that the feature will definitely not make it in before
the feature freeze.
However, with every day that passes without review, it will become more likely
that the feature will slip, because maintainers and reviewers may not have
enough time to do a thorough review, and developers may not have enough time to
adequately address any feedback that may come back.
A maintainer or reviewer may also determine that it will not be possible to
finish the current scope of the feature in time, but that it is possible to
reduce the scope so that something can still ship this month, with the remaining
scope moving to the next release. The sooner this decision is made, in
conversation with the Product Manager and developer, the more time there is to
extract that which is now out of scope, and to finish that which remains in scope.
For these reasons, it is strongly recommended to follow the guidelines above,
to maximize the chances of your feature making it in before the feature freeze,
and to prevent any last minute surprises.
### On the 7th ### On the 7th
Merge requests should still be complete, following the Merge requests should still be complete, following the
......
10.4.0-pre 10.5.0-pre
{"iconCount":189,"spriteSize":85766,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o-open","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","staged","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","unstaged","user","users","volume-up","warning","work"]} {"iconCount":189,"spriteSize":85900,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","staged","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_notfound","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","unstaged","user","users","volume-up","warning","work"]}
\ No newline at end of file \ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 80 80"><g fill="none" fill-rule="evenodd"><path fill="#EEE" d="M44.242 59.348c-3.7 1.576-7.3 1.994-10.902.84a7.002 7.002 0 0 1-9.085-.699l-4.243-4.243a7 7 0 0 1-.238-9.649c-.701-3.024-.419-6.083.646-9.206l-6.287-2.426a5.6 5.6 0 0 1-2.274-8.824l8.233-9.811a5.6 5.6 0 0 1 6.306-1.625l8.045 3.105c.772-.797 1.564-1.6 2.374-2.41C44.841 6.376 55.265 2.135 68.09 1.677a10 10 0 0 1 1.119.023c5.507.42 9.63 5.226 9.209 10.733-.935 12.225-5.373 22.309-13.315 30.25a410.76 410.76 0 0 1-1.661 1.653l3.247 8.412a5.6 5.6 0 0 1-1.625 6.306l-9.81 8.233a5.6 5.6 0 0 1-8.825-2.274l-2.186-5.665zm-22.92-26.923l10.406-12.402-6.822-2.633a1.6 1.6 0 0 0-1.801.464l-8.233 9.811a1.6 1.6 0 0 0 .65 2.521l5.8 2.239zm26.646 25.4l2.239 5.8a1.6 1.6 0 0 0 2.521.649l9.81-8.232a1.6 1.6 0 0 0 .465-1.802l-2.633-6.822-12.402 10.406zm-19.69-5.627c8.751 8.752 16.065 5.587 33.995-12.343 7.25-7.25 11.292-16.433 12.155-27.727a6 6 0 0 0-6.196-6.454c-11.846.423-21.303 4.271-28.586 11.554-17.03 17.03-20.414 25.924-11.368 34.97z"/><path fill="#FDC4A8" fill-rule="nonzero" d="M52.54 28.376a4 4 0 1 0 5.656-5.657 4 4 0 0 0-5.657 5.657zm-2.83 2.829A8 8 0 1 1 61.025 19.89a8 8 0 0 1-11.313 11.314z"/><path fill="#FEE1D3" d="M15.063 54.54a2 2 0 0 1 0 2.828L3.749 68.68A2 2 0 1 1 .92 65.853l11.314-11.314a2 2 0 0 1 2.829 0zm9.899 9.899a2 2 0 0 1 0 2.828l-8.485 8.485a2 2 0 1 1-2.829-2.828l8.486-8.485a2 2 0 0 1 2.828 0z"/><path fill="#FDC4A8" d="M20.012 59.489a2 2 0 0 1 0 2.828L4.456 77.874a2 2 0 0 1-2.829-2.829L17.184 59.49a2 2 0 0 1 2.828 0z"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 80 80"><g fill="none" fill-rule="evenodd" transform="translate(7 3)"><path fill="#EEE" fill-rule="nonzero" d="M54 18a2 2 0 1 1 0-4h4c.843 0 1.675.105 2.48.31a2 2 0 1 1-.99 3.876A6.015 6.015 0 0 0 58 18h-4zm9.735 4.228a2 2 0 0 1 3.822-1.18A10 10 0 0 1 68 24v3.513a2 2 0 1 1-4 0V24c0-.61-.09-1.204-.265-1.772zM64 35.513a2 2 0 1 1 4 0v6a2 2 0 1 1-4 0v-6zm0 14a2 2 0 1 1 4 0v6a2 2 0 1 1-4 0v-6zm0 14a2 2 0 1 1 4 0V66a9.97 9.97 0 0 1-.963 4.286 2 2 0 1 1-3.613-1.716A5.969 5.969 0 0 0 64 66v-2.487zm-5.255 8.441a2 2 0 1 1 .49 3.97c-.401.05-.806.075-1.218.076h-5.042a2 2 0 1 1 0-4h5.038c.246 0 .49-.016.732-.046zM44.975 72a2 2 0 1 1 0 4h-6a2 2 0 1 1 0-4h6zm-14 0a2 2 0 1 1 0 4H26c-.429 0-.855-.027-1.276-.08a2 2 0 0 1 .506-3.969c.254.033.51.049.77.049h4.975zm-10.438-3.514a2 2 0 1 1-3.64 1.66A9.97 9.97 0 0 1 16 66v-2.538a2 2 0 1 1 4 0V66c0 .871.185 1.713.537 2.486zM8 2a6 6 0 0 0-6 6v42a6 6 0 0 0 6 6h32a6 6 0 0 0 6-6V8a6 6 0 0 0-6-6H8zm0-4h32c5.523 0 10 4.477 10 10v42c0 5.523-4.477 10-10 10H8C2.477 60-2 55.523-2 50V8C-2 2.477 2.477-2 8-2z"/><rect width="10" height="4" x="8" y="16" fill="#EFEDF8" rx="2"/><rect width="10" height="4" x="21" y="16" fill="#6B4FBB" rx="2"/><rect width="10" height="4" x="8" y="32" fill="#E1DBF1" rx="2"/><rect width="6" height="4" x="34" y="16" fill="#EFEDF8" rx="2"/><rect width="6" height="4" x="8" y="24" fill="#6B4FBB" rx="2"/><rect width="6" height="4" x="17" y="24" fill="#EFEDF8" rx="2"/><rect width="6" height="4" x="21" y="32" fill="#6B4FBB" rx="2"/><rect width="6" height="4" x="8" y="40" fill="#6B4FBB" rx="2"/><rect width="6" height="4" x="17" y="40" fill="#EFEDF8" rx="2"/><rect width="6" height="4" x="26" y="40" fill="#C3B8E3" rx="2"/><rect width="10" height="4" x="26" y="24" fill="#C3B8E3" rx="2"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 80 80"><g fill="none" fill-rule="evenodd" transform="translate(0 3)"><path fill="#EEE" fill-rule="nonzero" d="M40.843 5.864a2 2 0 1 1 .348-3.985l5.977.523a2 2 0 1 1-.348 3.985l-5.977-.523zm13.946 1.22a2 2 0 1 1 .349-3.985l5.977.523a2 2 0 1 1-.348 3.985l-5.978-.523zm13.947 1.22a2 2 0 1 1 .349-3.984 11.952 11.952 0 0 1 6.655 2.75 2 2 0 1 1-2.569 3.066 7.953 7.953 0 0 0-4.435-1.832zm7.28 7.357a2 2 0 1 1 3.99-.301c.048.639.045 1.283-.01 1.934l-.385 4.4a2 2 0 1 1-3.985-.349l.384-4.395c.037-.433.039-.863.007-1.29zm-1.088 13.654a2 2 0 0 1 3.985.348l-.523 5.978a2 2 0 1 1-3.984-.349l.522-5.977zm-1.22 13.947a2 2 0 1 1 3.985.348l-.523 5.977a2 2 0 1 1-3.985-.348l.523-5.977zM72.305 56.7a2 2 0 0 1 3.79 1.282 11.995 11.995 0 0 1-4.253 5.81 2 2 0 0 1-2.373-3.22 7.996 7.996 0 0 0 2.836-3.872zm-9.054 5.33a2 2 0 1 1-.349 3.985l-5.977-.522a2 2 0 1 1 .349-3.985l5.977.523zM32.793 10.675a2 2 0 1 1-3.675-1.579 12.02 12.02 0 0 1 4.696-5.456 2 2 0 0 1 2.112 3.397 8.02 8.02 0 0 0-3.133 3.638z"/><rect width="48" height="58" x="2" y="14" fill="#FAFAFA" rx="10"/><path fill="#EEE" fill-rule="nonzero" d="M12 16a8 8 0 0 0-8 8v38a8 8 0 0 0 8 8h28a8 8 0 0 0 8-8V24a8 8 0 0 0-8-8H12zm0-4h28c6.627 0 12 5.373 12 12v38c0 6.627-5.373 12-12 12H12C5.373 74 0 68.627 0 62V24c0-6.627 5.373-12 12-12z"/><rect width="24" height="4" x="11" y="30" fill="#E5E5E5" rx="2"/><rect width="30" height="4" x="11" y="41" fill="#E5E5E5" rx="2"/><rect width="20" height="4" x="11" y="52" fill="#E5E5E5" rx="2"/></g></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="430" height="200" viewBox="0 0 430 200"><g fill="none" fill-rule="evenodd"><g transform="translate(138 65)"><path fill="#E5E5E5" fill-rule="nonzero" d="M35 70a2 2 0 1 1 0-4c2.542 0 5.042-.305 7.463-.904a2 2 0 1 1 .96 3.884A35.075 35.075 0 0 1 35 70zm18.21-5.105a2 2 0 1 1-2.083-3.414 31.143 31.143 0 0 0 5.896-4.664 2 2 0 1 1 2.842 2.815 35.143 35.143 0 0 1-6.654 5.263zM66.106 51.06a2 2 0 0 1-3.552-1.838 30.77 30.77 0 0 0 2.612-7.042 2 2 0 1 1 3.892.922 34.77 34.77 0 0 1-2.952 7.958zm3.816-18.433a2 2 0 1 1-3.991.268 30.873 30.873 0 0 0-1.407-7.38 2 2 0 0 1 3.808-1.223 34.873 34.873 0 0 1 1.59 8.335zm-6.346-17.842a2 2 0 0 1-3.264 2.312 31.188 31.188 0 0 0-5.054-5.564 2 2 0 0 1 2.615-3.027 35.188 35.188 0 0 1 5.703 6.279zM48.895 2.867a2 2 0 0 1-1.59 3.67 30.758 30.758 0 0 0-7.206-2.12 2 2 0 1 1 .653-3.946 34.758 34.758 0 0 1 8.143 2.396zM30.263.318a2 2 0 0 1 .537 3.964c-2.505.339-4.94.98-7.266 1.907a2 2 0 1 1-1.48-3.716A34.774 34.774 0 0 1 30.263.318zM12.907 7.853a2 2 0 0 1 2.527 3.1 31.196 31.196 0 0 0-5.213 5.416 2 2 0 0 1-3.196-2.406 35.196 35.196 0 0 1 5.882-6.11zM1.99 23.343a2 2 0 0 1 3.772 1.331 30.82 30.82 0 0 0-1.619 7.337 2 2 0 1 1-3.982-.38 34.82 34.82 0 0 1 1.829-8.289zM.719 42.086a2 2 0 1 1 3.917-.806 30.757 30.757 0 0 0 2.4 7.118 2 2 0 1 1-3.605 1.73 34.757 34.757 0 0 1-2.713-8.042zM9.393 58.86a2 2 0 0 1 2.926-2.728 31.167 31.167 0 0 0 5.751 4.841 2 2 0 1 1-2.187 3.349 35.167 35.167 0 0 1-6.49-5.462zm16.245 9.873a2 2 0 1 1 1.067-3.855 30.979 30.979 0 0 0 7.434 1.11 2 2 0 1 1-.11 3.998 34.979 34.979 0 0 1-8.391-1.253z"/><circle cx="35" cy="35" r="16" stroke="#E1DBF1" stroke-width="4"/><path fill="#6B4FBB" d="M37 33h5a2 2 0 1 1 0 4h-7a2 2 0 0 1-2-2v-8a2 2 0 1 1 4 0v6z"/></g><g transform="translate(247 30)"><rect width="116" height="135" y="5" fill="#F9F9F9" rx="10"/><rect width="116" height="134" x="5" fill="#FFF" stroke="#EEE" stroke-width="4" stroke-linecap="round" rx="10"/><g transform="translate(23 23)"><rect width="16" height="4" fill="#E1DBF1" rx="2"/><rect width="16" height="4" x="32" y="12" fill="#E1DBF1" rx="2"/><rect width="16" height="4" x="44" fill="#EEE" rx="2"/><rect width="16" height="4" x="12" y="24" fill="#E1DBF1" rx="2"/><rect width="16" height="4" x="64" y="36" fill="#FEF0E8" rx="2"/><rect width="8" height="4" x="20" fill="#FEE1D3" rx="2"/><rect width="8" height="4" x="32" y="36" fill="#FC6D26" rx="2"/><rect width="8" height="4" x="52" y="12" fill="#FEF0E8" rx="2"/><rect width="8" height="4" x="64" fill="#FEF0E8" rx="2"/><rect width="12" height="4" x="16" y="48" fill="#E1DBF1" rx="2"/><rect width="8" height="4" x="44" y="36" fill="#FC6D26" rx="2"/><rect width="4" height="4" x="56" y="36" fill="#E1DBF1" rx="2"/><rect width="4" height="4" x="64" y="60" fill="#E1DBF1" rx="2"/><rect width="4" height="4" x="72" y="60" fill="#FC6D26" rx="2"/><rect width="8" height="4" x="32" fill="#FC6D26" rx="2"/><rect width="28" height="4" y="36" fill="#EEE" rx="2"/><rect width="28" height="4" x="44" y="48" fill="#EEE" rx="2"/><rect width="28" height="4" x="32" y="60" fill="#EFEDF8" rx="2"/><rect width="28" height="4" y="12" fill="#6B4FBB" rx="2"/><rect width="28" height="4" x="32" y="24" fill="#C3B8E3" rx="2"/><rect width="8" height="4" y="24" fill="#FEF0E8" rx="2"/><rect width="8" height="4" x="32" y="48" fill="#6B4FBB" rx="2"/><rect width="12" height="4" y="48" fill="#FC6D26" rx="2"/><rect width="12" height="4" y="60" fill="#FEF0E8" rx="2"/><rect width="12" height="4" x="16" y="60" fill="#FEF0E8" rx="2"/></g><g transform="translate(23 95)"><rect width="16" height="4" fill="#EFEDF8" rx="2"/><rect width="16" height="4" x="18" y="12" fill="#FC6D26" rx="2"/><rect width="16" height="4" x="44" fill="#6B4FBB" rx="2"/><rect width="8" height="4" x="20" fill="#FEE1D3" rx="2"/><rect width="8" height="4" x="38" y="12" fill="#FEF0E8" rx="2"/><rect width="8" height="4" x="64" fill="#FEF0E8" rx="2"/><rect width="8" height="4" x="32" fill="#FC6D26" rx="2"/><rect width="14" height="4" y="12" fill="#EEE" rx="2"/></g></g><path fill="#FC6D26" fill-rule="nonzero" d="M81 119c-10.493 0-19-8.507-19-19s8.507-19 19-19 19 8.507 19 19-8.507 19-19 19zm0-4c8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15-8.284 0-15 6.716-15 15 0 8.284 6.716 15 15 15zm-5-20a2 2 0 0 1 2 2v6a2 2 0 1 1-4 0v-6a2 2 0 0 1 2-2zm10 0a2 2 0 0 1 2 2v6a2 2 0 1 1-4 0v-6a2 2 0 0 1 2-2z"/><path fill="#E5E5E5" fill-rule="nonzero" d="M108 102c0-1.105.887-2 1.998-2h4.004c1.103 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4.004a1.994 1.994 0 0 1-1.998-2zm14 0c0-1.105.887-2 1.998-2h4.004c1.103 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4.004a1.994 1.994 0 0 1-1.998-2zm93 0c0-1.105.887-2 1.998-2h4.004c1.103 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4.004a1.994 1.994 0 0 1-1.998-2zm14 0c0-1.105.887-2 1.998-2h4.004c1.103 0 1.998.888 1.998 2 0 1.105-.887 2-1.998 2h-4.004a1.994 1.994 0 0 1-1.998-2z"/></g></svg>
\ No newline at end of file
...@@ -178,7 +178,7 @@ const Api = { ...@@ -178,7 +178,7 @@ const Api = {
issueTemplate(namespacePath, projectPath, key, type, callback) { issueTemplate(namespacePath, projectPath, key, type, callback) {
const url = Api.buildUrl(Api.issuableTemplatePath) const url = Api.buildUrl(Api.issuableTemplatePath)
.replace(':key', key) .replace(':key', encodeURIComponent(key))
.replace(':type', type) .replace(':type', type)
.replace(':project_path', projectPath) .replace(':project_path', projectPath)
.replace(':namespace_path', namespacePath); .replace(':namespace_path', namespacePath);
...@@ -218,6 +218,7 @@ const Api = { ...@@ -218,6 +218,7 @@ const Api = {
(jqXHR, textStatus, errorThrown) => { (jqXHR, textStatus, errorThrown) => {
const error = new Error(`${options.url}: ${errorThrown}`); const error = new Error(`${options.url}: ${errorThrown}`);
error.textStatus = textStatus; error.textStatus = textStatus;
if (jqXHR && jqXHR.responseJSON) error.responseJSON = jqXHR.responseJSON;
reject(error); reject(error);
}, },
); );
......
...@@ -299,6 +299,13 @@ const gfmRules = { ...@@ -299,6 +299,13 @@ const gfmRules = {
export class CopyAsGFM { export class CopyAsGFM {
constructor() { constructor() {
// iOS currently does not support clipboardData.setData(). This bug should
// be fixed in iOS 12, but for now we'll disable this for all iOS browsers
// ref: https://trac.webkit.org/changeset/222228/webkit
const userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || '';
const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent);
if (isIOS) return;
$(document).on('copy', '.md, .wiki', (e) => { CopyAsGFM.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) => { CopyAsGFM.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', CopyAsGFM.pasteGFM); $(document).on('paste', '.js-gfm-input', CopyAsGFM.pasteGFM);
......
...@@ -2,18 +2,19 @@ import { n__ } from '../locale'; ...@@ -2,18 +2,19 @@ import { n__ } from '../locale';
import { convertPermissionToBoolean } from '../lib/utils/common_utils'; import { convertPermissionToBoolean } from '../lib/utils/common_utils';
export default class SecretValues { export default class SecretValues {
constructor(container) { constructor({
container,
valueSelector = '.js-secret-value',
placeholderSelector = '.js-secret-value-placeholder',
}) {
this.container = container; this.container = container;
this.valueSelector = valueSelector;
this.placeholderSelector = placeholderSelector;
} }
init() { init() {
this.values = this.container.querySelectorAll('.js-secret-value');
this.placeholders = this.container.querySelectorAll('.js-secret-value-placeholder');
this.revealButton = this.container.querySelector('.js-secret-value-reveal-button'); this.revealButton = this.container.querySelector('.js-secret-value-reveal-button');
this.revealText = n__('Reveal value', 'Reveal values', this.values.length);
this.hideText = n__('Hide value', 'Hide values', this.values.length);
const isRevealed = convertPermissionToBoolean(this.revealButton.dataset.secretRevealStatus); const isRevealed = convertPermissionToBoolean(this.revealButton.dataset.secretRevealStatus);
this.updateDom(isRevealed); this.updateDom(isRevealed);
...@@ -28,15 +29,17 @@ export default class SecretValues { ...@@ -28,15 +29,17 @@ export default class SecretValues {
} }
updateDom(isRevealed) { updateDom(isRevealed) {
this.values.forEach((value) => { const values = this.container.querySelectorAll(this.valueSelector);
values.forEach((value) => {
value.classList.toggle('hide', !isRevealed); value.classList.toggle('hide', !isRevealed);
}); });
this.placeholders.forEach((placeholder) => { const placeholders = this.container.querySelectorAll(this.placeholderSelector);
placeholders.forEach((placeholder) => {
placeholder.classList.toggle('hide', isRevealed); placeholder.classList.toggle('hide', isRevealed);
}); });
this.revealButton.textContent = isRevealed ? this.hideText : this.revealText; this.revealButton.textContent = isRevealed ? n__('Hide value', 'Hide values', values.length) : n__('Reveal value', 'Reveal values', values.length);
this.revealButton.dataset.secretRevealStatus = isRevealed; this.revealButton.dataset.secretRevealStatus = isRevealed;
} }
} }
...@@ -5,7 +5,7 @@ export default (path, extraData) => path.split('&').reduce((dataParam, filterPar ...@@ -5,7 +5,7 @@ export default (path, extraData) => path.split('&').reduce((dataParam, filterPar
const paramSplit = filterParam.split('='); const paramSplit = filterParam.split('=');
const paramKeyNormalized = paramSplit[0].replace('[]', ''); const paramKeyNormalized = paramSplit[0].replace('[]', '');
const isArray = paramSplit[0].indexOf('[]'); const isArray = paramSplit[0].indexOf('[]');
const value = decodeURIComponent(paramSplit[1]).replace(/\+/g, ' '); const value = decodeURIComponent(paramSplit[1].replace(/\+/g, ' '));
if (isArray !== -1) { if (isArray !== -1) {
if (!data[paramKeyNormalized]) { if (!data[paramKeyNormalized]) {
......
...@@ -65,7 +65,17 @@ export default class CreateItemDropdown { ...@@ -65,7 +65,17 @@ export default class CreateItemDropdown {
getData(term, callback) { getData(term, callback) {
this.getDataOption(term, (data = []) => { this.getDataOption(term, (data = []) => {
callback(data.concat(this.selectedItem || [])); // Ensure the selected item isn't already in the data to avoid duplicates
const alreadyHasSelectedItem = this.selectedItem && data.some(item =>
item.id === this.selectedItem.id,
);
let uniqueData = data;
if (!alreadyHasSelectedItem) {
uniqueData = data.concat(this.selectedItem || []);
}
callback(uniqueData);
}); });
} }
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
<div v-else-if="hasKeys"> <div v-else-if="hasKeys">
<keys-panel <keys-panel
title="Enabled deploy keys for this project" title="Enabled deploy keys for this project"
class="qa-project-deploy-keys"
:keys="keys.enabled_keys" :keys="keys.enabled_keys"
:store="store" :store="store"
:endpoint="endpoint" :endpoint="endpoint"
......
<script> <script>
import actionBtn from './action_btn.vue'; import actionBtn from './action_btn.vue';
import { getTimeago } from '../../lib/utils/datetime_utility'; import { getTimeago } from '../../lib/utils/datetime_utility';
import tooltip from '../../vue_shared/directives/tooltip';
export default { export default {
components: { components: {
actionBtn, actionBtn,
}, },
directives: {
tooltip,
},
props: { props: {
deployKey: { deployKey: {
type: Object, type: Object,
...@@ -32,6 +36,9 @@ ...@@ -32,6 +36,9 @@
isEnabled(id) { isEnabled(id) {
return this.store.findEnabledKey(id) !== undefined; return this.store.findEnabledKey(id) !== undefined;
}, },
tooltipTitle(project) {
return project.can_push ? 'Write access allowed' : 'Read access only';
},
}, },
}; };
</script> </script>
...@@ -46,27 +53,29 @@ ...@@ -46,27 +53,29 @@
</i> </i>
</div> </div>
<div class="deploy-key-content key-list-item-info"> <div class="deploy-key-content key-list-item-info">
<strong class="title"> <strong class="title qa-key-title">
{{ deployKey.title }} {{ deployKey.title }}
</strong> </strong>
<div class="description"> <div class="description qa-key-fingerprint">
{{ deployKey.fingerprint }} {{ deployKey.fingerprint }}
</div> </div>
<div
v-if="deployKey.can_push"
class="write-access-allowed"
>
Write access allowed
</div>
</div> </div>
<div class="deploy-key-content prepend-left-default deploy-key-projects"> <div class="deploy-key-content prepend-left-default deploy-key-projects">
<a <a
v-for="(project, i) in deployKey.projects" v-for="(deployKeysProject, i) in deployKey.deploy_keys_projects"
class="label deploy-project-label"
:href="project.full_path"
:key="i" :key="i"
class="label deploy-project-label"
:href="deployKeysProject.project.full_path"
:title="tooltipTitle(deployKeysProject)"
v-tooltip
> >
{{ project.full_name }} {{ deployKeysProject.project.full_name }}
<i
v-if="!deployKeysProject.can_push"
aria-hidden="true"
class="fa fa-lock"
>
</i>
</a> </a>
</div> </div>
<div class="deploy-key-content"> <div class="deploy-key-content">
......
This diff is collapsed.
...@@ -99,7 +99,7 @@ export default { ...@@ -99,7 +99,7 @@ export default {
> >
<div <div
v-if="model.isLoadingFolderContent" v-if="model.isLoadingFolderContent"
:key="i"> :key="`loading-item-${i}`">
<loading-icon size="2" /> <loading-icon size="2" />
</div> </div>
...@@ -110,10 +110,10 @@ export default { ...@@ -110,10 +110,10 @@ export default {
:model="children" :model="children"
:can-create-deployment="canCreateDeployment" :can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment" :can-read-environment="canReadEnvironment"
:key="index" :key="`env-item-${i}-${index}`"
/> />
<div :key="i"> <div :key="`sub-div-${i}`">
<div class="text-center prepend-top-10"> <div class="text-center prepend-top-10">
<a <a
:href="folderUrl(model)" :href="folderUrl(model)"
......
...@@ -10,6 +10,7 @@ const hideFlash = (flashEl, fadeTransition = true) => { ...@@ -10,6 +10,7 @@ const hideFlash = (flashEl, fadeTransition = true) => {
flashEl.addEventListener('transitionend', () => { flashEl.addEventListener('transitionend', () => {
flashEl.remove(); flashEl.remove();
if (document.body.classList.contains('flash-shown')) document.body.classList.remove('flash-shown');
}, { }, {
once: true, once: true,
passive: true, passive: true,
...@@ -64,6 +65,7 @@ const createFlash = function createFlash( ...@@ -64,6 +65,7 @@ const createFlash = function createFlash(
parent = document, parent = document,
actionConfig = null, actionConfig = null,
fadeTransition = true, fadeTransition = true,
addBodyClass = false,
) { ) {
const flashContainer = parent.querySelector('.flash-container'); const flashContainer = parent.querySelector('.flash-container');
...@@ -86,6 +88,8 @@ const createFlash = function createFlash( ...@@ -86,6 +88,8 @@ const createFlash = function createFlash(
flashContainer.style.display = 'block'; flashContainer.style.display = 'block';
if (addBodyClass) document.body.classList.add('flash-shown');
return flashContainer; return flashContainer;
}; };
......
...@@ -118,14 +118,14 @@ export const showSubLevelItems = (el) => { ...@@ -118,14 +118,14 @@ export const showSubLevelItems = (el) => {
moveSubItemsToPosition(el, subItems); moveSubItemsToPosition(el, subItems);
}; };
export const mouseEnterTopItems = (el) => { export const mouseEnterTopItems = (el, timeout = getHideSubItemsInterval()) => {
clearTimeout(timeoutId); clearTimeout(timeoutId);
timeoutId = setTimeout(() => { timeoutId = setTimeout(() => {
if (currentOpenMenu) hideMenu(currentOpenMenu); if (currentOpenMenu) hideMenu(currentOpenMenu);
showSubLevelItems(el); showSubLevelItems(el);
}, getHideSubItemsInterval()); }, timeout);
}; };
export const mouseLeaveTopItem = (el) => { export const mouseLeaveTopItem = (el) => {
......
...@@ -10,7 +10,7 @@ import groupItemComponent from './components/group_item.vue'; ...@@ -10,7 +10,7 @@ import groupItemComponent from './components/group_item.vue';
Vue.use(Translate); Vue.use(Translate);
document.addEventListener('DOMContentLoaded', () => { export default () => {
const el = document.getElementById('js-groups-tree'); const el = document.getElementById('js-groups-tree');
// Don't do anything if element doesn't exist (No groups) // Don't do anything if element doesn't exist (No groups)
...@@ -71,4 +71,4 @@ document.addEventListener('DOMContentLoaded', () => { ...@@ -71,4 +71,4 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
}, },
}); });
}); };
import Vue from 'vue'; import Vue from 'vue';
import VueResource from 'vue-resource'; import '../../vue_shared/vue_resource_interceptor';
Vue.use(VueResource);
export default class GroupsService { export default class GroupsService {
constructor(endpoint) { constructor(endpoint) {
......
...@@ -68,12 +68,8 @@ export default { ...@@ -68,12 +68,8 @@ export default {
this.commitChanges({ payload, newMr: this.startNewMR }) this.commitChanges({ payload, newMr: this.startNewMR })
.then(() => { .then(() => {
this.submitCommitsLoading = false; this.submitCommitsLoading = false;
this.$store.dispatch('getTreeData', { this.commitMessage = '';
projectId: this.currentProjectId, this.startNewMR = false;
branch: this.currentBranchId,
endpoint: `/tree/${this.currentBranchId}`,
force: true,
});
}) })
.catch(() => { .catch(() => {
this.submitCommitsLoading = false; this.submitCommitsLoading = false;
...@@ -153,6 +149,7 @@ you started editing. Would you like to create a new branch?`)" ...@@ -153,6 +149,7 @@ you started editing. Would you like to create a new branch?`)"
type="submit" type="submit"
:disabled="commitButtonDisabled" :disabled="commitButtonDisabled"
class="btn btn-default btn-sm append-right-10 prepend-left-10" class="btn btn-default btn-sm append-right-10 prepend-left-10"
:class="{ disabled: submitCommitsLoading }"
> >
<i <i
v-if="submitCommitsLoading" v-if="submitCommitsLoading"
......
...@@ -70,7 +70,10 @@ export default { ...@@ -70,7 +70,10 @@ export default {
this.editor.createInstance(this.$refs.editor); this.editor.createInstance(this.$refs.editor);
}) })
.then(() => this.setupEditor()) .then(() => this.setupEditor())
.catch(() => flash('Error setting up monaco. Please try again.')); .catch((err) => {
flash('Error setting up monaco. Please try again.', 'alert', document, null, false, true);
throw err;
});
}, },
setupEditor() { setupEditor() {
if (!this.activeFile) return; if (!this.activeFile) return;
......
...@@ -35,9 +35,12 @@ ...@@ -35,9 +35,12 @@
return this.file.type === 'tree'; return this.file.type === 'tree';
}, },
levelIndentation() { levelIndentation() {
return { if (this.file.level > 0) {
marginLeft: `${this.file.level * 16}px`, return {
}; marginLeft: `${this.file.level * 16}px`,
};
}
return {};
}, },
shortId() { shortId() {
return this.file.id.substr(0, 8); return this.file.id.substr(0, 8);
...@@ -111,7 +114,7 @@ ...@@ -111,7 +114,7 @@
/> />
<i <i
class="fa" class="fa"
v-if="changedClass" v-if="file.changed || file.tempFile"
:class="changedClass" :class="changedClass"
aria-hidden="true" aria-hidden="true"
> >
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
> >
<repo-tab <repo-tab
v-for="tab in openFiles" v-for="tab in openFiles"
:key="tab.id" :key="tab.key"
:tab="tab" :tab="tab"
/> />
</ul> </ul>
......
...@@ -84,13 +84,13 @@ router.beforeEach((to, from, next) => { ...@@ -84,13 +84,13 @@ router.beforeEach((to, from, next) => {
} }
}) })
.catch((e) => { .catch((e) => {
flash('Error while loading the branch files. Please try again.'); flash('Error while loading the branch files. Please try again.', 'alert', document, null, false, true);
throw e; throw e;
}); });
} }
}) })
.catch((e) => { .catch((e) => {
flash('Error while loading the project data. Please try again.'); flash('Error while loading the project data. Please try again.', 'alert', document, null, false, true);
throw e; throw e;
}); });
} }
......
...@@ -55,7 +55,7 @@ export default class Editor { ...@@ -55,7 +55,7 @@ export default class Editor {
attachModel(model) { attachModel(model) {
this.instance.setModel(model.getModel()); this.instance.setModel(model.getModel());
this.dirtyDiffController.attachModel(model); if (this.dirtyDiffController) this.dirtyDiffController.attachModel(model);
this.currentModel = model; this.currentModel = model;
...@@ -68,7 +68,7 @@ export default class Editor { ...@@ -68,7 +68,7 @@ export default class Editor {
return acc; return acc;
}, {})); }, {}));
this.dirtyDiffController.reDecorate(model); if (this.dirtyDiffController) this.dirtyDiffController.reDecorate(model);
} }
clearEditor() { clearEditor() {
......
...@@ -3,6 +3,7 @@ import { visitUrl } from '../../lib/utils/url_utility'; ...@@ -3,6 +3,7 @@ import { visitUrl } from '../../lib/utils/url_utility';
import flash from '../../flash'; import flash from '../../flash';
import service from '../services'; import service from '../services';
import * as types from './mutation_types'; import * as types from './mutation_types';
import { stripHtml } from '../../lib/utils/text_utility';
export const redirectToUrl = (_, url) => visitUrl(url); export const redirectToUrl = (_, url) => visitUrl(url);
...@@ -81,7 +82,7 @@ export const checkCommitStatus = ({ state }) => ...@@ -81,7 +82,7 @@ export const checkCommitStatus = ({ state }) =>
return false; return false;
}) })
.catch(() => flash('Error checking branch data. Please try again.')); .catch(() => flash('Error checking branch data. Please try again.', 'alert', document, null, false, true));
export const commitChanges = ( export const commitChanges = (
{ commit, state, dispatch, getters }, { commit, state, dispatch, getters },
...@@ -92,7 +93,7 @@ export const commitChanges = ( ...@@ -92,7 +93,7 @@ export const commitChanges = (
.then((data) => { .then((data) => {
const { branch } = payload; const { branch } = payload;
if (!data.short_id) { if (!data.short_id) {
flash(data.message); flash(data.message, 'alert', document, null, false, true);
return; return;
} }
...@@ -105,19 +106,25 @@ export const commitChanges = ( ...@@ -105,19 +106,25 @@ export const commitChanges = (
}, },
}; };
let commitMsg = `Your changes have been committed. Commit ${data.short_id}`;
if (data.stats) {
commitMsg += ` with ${data.stats.additions} additions, ${data.stats.deletions} deletions.`;
}
flash( flash(
`Your changes have been committed. Commit ${data.short_id} with ${ commitMsg,
data.stats.additions
} additions, ${data.stats.deletions} deletions.`,
'notice', 'notice',
); document,
null,
false,
true);
window.dispatchEvent(new Event('resize'));
if (newMr) { if (newMr) {
dispatch('discardAllChanges');
dispatch( dispatch(
'redirectToUrl', 'redirectToUrl',
`${ `${selectedProject.web_url}/merge_requests/new?merge_request%5Bsource_branch%5D=${branch}`,
selectedProject.web_url
}/merge_requests/new?merge_request%5Bsource_branch%5D=${branch}`,
); );
} else { } else {
commit(types.SET_BRANCH_WORKING_REFERENCE, { commit(types.SET_BRANCH_WORKING_REFERENCE, {
...@@ -134,12 +141,18 @@ export const commitChanges = ( ...@@ -134,12 +141,18 @@ export const commitChanges = (
}); });
dispatch('discardAllChanges'); dispatch('discardAllChanges');
dispatch('closeAllFiles');
window.scrollTo(0, 0); window.scrollTo(0, 0);
} }
}) })
.catch(() => flash('Error committing changes. Please try again.')); .catch((err) => {
let errMsg = 'Error committing changes. Please try again.';
if (err.responseJSON && err.responseJSON.message) {
errMsg += ` (${stripHtml(err.responseJSON.message)})`;
}
flash(errMsg, 'alert', document, null, false, true);
window.dispatchEvent(new Event('resize'));
});
export const createTempEntry = ( export const createTempEntry = (
{ state, dispatch }, { state, dispatch },
......
...@@ -17,7 +17,7 @@ export const getBranchData = ( ...@@ -17,7 +17,7 @@ export const getBranchData = (
resolve(data); resolve(data);
}) })
.catch(() => { .catch(() => {
flash('Error loading branch data. Please try again.'); flash('Error loading branch data. Please try again.', 'alert', document, null, false, true);
reject(new Error(`Branch not loaded - ${projectId}/${branchId}`)); reject(new Error(`Branch not loaded - ${projectId}/${branchId}`));
}); });
} else { } else {
......
...@@ -69,7 +69,7 @@ export const getFileData = ({ state, commit, dispatch }, file) => { ...@@ -69,7 +69,7 @@ export const getFileData = ({ state, commit, dispatch }, file) => {
}) })
.catch(() => { .catch(() => {
commit(types.TOGGLE_LOADING, file); commit(types.TOGGLE_LOADING, file);
flash('Error loading file data. Please try again.'); flash('Error loading file data. Please try again.', 'alert', document, null, false, true);
}); });
}; };
...@@ -77,22 +77,28 @@ export const getRawFileData = ({ commit, dispatch }, file) => service.getRawFile ...@@ -77,22 +77,28 @@ export const getRawFileData = ({ commit, dispatch }, file) => service.getRawFile
.then((raw) => { .then((raw) => {
commit(types.SET_FILE_RAW_DATA, { file, raw }); commit(types.SET_FILE_RAW_DATA, { file, raw });
}) })
.catch(() => flash('Error loading file content. Please try again.')); .catch(() => flash('Error loading file content. Please try again.', 'alert', document, null, false, true));
export const changeFileContent = ({ commit }, { file, content }) => { export const changeFileContent = ({ commit }, { file, content }) => {
commit(types.UPDATE_FILE_CONTENT, { file, content }); commit(types.UPDATE_FILE_CONTENT, { file, content });
}; };
export const setFileLanguage = ({ state, commit }, { fileLanguage }) => { export const setFileLanguage = ({ state, commit }, { fileLanguage }) => {
commit(types.SET_FILE_LANGUAGE, { file: state.selectedFile, fileLanguage }); if (state.selectedFile) {
commit(types.SET_FILE_LANGUAGE, { file: state.selectedFile, fileLanguage });
}
}; };
export const setFileEOL = ({ state, commit }, { eol }) => { export const setFileEOL = ({ state, commit }, { eol }) => {
commit(types.SET_FILE_EOL, { file: state.selectedFile, eol }); if (state.selectedFile) {
commit(types.SET_FILE_EOL, { file: state.selectedFile, eol });
}
}; };
export const setEditorPosition = ({ state, commit }, { editorRow, editorColumn }) => { export const setEditorPosition = ({ state, commit }, { editorRow, editorColumn }) => {
commit(types.SET_FILE_POSITION, { file: state.selectedFile, editorRow, editorColumn }); if (state.selectedFile) {
commit(types.SET_FILE_POSITION, { file: state.selectedFile, editorRow, editorColumn });
}
}; };
export const createTempFile = ({ state, commit, dispatch }, { projectId, branchId, parent, name, content = '', base64 = '' }) => { export const createTempFile = ({ state, commit, dispatch }, { projectId, branchId, parent, name, content = '', base64 = '' }) => {
...@@ -112,7 +118,7 @@ export const createTempFile = ({ state, commit, dispatch }, { projectId, branchI ...@@ -112,7 +118,7 @@ export const createTempFile = ({ state, commit, dispatch }, { projectId, branchI
url: newUrl, url: newUrl,
}); });
if (findEntry(parent.tree, 'blob', file.name)) return flash(`The name "${file.name}" is already taken in this directory.`); if (findEntry(parent.tree, 'blob', file.name)) return flash(`The name "${file.name}" is already taken in this directory.`, 'alert', document, null, false, true);
commit(types.CREATE_TMP_FILE, { commit(types.CREATE_TMP_FILE, {
parent, parent,
......
...@@ -18,7 +18,7 @@ export const getProjectData = ( ...@@ -18,7 +18,7 @@ export const getProjectData = (
resolve(data); resolve(data);
}) })
.catch(() => { .catch(() => {
flash('Error loading project data. Please try again.'); flash('Error loading project data. Please try again.', 'alert', document, null, false, true);
reject(new Error(`Project not loaded ${namespace}/${projectId}`)); reject(new Error(`Project not loaded ${namespace}/${projectId}`));
}); });
} else { } else {
......
...@@ -52,7 +52,7 @@ export const getTreeData = ( ...@@ -52,7 +52,7 @@ export const getTreeData = (
resolve(data); resolve(data);
}) })
.catch((e) => { .catch((e) => {
flash('Error loading tree data. Please try again.'); flash('Error loading tree data. Please try again.', 'alert', document, null, false, true);
if (tree) commit(types.TOGGLE_LOADING, tree); if (tree) commit(types.TOGGLE_LOADING, tree);
reject(e); reject(e);
}); });
...@@ -151,7 +151,7 @@ export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = s ...@@ -151,7 +151,7 @@ export const getLastCommitData = ({ state, commit, dispatch, getters }, tree = s
dispatch('getLastCommitData', tree); dispatch('getLastCommitData', tree);
}) })
.catch(() => flash('Error fetching log data.')); .catch(() => flash('Error fetching log data.', 'alert', document, null, false, true));
}; };
export const updateDirectoryData = ( export const updateDirectoryData = (
......
...@@ -64,7 +64,7 @@ export default { ...@@ -64,7 +64,7 @@ export default {
}, },
[types.DISCARD_FILE_CHANGES](state, file) { [types.DISCARD_FILE_CHANGES](state, file) {
Object.assign(file, { Object.assign(file, {
content: '', content: file.raw,
changed: false, changed: false,
}); });
}, },
......
...@@ -11,6 +11,14 @@ class AutoWidthDropdownSelect { ...@@ -11,6 +11,14 @@ class AutoWidthDropdownSelect {
const dropdownClass = this.dropdownClass; const dropdownClass = this.dropdownClass;
this.$selectElement.select2({ this.$selectElement.select2({
dropdownCssClass: dropdownClass, dropdownCssClass: dropdownClass,
...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
});
return this;
}
static selectOptions(dropdownClass) {
return {
dropdownCss() { dropdownCss() {
let resultantWidth = 'auto'; let resultantWidth = 'auto';
const $dropdown = $(`.${dropdownClass}`); const $dropdown = $(`.${dropdownClass}`);
...@@ -29,9 +37,7 @@ class AutoWidthDropdownSelect { ...@@ -29,9 +37,7 @@ class AutoWidthDropdownSelect {
maxWidth: offsetParentWidth, maxWidth: offsetParentWidth,
}; };
}, },
}); };
return this;
} }
} }
......
...@@ -6,6 +6,7 @@ import Autosave from './autosave'; ...@@ -6,6 +6,7 @@ import Autosave from './autosave';
import UsersSelect from './users_select'; import UsersSelect from './users_select';
import GfmAutoComplete from './gfm_auto_complete'; import GfmAutoComplete from './gfm_auto_complete';
import ZenMode from './zen_mode'; import ZenMode from './zen_mode';
import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
import { parsePikadayDate, pikadayToString } from './lib/utils/datefix'; import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
export default class IssuableForm { export default class IssuableForm {
...@@ -46,6 +47,12 @@ export default class IssuableForm { ...@@ -46,6 +47,12 @@ export default class IssuableForm {
}); });
calendar.setDate(parsePikadayDate($issuableDueDate.val())); calendar.setDate(parsePikadayDate($issuableDueDate.val()));
} }
this.$targetBranchSelect = $('.js-target-branch-select', this.form);
if (this.$targetBranchSelect.length) {
this.initTargetBranchDropdown();
}
} }
initAutosave() { initAutosave() {
...@@ -104,4 +111,37 @@ export default class IssuableForm { ...@@ -104,4 +111,37 @@ export default class IssuableForm {
addWip() { addWip() {
this.titleField.val(`WIP: ${(this.titleField.val())}`); this.titleField.val(`WIP: ${(this.titleField.val())}`);
} }
initTargetBranchDropdown() {
this.$targetBranchSelect.select2({
...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
ajax: {
url: this.$targetBranchSelect.data('endpoint'),
dataType: 'JSON',
quietMillis: 250,
data(search) {
return {
search,
};
},
results(data) {
return {
// `data` keys are translated so we can't just access them with a string based key
results: data[Object.keys(data)[0]].map(name => ({
id: name,
text: name,
})),
};
},
},
initSelection(el, callback) {
const val = el.val();
callback({
id: val,
text: val,
});
},
});
}
} }
...@@ -152,6 +152,13 @@ ...@@ -152,6 +152,13 @@
hasUpdated() { hasUpdated() {
return !!this.state.updatedAt; return !!this.state.updatedAt;
}, },
issueChanged() {
const descriptionChanged =
this.initialDescriptionText !== this.store.formState.description;
const titleChanged =
this.initialTitleText !== this.store.formState.title;
return descriptionChanged || titleChanged;
},
}, },
created() { created() {
this.service = new Service(this.endpoint); this.service = new Service(this.endpoint);
...@@ -176,6 +183,8 @@ ...@@ -176,6 +183,8 @@
} }
}); });
window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
eventHub.$on('delete.issuable', this.deleteIssuable); eventHub.$on('delete.issuable', this.deleteIssuable);
eventHub.$on('update.issuable', this.updateIssuable); eventHub.$on('update.issuable', this.updateIssuable);
eventHub.$on('close.form', this.closeForm); eventHub.$on('close.form', this.closeForm);
...@@ -186,8 +195,17 @@ ...@@ -186,8 +195,17 @@
eventHub.$off('update.issuable', this.updateIssuable); eventHub.$off('update.issuable', this.updateIssuable);
eventHub.$off('close.form', this.closeForm); eventHub.$off('close.form', this.closeForm);
eventHub.$off('open.form', this.openForm); eventHub.$off('open.form', this.openForm);
window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent);
}, },
methods: { methods: {
handleBeforeUnloadEvent(e) {
const event = e;
if (this.showForm && this.issueChanged) {
event.returnValue = 'Are you sure you want to lose your issue information?';
}
return undefined;
},
openForm() { openForm() {
if (!this.showForm) { if (!this.showForm) {
this.showForm = true; this.showForm = true;
......
...@@ -3,7 +3,6 @@ import { visitUrl } from './lib/utils/url_utility'; ...@@ -3,7 +3,6 @@ import { visitUrl } from './lib/utils/url_utility';
import bp from './breakpoints'; import bp from './breakpoints';
import { numberToHumanSize } from './lib/utils/number_utils'; import { numberToHumanSize } from './lib/utils/number_utils';
import { setCiStatusFavicon } from './lib/utils/common_utils'; import { setCiStatusFavicon } from './lib/utils/common_utils';
import { timeFor } from './lib/utils/datetime_utility';
export default class Job { export default class Job {
constructor(options) { constructor(options) {
...@@ -71,7 +70,6 @@ export default class Job { ...@@ -71,7 +70,6 @@ export default class Job {
.off('resize.build') .off('resize.build')
.on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100)); .on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100));
this.updateArtifactRemoveDate();
this.initAffixTopArea(); this.initAffixTopArea();
this.getBuildTrace(); this.getBuildTrace();
...@@ -261,16 +259,7 @@ export default class Job { ...@@ -261,16 +259,7 @@ export default class Job {
sidebarOnClick() { sidebarOnClick() {
if (this.shouldHideSidebarForViewport()) this.toggleSidebar(); if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
} }
// eslint-disable-next-line class-methods-use-this, consistent-return
updateArtifactRemoveDate() {
const $date = $('.js-artifacts-remove');
if ($date.length) {
const date = $date.text();
return $date.text(
timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3'))),
);
}
}
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
populateJobs(stage) { populateJobs(stage) {
$('.build-job').hide(); $('.build-job').hide();
......
...@@ -231,7 +231,7 @@ export default class LabelsSelect { ...@@ -231,7 +231,7 @@ export default class LabelsSelect {
selectedClass.push('label-item'); selectedClass.push('label-item');
$a.attr('data-label-id', label.id); $a.attr('data-label-id', label.id);
} }
$a.addClass(selectedClass.join(' ')).html(colorEl + " " + label.title); $a.addClass(selectedClass.join(' ')).html(`${colorEl} ${_.escape(label.title)}`);
// Return generated html // Return generated html
return $li.html($a).prop('outerHTML'); return $li.html($a).prop('outerHTML');
}, },
......
...@@ -72,4 +72,4 @@ export function capitalizeFirstCharacter(text) { ...@@ -72,4 +72,4 @@ export function capitalizeFirstCharacter(text) {
* @param {*} replace * @param {*} replace
* @returns {String} * @returns {String}
*/ */
export const stripeHtml = (string, replace = '') => string.replace(/<[^>]*>/g, replace); export const stripHtml = (string, replace = '') => string.replace(/<[^>]*>/g, replace);
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, max-len, prefer-arrow-callback */ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, max-len, prefer-arrow-callback */
import 'vendor/jquery.waitforimages'; import 'vendor/jquery.waitforimages';
import { __ } from '~/locale';
import TaskList from './task_list'; import TaskList from './task_list';
import MergeRequestTabs from './merge_request_tabs'; import MergeRequestTabs from './merge_request_tabs';
import IssuablesHelper from './helpers/issuables_helper'; import IssuablesHelper from './helpers/issuables_helper';
...@@ -110,12 +111,12 @@ MergeRequest.prototype.initCommitMessageListeners = function() { ...@@ -110,12 +111,12 @@ MergeRequest.prototype.initCommitMessageListeners = function() {
}); });
}; };
MergeRequest.updateStatusText = function(classToRemove, classToAdd, newStatusText) { MergeRequest.setStatusBoxToMerged = function() {
$('.detail-page-header .status-box') $('.detail-page-header .status-box')
.removeClass(classToRemove) .removeClass('status-box-open')
.addClass(classToAdd) .addClass('status-box-mr-merged')
.find('span') .find('span')
.text(newStatusText); .text(__('Merged'));
}; };
MergeRequest.decreaseCounter = function(by = 1) { MergeRequest.decreaseCounter = function(by = 1) {
......
import Vue from 'vue'; import Vue from 'vue';
import Dashboard from './components/dashboard.vue'; import Dashboard from './components/dashboard.vue';
document.addEventListener('DOMContentLoaded', () => new Vue({ export default () => new Vue({
el: '#prometheus-graphs', el: '#prometheus-graphs',
render: createElement => createElement(Dashboard), render: createElement => createElement(Dashboard),
})); });
<script> <script>
/* global katex */ /* global katex */
import marked from 'marked'; import marked from 'marked';
import sanitize from 'sanitize-html';
import Prompt from './prompt.vue'; import Prompt from './prompt.vue';
const renderer = new marked.Renderer(); const renderer = new marked.Renderer();
...@@ -82,7 +83,12 @@ ...@@ -82,7 +83,12 @@
}, },
computed: { computed: {
markdown() { markdown() {
return marked(this.cell.source.join('').replace(/\\/g, '\\\\')); return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), {
allowedTags: false,
allowedAttributes: {
'*': ['class'],
},
});
}, },
}, },
}; };
......
<script> <script>
import sanitize from 'sanitize-html';
import Prompt from '../prompt.vue'; import Prompt from '../prompt.vue';
export default { export default {
...@@ -11,12 +12,24 @@ ...@@ -11,12 +12,24 @@
required: true, required: true,
}, },
}, },
computed: {
sanitizedOutput() {
return sanitize(this.rawCode, {
allowedTags: sanitize.defaults.allowedTags.concat([
'img', 'svg',
]),
allowedAttributes: {
img: ['src'],
},
});
},
},
}; };
</script> </script>
<template> <template>
<div class="output"> <div class="output">
<prompt /> <prompt />
<div v-html="rawCode"></div> <div v-html="sanitizedOutput"></div>
</div> </div>
</template> </template>
...@@ -66,9 +66,7 @@ ...@@ -66,9 +66,7 @@
<template> <template>
<div class="note-header-info"> <div class="note-header-info">
<a :href="author.path"> <a :href="author.path">
<span class="note-header-author-name"> <span class="note-header-author-name">{{ author.name }}</span>
{{ author.name }}
</span>
<span class="note-headline-light"> <span class="note-headline-light">
@{{ author.username }} @{{ author.username }}
</span> </span>
......
<script>
import axios from '~/lib/utils/axios_utils';
import Flash from '~/flash';
import modal from '~/vue_shared/components/modal.vue';
import { s__ } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
export default {
components: {
modal,
},
props: {
url: {
type: String,
required: true,
},
},
computed: {
text() {
return s__('AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running.');
},
},
methods: {
onSubmit() {
return axios.post(this.url)
.then((response) => {
// follow the rediect to refresh the page
redirectTo(response.request.responseURL);
})
.catch((error) => {
Flash(s__('AdminArea|Stopping jobs failed'));
throw error;
});
},
},
};
</script>
<template>
<modal
id="stop-jobs-modal"
:title="s__('AdminArea|Stop all jobs?')"
:text="text"
kind="danger"
:primary-button-label="s__('AdminArea|Stop jobs')"
@submit="onSubmit" />
</template>
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import stopJobsModal from './components/stop_jobs_modal.vue';
Vue.use(Translate);
export default () => {
const stopJobsButton = document.getElementById('stop-jobs-button');
// eslint-disable-next-line no-new
new Vue({
el: '#stop-jobs-modal',
components: {
stopJobsModal,
},
mounted() {
stopJobsButton.classList.remove('disabled');
},
render(createElement) {
return createElement('stop-jobs-modal', {
props: {
url: stopJobsButton.dataset.url,
},
});
},
});
};
/* eslint-disable import/prefer-default-export */
export const FILTERED_SEARCH = {
MERGE_REQUESTS: 'merge_requests',
ISSUES: 'issues',
};
import initGroupsList from '../../../../groups';
export default () => {
initGroupsList();
};
import GroupsList from '~/groups_list'; import GroupsList from '~/groups_list';
import Landing from '~/landing'; import Landing from '~/landing';
import initGroupsList from '../../../groups';
export default function () { export default function () {
new GroupsList(); // eslint-disable-line no-new new GroupsList(); // eslint-disable-line no-new
initGroupsList();
const landingElement = document.querySelector('.js-explore-groups-landing'); const landingElement = document.querySelector('.js-explore-groups-landing');
if (!landingElement) return; if (!landingElement) return;
const exploreGroupsLanding = new Landing( const exploreGroupsLanding = new Landing(
......
import Activities from '~/activities';
export default () => new Activities();
import groupAvatar from '~/group_avatar';
export default groupAvatar;
/* eslint-disable no-new */
import memberExpirationDate from '~/member_expiration_date';
import Members from '~/members';
import UsersSelect from '~/users_select';
export default () => {
memberExpirationDate();
new Members();
new UsersSelect();
};
import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
export default () => {
initFilteredSearch(FILTERED_SEARCH.ISSUES);
projectSelect();
};
import Labels from '~/labels';
export default () => new Labels();
import initLabels from '~/init_labels';
export default initLabels;
import Labels from '~/labels';
export default () => new Labels();
import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
export default () => {
initFilteredSearch(FILTERED_SEARCH.MERGE_REQUESTS);
projectSelect();
};
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
export default initMilestonesShow;
import BindInOut from '~/behaviors/bind_in_out';
import Group from '~/group';
import groupAvatar from '~/group_avatar';
export default () => {
BindInOut.initAll();
new Group(); // eslint-disable-line no-new
groupAvatar();
};
import SecretValues from '~/behaviors/secret_values';
export default () => {
const secretVariableTable = document.querySelector('.js-secret-variable-table');
if (secretVariableTable) {
const secretVariableTableValues = new SecretValues({
container: secretVariableTable,
});
secretVariableTableValues.init();
}
};
/* eslint-disable no-new */
import NewGroupChild from '~/groups/new_group_child';
import notificationsDropdown from '~/notifications_dropdown';
import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/shortcuts_navigation';
import initGroupsList from '../../../groups';
export default () => {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
new ShortcutsNavigation();
new NotificationsForm();
notificationsDropdown();
new ProjectsList();
if (newGroupChildWrapper) {
new NewGroupChild(newGroupChildWrapper);
}
initGroupsList();
};
<script>
import axios from '~/lib/utils/axios_utils';
import Flash from '~/flash';
import modal from '~/vue_shared/components/modal.vue';
import { n__, s__, sprintf } from '~/locale';
import { redirectTo } from '~/lib/utils/url_utility';
import eventHub from '../event_hub';
export default {
components: {
modal,
},
props: {
issueCount: {
type: Number,
required: true,
},
mergeRequestCount: {
type: Number,
required: true,
},
milestoneId: {
type: Number,
required: true,
},
milestoneTitle: {
type: String,
required: true,
},
milestoneUrl: {
type: String,
required: true,
},
},
computed: {
text() {
const milestoneTitle = sprintf('<strong>%{milestoneTitle}</strong>', { milestoneTitle: this.milestoneTitle });
if (this.issueCount === 0 && this.mergeRequestCount === 0) {
return sprintf(
s__(`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle} from this project.
%{milestoneTitle} is not currently used in any issues or merge requests.`),
{
milestoneTitle,
},
false,
);
}
return sprintf(
s__(`Milestones|
You’re about to permanently delete the milestone %{milestoneTitle} from this project and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}.
Once deleted, it cannot be undone or recovered.`),
{
milestoneTitle,
issuesWithCount: n__('%d issue', '%d issues', this.issueCount),
mergeRequestsWithCount: n__('%d merge request', '%d merge requests', this.mergeRequestCount),
},
false,
);
},
title() {
return sprintf(s__('Milestones|Delete milestone %{milestoneTitle}?'), { milestoneTitle: this.milestoneTitle });
},
},
methods: {
onSubmit() {
eventHub.$emit('deleteMilestoneModal.requestStarted', this.milestoneUrl);
return axios.delete(this.milestoneUrl)
.then((response) => {
eventHub.$emit('deleteMilestoneModal.requestFinished', { milestoneUrl: this.milestoneUrl, successful: true });
// follow the rediect to milestones overview page
redirectTo(response.request.responseURL);
})
.catch((error) => {
eventHub.$emit('deleteMilestoneModal.requestFinished', { milestoneUrl: this.milestoneUrl, successful: false });
if (error.response && error.response.status === 404) {
Flash(sprintf(s__('Milestones|Milestone %{milestoneTitle} was not found'), { milestoneTitle: this.milestoneTitle }));
} else {
Flash(sprintf(s__('Milestones|Failed to delete milestone %{milestoneTitle}'), { milestoneTitle: this.milestoneTitle }));
}
throw error;
});
},
},
};
</script>
<template>
<modal
id="delete-milestone-modal"
:title="title"
:text="text"
kind="danger"
:primary-button-label="s__('Milestones|Delete milestone')"
@submit="onSubmit">
<template
slot="body"
slot-scope="props">
<p v-html="props.text"></p>
</template>
</modal>
</template>
import Vue from 'vue';
export default new Vue();
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import deleteMilestoneModal from './components/delete_milestone_modal.vue';
import eventHub from './event_hub';
export default () => {
Vue.use(Translate);
const onRequestFinished = ({ milestoneUrl, successful }) => {
const button = document.querySelector(`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`);
if (!successful) {
button.removeAttribute('disabled');
}
button.querySelector('.js-loading-icon').classList.add('hidden');
};
const onRequestStarted = (milestoneUrl) => {
const button = document.querySelector(`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`);
button.setAttribute('disabled', '');
button.querySelector('.js-loading-icon').classList.remove('hidden');
eventHub.$once('deleteMilestoneModal.requestFinished', onRequestFinished);
};
const onDeleteButtonClick = (event) => {
const button = event.currentTarget;
const modalProps = {
milestoneId: parseInt(button.dataset.milestoneId, 10),
milestoneTitle: button.dataset.milestoneTitle,
milestoneUrl: button.dataset.milestoneUrl,
issueCount: parseInt(button.dataset.milestoneIssueCount, 10),
mergeRequestCount: parseInt(button.dataset.milestoneMergeRequestCount, 10),
};
eventHub.$once('deleteMilestoneModal.requestStarted', onRequestStarted);
eventHub.$emit('deleteMilestoneModal.props', modalProps);
};
const deleteMilestoneButtons = document.querySelectorAll('.js-delete-milestone-button');
for (let i = 0; i < deleteMilestoneButtons.length; i += 1) {
const button = deleteMilestoneButtons[i];
button.addEventListener('click', onDeleteButtonClick);
}
eventHub.$once('deleteMilestoneModal.mounted', () => {
for (let i = 0; i < deleteMilestoneButtons.length; i += 1) {
const button = deleteMilestoneButtons[i];
button.removeAttribute('disabled');
}
});
return new Vue({
el: '#delete-milestone-modal',
components: {
deleteMilestoneModal,
},
data() {
return {
modalProps: {
milestoneId: -1,
milestoneTitle: '',
milestoneUrl: '',
issueCount: -1,
mergeRequestCount: -1,
},
};
},
mounted() {
eventHub.$on('deleteMilestoneModal.props', this.setModalProps);
eventHub.$emit('deleteMilestoneModal.mounted');
},
beforeDestroy() {
eventHub.$off('deleteMilestoneModal.props', this.setModalProps);
},
methods: {
setModalProps(modalProps) {
this.modalProps = modalProps;
},
},
render(createElement) {
return createElement(deleteMilestoneModal, {
props: this.modalProps,
});
},
});
};
/* eslint-disable no-new */
import Milestone from '~/milestone';
import Sidebar from '~/right_sidebar';
export default () => {
new Milestone();
new Sidebar();
};
import initU2F from '../../shared/sessions/u2f';
export default () => {
initU2F();
};
/* eslint-disable import/prefer-default-export */
export const ISSUABLE_INDEX = {
MERGE_REQUEST: 'merge_request_',
ISSUE: 'issue_',
};
import initSettingsPanels from '~/settings_panels'; import initSettingsPanels from '~/settings_panels';
import setupProjectEdit from '~/project_edit'; import setupProjectEdit from '~/project_edit';
import ProjectNew from '../shared/project_new';
import projectAvatar from '../shared/project_avatar';
import initProjectPermissionsSettings from '../shared/permissions';
export default () => { export default () => {
new ProjectNew(); // eslint-disable-line no-new
setupProjectEdit(); setupProjectEdit();
// Initialize expandable settings panels // Initialize expandable settings panels
initSettingsPanels(); initSettingsPanels();
projectAvatar();
initProjectPermissionsSettings();
}; };
import monitoringBundle from '~/monitoring/monitoring_bundle';
export default monitoringBundle;
import Project from './project';
import ShortcutsNavigation from '../../shortcuts_navigation';
export default () => {
new Project(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
};
import ZenMode from '~/zen_mode';
import GLForm from '~/gl_form';
export default function ($formEl) {
new ZenMode(); // eslint-disable-line no-new
new GLForm($formEl, true); // eslint-disable-line no-new
}
/* eslint-disable no-new */ /* eslint-disable no-new */
import IssuableIndex from '~/issuable_index'; import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
import UsersSelect from '~/users_select'; import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
export default () => { export default () => {
const filteredSearchEnabled = gl.FilteredSearchManager && document.querySelector('.filtered-search'); initFilteredSearch(FILTERED_SEARCH.ISSUES);
if (filteredSearchEnabled) { new IssuableIndex(ISSUABLE_INDEX.ISSUE);
const filteredSearchManager = new gl.FilteredSearchManager('issues');
filteredSearchManager.setup();
}
new IssuableIndex('issue_');
new ShortcutsNavigation(); new ShortcutsNavigation();
new UsersSelect(); new UsersSelect();
......
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
export default initMergeRequest;
import Compare from '~/compare';
import MergeRequest from '~/merge_request';
export default () => {
const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
if (mrNewCompareNode) {
new Compare({ // eslint-disable-line no-new
targetProjectUrl: mrNewCompareNode.dataset.targetProjectUrl,
sourceBranchUrl: mrNewCompareNode.dataset.sourceBranchUrl,
targetBranchUrl: mrNewCompareNode.dataset.targetBranchUrl,
});
} else {
const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit');
new MergeRequest({ // eslint-disable-line no-new
action: mrNewSubmitNode.dataset.mrSubmitAction,
});
}
};
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
export default initMergeRequest;
import IssuableIndex from '~/issuable_index'; import IssuableIndex from '~/issuable_index';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
import UsersSelect from '~/users_select'; import UsersSelect from '~/users_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
export default () => { export default () => {
const filteredSearchEnabled = gl.FilteredSearchManager && document.querySelector('.filtered-search'); initFilteredSearch(FILTERED_SEARCH.MERGE_REQUESTS);
new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
if (filteredSearchEnabled) {
const filteredSearchManager = new gl.FilteredSearchManager('merge_requests');
filteredSearchManager.setup();
}
new IssuableIndex('merge_request_'); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new new UsersSelect(); // eslint-disable-line no-new
}; };
/* eslint-disable no-new */
import Diff from '~/diff';
import ShortcutsNavigation from '~/shortcuts_navigation';
import GLForm from '~/gl_form';
import IssuableForm from '~/issuable_form';
import LabelsSelect from '~/labels_select';
import MilestoneSelect from '~/milestone_select';
import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
export default () => {
new Diff();
new ShortcutsNavigation();
new GLForm($('.merge-request-form'), true);
new IssuableForm($('.merge-request-form'));
new LabelsSelect();
new MilestoneSelect();
new IssuableTemplateSelectors();
};
import milestones from '~/pages/milestones/shared';
export default milestones;
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
import milestones from '~/pages/milestones/shared';
export default () => {
initMilestonesShow();
milestones();
};
import ProjectNew from '../shared/project_new';
import initProjectVisibilitySelector from '../../../project_visibility';
import initProjectNew from '../../../projects/project_new';
export default () => {
new ProjectNew(); // eslint-disable-line no-new
initProjectVisibilitySelector();
initProjectNew.bindEvents();
};
/* eslint-disable func-names, space-before-function-paren, no-var, consistent-return, no-new, prefer-arrow-callback, no-return-assign, one-var, one-var-declaration-per-line, object-shorthand, no-else-return, newline-per-chained-call, no-shadow, vars-on-top, prefer-template, max-len */ /* eslint-disable func-names, space-before-function-paren, no-var, consistent-return, no-new, prefer-arrow-callback, no-return-assign, one-var, one-var-declaration-per-line, object-shorthand, no-else-return, newline-per-chained-call, no-shadow, vars-on-top, prefer-template, max-len */
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import { visitUrl } from './lib/utils/url_utility'; import { visitUrl } from '../../lib/utils/url_utility';
import projectSelect from './project_select'; import projectSelect from '../../project_select';
export default class Project { export default class Project {
constructor() { constructor() {
......
import initForm from '~/pages/projects/init_form';
export default initForm($('.release-form'));
import initSettingsPanels from '~/settings_panels';
import SecretValues from '~/behaviors/secret_values';
export default function () {
// Initialize expandable settings panels
initSettingsPanels();
const runnerToken = document.querySelector('.js-secret-runner-token');
if (runnerToken) {
const runnerTokenSecretValue = new SecretValues({
container: runnerToken,
});
runnerTokenSecretValue.init();
}
const secretVariableTable = document.querySelector('.js-secret-variable-table');
if (secretVariableTable) {
const secretVariableTableValues = new SecretValues({
container: secretVariableTable,
});
secretVariableTableValues.init();
}
}
import initSettingsPanels from '~/settings_panels';
export default initSettingsPanels;
<script> <script>
import projectFeatureToggle from '../../../vue_shared/components/toggle_button.vue'; import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
export default { export default {
components: { components: {
......
<script> <script>
import projectFeatureSetting from './project_feature_setting.vue'; import projectFeatureSetting from './project_feature_setting.vue';
import projectFeatureToggle from '../../../vue_shared/components/toggle_button.vue'; import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
import projectSettingRow from './project_setting_row.vue'; import projectSettingRow from './project_setting_row.vue';
import { visibilityOptions, visibilityLevelDescriptions } from '../constants'; import { visibilityOptions, visibilityLevelDescriptions } from '../constants';
import { toggleHiddenClassBySelector } from '../external'; import { toggleHiddenClassBySelector } from '../external';
...@@ -215,7 +215,7 @@ ...@@ -215,7 +215,7 @@
</div> </div>
<span class="help-block">{{ visibilityLevelDescription }}</span> <span class="help-block">{{ visibilityLevelDescription }}</span>
<label <label
v-if="visibilityLevel !== visibilityOptions.PUBLIC" v-if="visibilityLevel !== visibilityOptions.PRIVATE"
class="request-access" class="request-access"
> >
<input <input
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment