Commit b20c7846 authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge remote-tracking branch 'upstream/master' into show-commit-status-from-latest-pipeline

* upstream/master: (754 commits)
  Add documentation about todos and failed builds
  Add Changelog entry for failed builds todos fix
  Do not create TODO when build is allowed to fail
  Fix 404 on some group pages when name contains dot
  Grapify the users API
  Remove duplicate sidekiq throttling parameters
  Fix regression in Merge request form
  Fix wrong link
  Fix test
  Fix broken test
  Changes for stop url to path
  fix typo in gitlab_flow.md ('munch'->'much')
  Fix spec
  Backport some changes done from Time Tracking feature in EE.
  Use build instead create in BroadcastMessage model spec
  Try to fix tests
  Remove unnecessary self from user model
  Expose stop_path for environment to not construct that in frontend
  Bring back the `commit_url` as it's used by CycleAnalytics
  Add api endpoint for creating a pipeline
  ...
parents f593abbc 77a43827

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

CHANGELOG.md merge=union
*.js.es6 gitlab-language=javascript *.js.es6 gitlab-language=javascript
...@@ -61,20 +61,33 @@ update-knapsack: ...@@ -61,20 +61,33 @@ update-knapsack:
- scripts/merge-reports knapsack/spinach_report.json knapsack/spinach_node_*.json - scripts/merge-reports knapsack/spinach_report.json knapsack/spinach_node_*.json
- rm -f knapsack/*_node_*.json - rm -f knapsack/*_node_*.json
only: only:
- master - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
# Execute all testing suites - master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
.use-db: &use-db .use-db: &use-db
services: services:
- mysql:latest - mysql:latest
- redis:alpine - redis:alpine
setup-test-env:
<<: *use-db
stage: prepare
script:
- bundle exec rake assets:precompile 2>/dev/null
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
artifacts:
expire_in: 7d
paths:
- public/assets
- tmp/tests
.rspec-knapsack: &rspec-knapsack .rspec-knapsack: &rspec-knapsack
stage: test stage: test
<<: *use-db <<: *use-db
script: script:
- bundle exec rake assets:precompile 2>/dev/null
- JOB_NAME=( $CI_BUILD_NAME ) - JOB_NAME=( $CI_BUILD_NAME )
- export CI_NODE_INDEX=${JOB_NAME[1]} - export CI_NODE_INDEX=${JOB_NAME[1]}
- export CI_NODE_TOTAL=${JOB_NAME[2]} - export CI_NODE_TOTAL=${JOB_NAME[2]}
...@@ -92,7 +105,6 @@ update-knapsack: ...@@ -92,7 +105,6 @@ update-knapsack:
stage: test stage: test
<<: *use-db <<: *use-db
script: script:
- bundle exec rake assets:precompile 2>/dev/null
- JOB_NAME=( $CI_BUILD_NAME ) - JOB_NAME=( $CI_BUILD_NAME )
- export CI_NODE_INDEX=${JOB_NAME[1]} - export CI_NODE_INDEX=${JOB_NAME[1]}
- export CI_NODE_TOTAL=${JOB_NAME[2]} - export CI_NODE_TOTAL=${JOB_NAME[2]}
...@@ -143,7 +155,10 @@ spinach 9 10: *spinach-knapsack ...@@ -143,7 +155,10 @@ spinach 9 10: *spinach-knapsack
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.1-git-2.7-phantomjs-2.1" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.1-git-2.7-phantomjs-2.1"
<<: *use-db <<: *use-db
only: only:
- master - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
cache: cache:
key: "ruby21" key: "ruby21"
paths: paths:
...@@ -213,11 +228,24 @@ rake downtime_check: *exec ...@@ -213,11 +228,24 @@ rake downtime_check: *exec
rake ee_compat_check: rake ee_compat_check:
<<: *exec <<: *exec
only: only:
- branches - branches@gitlab-org/gitlab-ce
- branches@gitlab/gitlabhq
except: except:
- master - master
- tags - tags
- /^[\d-]+-stable(-ee)?$/
allow_failure: yes allow_failure: yes
cache:
key: "ruby231-ee_compat_check_repo"
paths:
- ee_compat_check/repo/
- vendor/ruby
artifacts:
name: "${CI_BUILD_NAME}_${CI_BUILD_REF_NAME}_${CI_BUILD_REF}"
when: on_failure
expire_in: 10d
paths:
- ee_compat_check/patches/*.patch
rake db:migrate:reset: rake db:migrate:reset:
stage: test stage: test
...@@ -273,7 +301,10 @@ bundler:audit: ...@@ -273,7 +301,10 @@ bundler:audit:
stage: test stage: test
<<: *ruby-static-analysis <<: *ruby-static-analysis
only: only:
- master - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
script: script:
- "bundle exec bundle-audit check --update --ignore OSVDB-115941" - "bundle exec bundle-audit check --update --ignore OSVDB-115941"
...@@ -284,6 +315,9 @@ migration paths: ...@@ -284,6 +315,9 @@ migration paths:
SETUP_DB: "false" SETUP_DB: "false"
only: only:
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
- master@gitlab/gitlabhq
- master@gitlab/gitlab-ee
script: script:
- git checkout HEAD . - git checkout HEAD .
- git fetch --tags - git fetch --tags
...@@ -331,7 +365,7 @@ trigger_docs: ...@@ -331,7 +365,7 @@ trigger_docs:
cache: {} cache: {}
artifacts: {} artifacts: {}
script: script:
- "curl -X POST -F token=${DOCS_TRIGGER_TOKEN} -F ref=master -F variables[PROJECT]=ce https://gitlab.com/api/v3/projects/38069/trigger/builds" - "curl -X POST -F token=${DOCS_TRIGGER_TOKEN} -F ref=master -F variables[PROJECT]=ce https://gitlab.com/api/v3/projects/1794617/trigger/builds"
only: only:
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
......
...@@ -12,6 +12,7 @@ entry. ...@@ -12,6 +12,7 @@ entry.
- Trim leading and trailing whitespace on project_path (Linus Thiel) - Trim leading and trailing whitespace on project_path (Linus Thiel)
- Prevent award emoji via notes for issues/MRs authored by user (barthc) - Prevent award emoji via notes for issues/MRs authored by user (barthc)
- Adds support for the `token` attribute in project hooks API (Gauvain Pocentek) - Adds support for the `token` attribute in project hooks API (Gauvain Pocentek)
- Change auto selection behaviour of emoji and slash commands to be more UX/Type friendly (Yann Gravrand)
- Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO) - Adds an optional path parameter to the Commits API to filter commits by path (Luis HGO)
- Fix Markdown styling inside reference links (Jan Zdráhal) - Fix Markdown styling inside reference links (Jan Zdráhal)
- Create new issue board list after creating a new label - Create new issue board list after creating a new label
...@@ -19,6 +20,7 @@ entry. ...@@ -19,6 +20,7 @@ entry.
- Fail gracefully when creating merge request with non-existing branch (alexsanford) - Fail gracefully when creating merge request with non-existing branch (alexsanford)
- Fix mobile layout issues in admin user overview page !7087 - Fix mobile layout issues in admin user overview page !7087
- Fix HipChat notifications rendering (airatshigapov, eisnerd) - Fix HipChat notifications rendering (airatshigapov, eisnerd)
- Removed unneeded "Builds" and "Environments" link from project titles
- Remove 'Edit' button from wiki edit view !7143 (Hiroyuki Sato) - Remove 'Edit' button from wiki edit view !7143 (Hiroyuki Sato)
- Cleaned up global namespace JS !19661 (Jose Ivan Vargas) - Cleaned up global namespace JS !19661 (Jose Ivan Vargas)
- Refactor Jira service to use jira-ruby gem - Refactor Jira service to use jira-ruby gem
...@@ -71,14 +73,49 @@ entry. ...@@ -71,14 +73,49 @@ entry.
- Fix applying GitHub-imported labels when importing job is interrupted - Fix applying GitHub-imported labels when importing job is interrupted
- Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar) - Allow to search for user by secondary email address in the admin interface(/admin/users) !7115 (YarNayar)
- Updated commit SHA styling on the branches page. - Updated commit SHA styling on the branches page.
- Fix "Without projects" filter. !6611 (Ben Bodenmiller)
- Fix 404 when visit /projects page
## 8.13.6 (2016-11-17)
- Omniauth auto link LDAP user falls back to find by DN when user cannot be found by UID. !7002
- Fix Milestone dropdown not stay selected for `Upcoming` and `No Milestone` option. !7117
- Fix relative links in Markdown wiki when displayed in "Project" tab. !7218
- Fix no "Register" tab if ldap auth is enabled (#24038). !7274 (Luc Didry)
- Fix cache for commit status in commits list to respect branches. !7372
- Fix issue causing Labels not to appear in sidebar on MR page. !7416 (Alex Sanford)
- Limit labels returned for a specific project as an administrator. !7496
- Clicking "force remove source branch" label now toggles the checkbox again.
- Allow commit note to be visible if repo is visible.
- Fix project Visibility Level selector not using default values.
## 8.13.5 (2016-11-08)
- Restore unauthenticated access to public container registries
- Fix showing pipeline status for a given commit from correct branch. !7034
- Only skip group when it's actually a group in the "Share with group" select. !7262
- Introduce round-robin project creation to spread load over multiple shards. !7266
- Ensure merge request's "remove branch" accessors return booleans. !7267
- Ensure external users are not able to clone disabled repositories.
- Fix XSS issue in Markdown autolinker.
- Respect event visibility in Gitlab::ContributionsCalendar.
- Honour issue and merge request visibility in their respective finders.
- Disable reference Markdown for unavailable features.
- Fix lightweight tags not processed correctly by GitTagPushService. !6532
- Allow owners to fetch source code in CI builds. !6943
- Return conflict error in label API when title is taken by group label. !7014
- Reduce the overhead to calculate number of open/closed issues and merge requests within the group or project. !7123
- Fix builds tab visibility. !7178
- Fix project features default values. !7181
## 8.13.4
- Pulled due to packaging error.
## 8.13.3 (2016-11-02) ## 8.13.3 (2016-11-02)
- Removes any symlinks before importing a project export file. CVE-2016-9086 - Removes any symlinks before importing a project export file. CVE-2016-9086
- Fixed Import/Export foreign key issue to do with project members. - Fixed Import/Export foreign key issue to do with project members.
- Fix relative links in Markdown wiki when displayed in "Project" tab !7218
- Reduce the overhead to calculate number of open/closed issues and merge requests within the group or project
- Fix project features default values
- Changed build dropdown list length to be 6,5 builds long in the pipeline graph - Changed build dropdown list length to be 6,5 builds long in the pipeline graph
## 8.13.2 (2016-10-31) ## 8.13.2 (2016-10-31)
...@@ -269,6 +306,10 @@ entry. ...@@ -269,6 +306,10 @@ entry.
- Fix broken Project API docs (Takuya Noguchi) - Fix broken Project API docs (Takuya Noguchi)
- Migrate invalid project members (owner -> master) - Migrate invalid project members (owner -> master)
## 8.12.9 (2016-11-07)
- Fix XSS issue in Markdown autolinker
## 8.12.8 (2016-11-02) ## 8.12.8 (2016-11-02)
- Removes any symlinks before importing a project export file. CVE-2016-9086 - Removes any symlinks before importing a project export file. CVE-2016-9086
...@@ -533,6 +574,10 @@ entry. ...@@ -533,6 +574,10 @@ entry.
- Fix non-master branch readme display in tree view - Fix non-master branch readme display in tree view
- Add UX improvements for merge request version diffs - Add UX improvements for merge request version diffs
## 8.11.11 (2016-11-07)
- Fix XSS issue in Markdown autolinker
## 8.11.10 (2016-11-02) ## 8.11.10 (2016-11-02)
- Removes any symlinks before importing a project export file. CVE-2016-9086 - Removes any symlinks before importing a project export file. CVE-2016-9086
......
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
- [Helping others](#helping-others) - [Helping others](#helping-others)
- [I want to contribute!](#i-want-to-contribute) - [I want to contribute!](#i-want-to-contribute)
- [Implement design & UI elements](#implement-design-ui-elements) - [Implement design & UI elements](#implement-design-ui-elements)
- [Design reference](#design-reference)
- [UI development kit](#ui-development-kit)
- [Issue tracker](#issue-tracker) - [Issue tracker](#issue-tracker)
- [Feature proposals](#feature-proposals) - [Feature proposals](#feature-proposals)
- [Issue tracker guidelines](#issue-tracker-guidelines) - [Issue tracker guidelines](#issue-tracker-guidelines)
...@@ -90,7 +88,7 @@ This was inspired by [an article by Kent C. Dodds][medium-up-for-grabs]. ...@@ -90,7 +88,7 @@ This was inspired by [an article by Kent C. Dodds][medium-up-for-grabs].
## Implement design & UI elements ## Implement design & UI elements
Please see the [UI Guide for building GitLab]. Please see the [UX Guide for GitLab].
## Issue tracker ## Issue tracker
...@@ -218,7 +216,10 @@ associated with in the description of the issue. ...@@ -218,7 +216,10 @@ associated with in the description of the issue.
We welcome merge requests with fixes and improvements to GitLab code, tests, We welcome merge requests with fixes and improvements to GitLab code, tests,
and/or documentation. The features we would really like a merge request for are and/or documentation. The features we would really like a merge request for are
listed with the label [`Accepting Merge Requests` on our issue tracker for CE][accepting-mrs-ce] listed with the label [`Accepting Merge Requests` on our issue tracker for CE][accepting-mrs-ce]
and [EE][accepting-mrs-ee] but other improvements are also welcome. and [EE][accepting-mrs-ee] but other improvements are also welcome. Please note
that if an issue is marked for the current milestone either before or while you
are working on it, a team member may take over the merge request in order to
ensure the work is finished before the release date.
If you want to add a new feature that is not labeled it is best to first create If you want to add a new feature that is not labeled it is best to first create
a feedback issue (if there isn't one already) and leave a comment asking for it a feedback issue (if there isn't one already) and leave a comment asking for it
...@@ -469,5 +470,5 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor ...@@ -469,5 +470,5 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide" [doc-styleguide]: doc/development/doc_styleguide.md "Documentation styleguide"
[scss-styleguide]: doc/development/scss_styleguide.md "SCSS styleguide" [scss-styleguide]: doc/development/scss_styleguide.md "SCSS styleguide"
[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide" [newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
[UI Guide for building GitLab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/ui_guide.md [UX Guide for GitLab]: http://docs.gitlab.com/ce/development/ux_guide/
[license-finder-doc]: doc/development/licensing.md [license-finder-doc]: doc/development/licensing.md
...@@ -26,7 +26,7 @@ gem 'omniauth-bitbucket', '~> 0.0.2' ...@@ -26,7 +26,7 @@ gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-cas3', '~> 1.1.2' gem 'omniauth-cas3', '~> 1.1.2'
gem 'omniauth-facebook', '~> 4.0.0' gem 'omniauth-facebook', '~> 4.0.0'
gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-gitlab', '~> 1.0.2'
gem 'omniauth-google-oauth2', '~> 0.4.1' gem 'omniauth-google-oauth2', '~> 0.4.1'
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-saml', '~> 1.7.0' gem 'omniauth-saml', '~> 1.7.0'
...@@ -137,6 +137,7 @@ gem 'acts-as-taggable-on', '~> 4.0' ...@@ -137,6 +137,7 @@ gem 'acts-as-taggable-on', '~> 4.0'
gem 'sidekiq', '~> 4.2' gem 'sidekiq', '~> 4.2'
gem 'sidekiq-cron', '~> 0.4.0' gem 'sidekiq-cron', '~> 0.4.0'
gem 'redis-namespace', '~> 1.5.2' gem 'redis-namespace', '~> 1.5.2'
gem 'sidekiq-limit_fetch', '~> 3.4'
# HTTP requests # HTTP requests
gem 'httparty', '~> 0.13.3' gem 'httparty', '~> 0.13.3'
...@@ -152,7 +153,7 @@ gem 'settingslogic', '~> 2.0.9' ...@@ -152,7 +153,7 @@ gem 'settingslogic', '~> 2.0.9'
gem 'version_sorter', '~> 2.1.0' gem 'version_sorter', '~> 2.1.0'
# Cache # Cache
gem 'redis-rails', '~> 4.0.0' gem 'redis-rails', '~> 5.0.1'
# Redis # Redis
gem 'redis', '~> 3.2' gem 'redis', '~> 3.2'
...@@ -329,13 +330,10 @@ gem 'octokit', '~> 4.3.0' ...@@ -329,13 +330,10 @@ gem 'octokit', '~> 4.3.0'
gem 'mail_room', '~> 0.9.0' gem 'mail_room', '~> 0.9.0'
gem 'email_reply_parser', '~> 0.5.8' gem 'email_reply_parser', '~> 0.5.8'
gem 'html2text'
gem 'ruby-prof', '~> 0.16.2' gem 'ruby-prof', '~> 0.16.2'
## CI
gem 'activerecord-session_store', '~> 1.0.0'
gem 'nested_form', '~> 0.3.2'
# OAuth # OAuth
gem 'oauth2', '~> 1.2.0' gem 'oauth2', '~> 1.2.0'
......
...@@ -32,12 +32,6 @@ GEM ...@@ -32,12 +32,6 @@ GEM
activemodel (= 4.2.7.1) activemodel (= 4.2.7.1)
activesupport (= 4.2.7.1) activesupport (= 4.2.7.1)
arel (~> 6.0) arel (~> 6.0)
activerecord-session_store (1.0.0)
actionpack (>= 4.0, < 5.1)
activerecord (>= 4.0, < 5.1)
multi_json (~> 1.11, >= 1.11.2)
rack (>= 1.5.2, < 3)
railties (>= 4.0, < 5.1)
activerecord_sane_schema_dumper (0.2) activerecord_sane_schema_dumper (0.2)
rails (>= 4, < 5) rails (>= 4, < 5)
activesupport (4.2.7.1) activesupport (4.2.7.1)
...@@ -345,6 +339,8 @@ GEM ...@@ -345,6 +339,8 @@ GEM
html-pipeline (1.11.0) html-pipeline (1.11.0)
activesupport (>= 2) activesupport (>= 2)
nokogiri (~> 1.4) nokogiri (~> 1.4)
html2text (0.2.0)
nokogiri (~> 1.6)
htmlentities (4.3.4) htmlentities (4.3.4)
httparty (0.13.7) httparty (0.13.7)
json (~> 1.8) json (~> 1.8)
...@@ -416,7 +412,6 @@ GEM ...@@ -416,7 +412,6 @@ GEM
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (2.0.0) multipart-post (2.0.0)
mysql2 (0.3.20) mysql2 (0.3.20)
nested_form (0.3.2)
net-ldap (0.12.1) net-ldap (0.12.1)
net-ssh (3.0.1) net-ssh (3.0.1)
newrelic_rpm (3.16.0.318) newrelic_rpm (3.16.0.318)
...@@ -456,7 +451,7 @@ GEM ...@@ -456,7 +451,7 @@ GEM
omniauth-github (1.1.2) omniauth-github (1.1.2)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.1)
omniauth-gitlab (1.0.1) omniauth-gitlab (1.0.2)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0) omniauth-oauth2 (~> 1.0)
omniauth-google-oauth2 (0.4.1) omniauth-google-oauth2 (0.4.1)
...@@ -573,23 +568,23 @@ GEM ...@@ -573,23 +568,23 @@ GEM
json json
redcarpet (3.3.3) redcarpet (3.3.3)
redis (3.2.2) redis (3.2.2)
redis-actionpack (4.0.1) redis-actionpack (5.0.1)
actionpack (~> 4) actionpack (>= 4.0, < 6)
redis-rack (~> 1.5.0) redis-rack (>= 1, < 3)
redis-store (~> 1.1.0) redis-store (>= 1.1.0, < 1.4.0)
redis-activesupport (4.1.5) redis-activesupport (5.0.1)
activesupport (>= 3, < 5) activesupport (>= 3, < 6)
redis-store (~> 1.1.0) redis-store (~> 1.2.0)
redis-namespace (1.5.2) redis-namespace (1.5.2)
redis (~> 3.0, >= 3.0.4) redis (~> 3.0, >= 3.0.4)
redis-rack (1.5.0) redis-rack (1.6.0)
rack (~> 1.5) rack (~> 1.5)
redis-store (~> 1.1.0) redis-store (~> 1.2.0)
redis-rails (4.0.0) redis-rails (5.0.1)
redis-actionpack (~> 4) redis-actionpack (~> 5.0.0)
redis-activesupport (~> 4) redis-activesupport (~> 5.0.0)
redis-store (~> 1.1.0) redis-store (~> 1.2.0)
redis-store (1.1.7) redis-store (1.2.0)
redis (>= 2.2) redis (>= 2.2)
request_store (1.3.1) request_store (1.3.1)
rerun (0.11.0) rerun (0.11.0)
...@@ -598,7 +593,7 @@ GEM ...@@ -598,7 +593,7 @@ GEM
railties (>= 4.2.0, < 5.1) railties (>= 4.2.0, < 5.1)
rinku (2.0.0) rinku (2.0.0)
rotp (2.1.2) rotp (2.1.2)
rouge (2.0.6) rouge (2.0.7)
rqrcode (0.7.0) rqrcode (0.7.0)
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
...@@ -685,6 +680,8 @@ GEM ...@@ -685,6 +680,8 @@ GEM
redis-namespace (>= 1.5.2) redis-namespace (>= 1.5.2)
rufus-scheduler (>= 2.0.24) rufus-scheduler (>= 2.0.24)
sidekiq (>= 4.0.0) sidekiq (>= 4.0.0)
sidekiq-limit_fetch (3.4.0)
sidekiq (>= 4)
simplecov (0.12.0) simplecov (0.12.0)
docile (~> 1.1.0) docile (~> 1.1.0)
json (>= 1.8, < 3) json (>= 1.8, < 3)
...@@ -807,7 +804,6 @@ PLATFORMS ...@@ -807,7 +804,6 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
RedCloth (~> 4.3.2) RedCloth (~> 4.3.2)
ace-rails-ap (~> 4.1.0) ace-rails-ap (~> 4.1.0)
activerecord-session_store (~> 1.0.0)
activerecord_sane_schema_dumper (= 0.2) activerecord_sane_schema_dumper (= 0.2)
acts-as-taggable-on (~> 4.0) acts-as-taggable-on (~> 4.0)
addressable (~> 2.3.8) addressable (~> 2.3.8)
...@@ -879,6 +875,7 @@ DEPENDENCIES ...@@ -879,6 +875,7 @@ DEPENDENCIES
health_check (~> 2.2.0) health_check (~> 2.2.0)
hipchat (~> 1.5.0) hipchat (~> 1.5.0)
html-pipeline (~> 1.11.0) html-pipeline (~> 1.11.0)
html2text
httparty (~> 0.13.3) httparty (~> 0.13.3)
influxdb (~> 0.2) influxdb (~> 0.2)
jira-ruby (~> 1.1.2) jira-ruby (~> 1.1.2)
...@@ -899,7 +896,6 @@ DEPENDENCIES ...@@ -899,7 +896,6 @@ DEPENDENCIES
minitest (~> 5.7.0) minitest (~> 5.7.0)
mousetrap-rails (~> 1.4.6) mousetrap-rails (~> 1.4.6)
mysql2 (~> 0.3.16) mysql2 (~> 0.3.16)
nested_form (~> 0.3.2)
net-ssh (~> 3.0.1) net-ssh (~> 3.0.1)
newrelic_rpm (~> 3.16) newrelic_rpm (~> 3.16)
nokogiri (~> 1.6.7, >= 1.6.7.2) nokogiri (~> 1.6.7, >= 1.6.7.2)
...@@ -913,7 +909,7 @@ DEPENDENCIES ...@@ -913,7 +909,7 @@ DEPENDENCIES
omniauth-cas3 (~> 1.1.2) omniauth-cas3 (~> 1.1.2)
omniauth-facebook (~> 4.0.0) omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.1.1) omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.0) omniauth-gitlab (~> 1.0.2)
omniauth-google-oauth2 (~> 0.4.1) omniauth-google-oauth2 (~> 0.4.1)
omniauth-kerberos (~> 0.3.0) omniauth-kerberos (~> 0.3.0)
omniauth-saml (~> 1.7.0) omniauth-saml (~> 1.7.0)
...@@ -938,7 +934,7 @@ DEPENDENCIES ...@@ -938,7 +934,7 @@ DEPENDENCIES
redcarpet (~> 3.3.3) redcarpet (~> 3.3.3)
redis (~> 3.2) redis (~> 3.2)
redis-namespace (~> 1.5.2) redis-namespace (~> 1.5.2)
redis-rails (~> 4.0.0) redis-rails (~> 5.0.1)
request_store (~> 1.3) request_store (~> 1.3)
rerun (~> 0.11.0) rerun (~> 0.11.0)
responders (~> 2.0) responders (~> 2.0)
...@@ -961,6 +957,7 @@ DEPENDENCIES ...@@ -961,6 +957,7 @@ DEPENDENCIES
shoulda-matchers (~> 2.8.0) shoulda-matchers (~> 2.8.0)
sidekiq (~> 4.2) sidekiq (~> 4.2)
sidekiq-cron (~> 0.4.0) sidekiq-cron (~> 0.4.0)
sidekiq-limit_fetch (~> 3.4)
simplecov (= 0.12.0) simplecov (= 0.12.0)
slack-notifier (~> 1.2.0) slack-notifier (~> 1.2.0)
spinach-rails (~> 0.2.1) spinach-rails (~> 0.2.1)
...@@ -994,4 +991,4 @@ DEPENDENCIES ...@@ -994,4 +991,4 @@ DEPENDENCIES
wikicloth (= 0.8.1) wikicloth (= 0.8.1)
BUNDLED WITH BUNDLED WITH
1.13.5 1.13.6
...@@ -82,6 +82,10 @@ GitLab is a Ruby on Rails application that runs on the following software: ...@@ -82,6 +82,10 @@ GitLab is a Ruby on Rails application that runs on the following software:
For more information please see the [architecture documentation](https://docs.gitlab.com/ce/development/architecture.html). For more information please see the [architecture documentation](https://docs.gitlab.com/ce/development/architecture.html).
## UX design
Please adhere to the [UX Guide](doc/development/ux_guide/readme.md) when creating designs and implementing code.
## Third-party applications ## Third-party applications
There are a lot of [third-party applications integrating with GitLab](https://about.gitlab.com/applications/). These include GUI Git clients, mobile applications and API wrappers for various languages. There are a lot of [third-party applications integrating with GitLab](https://about.gitlab.com/applications/). These include GUI Git clients, mobile applications and API wrappers for various languages.
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-undef, quotes, no-var, padded-blocks, max-len */
(function() { (function() {
this.Activities = (function() { this.Activities = (function() {
function Activities() { function Activities() {
...@@ -13,12 +13,12 @@ ...@@ -13,12 +13,12 @@
} }
Activities.prototype.updateTooltips = function() { Activities.prototype.updateTooltips = function() {
return gl.utils.localTimeAgo($('.js-timeago', '.content_list')); gl.utils.localTimeAgo($('.js-timeago', '.content_list'));
}; };
Activities.prototype.reloadActivities = function() { Activities.prototype.reloadActivities = function() {
$(".content_list").html(''); $(".content_list").html('');
return Pager.init(20, true); Pager.init(20, true, false, this.updateTooltips);
}; };
Activities.prototype.toggleFilter = function(sender) { Activities.prototype.toggleFilter = function(sender) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-arrow-callback, camelcase, quotes, comma-dangle, no-undef, padded-blocks, max-len */
(function() { (function() {
this.Admin = (function() { this.Admin = (function() {
function Admin() { function Admin() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, quotes, object-shorthand, camelcase, no-var, no-undef, comma-dangle, prefer-arrow-callback, indent, object-curly-spacing, quote-props, no-param-reassign, padded-blocks, max-len */
(function() { (function() {
this.Api = { this.Api = {
groupsPath: "/api/:version/groups.json", groupsPath: "/api/:version/groups.json",
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, no-undef, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len */
// This is a manifest file that'll be compiled into including all the files listed below. // This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript code in separate files in this directory and they'll automatically // Add new JavaScript code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js // be included in the compiled file accessible from http://example.com/assets/application.js
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
/*= require jquery-ui/sortable */ /*= require jquery-ui/sortable */
/*= require jquery_ujs */ /*= require jquery_ujs */
/*= require jquery.endless-scroll */ /*= require jquery.endless-scroll */
/*= require jquery.timeago */
/*= require jquery.highlight */ /*= require jquery.highlight */
/*= require jquery.waitforimages */ /*= require jquery.waitforimages */
/*= require jquery.atwho */ /*= require jquery.atwho */
...@@ -54,16 +53,34 @@ ...@@ -54,16 +53,34 @@
/*= require_directory ./u2f */ /*= require_directory ./u2f */
/*= require_directory . */ /*= require_directory . */
/*= require fuzzaldrin-plus */ /*= require fuzzaldrin-plus */
/*= require es6-promise.auto */
(function () { (function () {
document.addEventListener('page:fetch', gl.utils.cleanupBeforeFetch); document.addEventListener('page:fetch', gl.utils.cleanupBeforeFetch);
window.addEventListener('hashchange', gl.utils.shiftWindow); window.addEventListener('hashchange', gl.utils.shiftWindow);
// automatically adjust scroll position for hash urls taking the height of the navbar into account
// https://github.com/twitter/bootstrap/issues/1768
window.adjustScroll = function() {
var navbar = document.querySelector('.navbar-gitlab');
var subnav = document.querySelector('.layout-nav');
var fixedTabs = document.querySelector('.js-tabs-affix');
adjustment = 0;
if (navbar) adjustment -= navbar.offsetHeight;
if (subnav) adjustment -= subnav.offsetHeight;
if (fixedTabs) adjustment -= fixedTabs.offsetHeight;
return scrollBy(0, adjustment);
};
window.addEventListener("hashchange", adjustScroll);
window.onload = function () { window.onload = function () {
// Scroll the window to avoid the topnav bar // Scroll the window to avoid the topnav bar
// https://github.com/twitter/bootstrap/issues/1768 // https://github.com/twitter/bootstrap/issues/1768
if (location.hash) { if (location.hash) {
return setTimeout(gl.utils.shiftWindow, 100); return setTimeout(adjustScroll, 100);
} }
}; };
...@@ -194,9 +211,6 @@ ...@@ -194,9 +211,6 @@
e.preventDefault(); e.preventDefault();
return new ConfirmDangerModal(form, text); return new ConfirmDangerModal(form, text);
}); });
$document.on('click', 'button', function () {
return $(this).blur();
});
$('input[type="search"]').each(function () { $('input[type="search"]').each(function () {
var $this = $(this); var $this = $(this);
$this.attr('value', $this.val()); $this.attr('value', $this.val());
...@@ -238,8 +252,5 @@ ...@@ -238,8 +252,5 @@
// bind sidebar events // bind sidebar events
new gl.Sidebar(); new gl.Sidebar();
// Custom time ago
gl.utils.shortTimeAgo($('.js-short-timeago'));
}); });
}).call(this); }).call(this);
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, prefer-arrow-callback, no-var, one-var, one-var-declaration-per-line, no-else-return, padded-blocks, max-len */
(function() { (function() {
this.Aside = (function() { this.Aside = (function() {
function Aside() { function Aside() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-param-reassign, quotes, prefer-template, no-var, one-var, no-unused-vars, one-var-declaration-per-line, no-void, consistent-return, no-empty, padded-blocks, max-len */
(function() { (function() {
this.Autosave = (function() { this.Autosave = (function() {
function Autosave(field, key) { function Autosave(field, key) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, no-var, spaced-comment, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, no-unused-vars, no-else-return, prefer-template, quotes, comma-dangle, no-param-reassign, no-void, radix, keyword-spacing, space-before-blocks, brace-style, no-underscore-dangle, no-undef, no-plusplus, no-return-assign, camelcase, padded-blocks, max-len */
(function() { (function() {
this.AwardsHandler = (function() { this.AwardsHandler = (function() {
var FROM_SENTENCE_REGEX = /(?:, and | and |, )/; //For separating lists produced by ruby's Array#toSentence var FROM_SENTENCE_REGEX = /(?:, and | and |, )/; //For separating lists produced by ruby's Array#toSentence
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, consistent-return, no-undef, padded-blocks, max-len */
/*= require jquery.ba-resize */ /*= require jquery.ba-resize */
/*= require autosize */ /*= require autosize */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, quotes, no-var, vars-on-top, padded-blocks, max-len */
(function() { (function() {
$(function() { $(function() {
$("body").on("click", ".js-details-target", function() { $("body").on("click", ".js-details-target", function() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-undef, prefer-arrow-callback, camelcase, max-len, consistent-return, quotes, object-shorthand, comma-dangle, padded-blocks, max-len */
// Quick Submit behavior // Quick Submit behavior
// //
// When a child field of a form with a `js-quick-submit` class receives a // When a child field of a form with a `js-quick-submit` class receives a
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, no-else-return, consistent-return, padded-blocks, max-len */
// Requires Input behavior // Requires Input behavior
// //
// When called on a form with input fields with the `required` attribute, the // When called on a form with input fields with the `required` attribute, the
......
/* eslint-disable */ /* eslint-disable wrap-iife, func-names, space-before-function-paren, prefer-arrow-callback, vars-on-top, no-var, max-len */
(function(w) { (function(w) {
$(function() { $(function() {
// Toggle button. Show/hide content inside parent container. // Toggle button. Show/hide content inside parent container.
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, camelcase, no-undef, object-shorthand, quotes, comma-dangle, prefer-arrow-callback, no-unused-vars, prefer-template, no-useless-escape, no-alert, padded-blocks, max-len */
(function() { (function() {
this.BlobFileDropzone = (function() { this.BlobFileDropzone = (function() {
function BlobFileDropzone(form, method) { function BlobFileDropzone(form, method) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, no-undef, padded-blocks, max-len */
/*= require blob/template_selector */ /*= require blob/template_selector */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-unused-expressions, no-cond-assign, no-sequences, no-undef, comma-dangle, padded-blocks, max-len */
(function() { (function() {
this.BlobGitignoreSelectors = (function() { this.BlobGitignoreSelectors = (function() {
function BlobGitignoreSelectors(opts) { function BlobGitignoreSelectors(opts) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, max-len, one-var, no-var, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, prefer-rest-params, comma-dangle, no-undef, padded-blocks, max-len */
/*= require blob/template_selector */ /*= require blob/template_selector */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-undef, no-new, padded-blocks, max-len */
/*= require_tree . */ /*= require_tree . */
(function() { (function() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, camelcase, no-param-reassign, no-undef, quotes, prefer-template, no-new, comma-dangle, one-var, one-var-declaration-per-line, prefer-arrow-callback, no-else-return, no-unused-vars, padded-blocks, max-len */
(function() { (function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
......
...@@ -22,6 +22,8 @@ $(() => { ...@@ -22,6 +22,8 @@ $(() => {
gl.IssueBoardsApp.$destroy(true); gl.IssueBoardsApp.$destroy(true);
} }
Store.create();
gl.IssueBoardsApp = new Vue({ gl.IssueBoardsApp = new Vue({
el: $boardApp, el: $boardApp,
components: { components: {
...@@ -37,16 +39,15 @@ $(() => { ...@@ -37,16 +39,15 @@ $(() => {
issueLinkBase: $boardApp.dataset.issueLinkBase, issueLinkBase: $boardApp.dataset.issueLinkBase,
detailIssue: Store.detail detailIssue: Store.detail
}, },
init: Store.create.bind(Store),
computed: { computed: {
detailIssueVisible () { detailIssueVisible () {
return Object.keys(this.detailIssue.issue).length; return Object.keys(this.detailIssue.issue).length;
} },
}, },
created () { created () {
gl.boardService = new BoardService(this.endpoint, this.boardId); gl.boardService = new BoardService(this.endpoint, this.boardId);
}, },
ready () { mounted () {
Store.disabled = this.disabled; Store.disabled = this.disabled;
gl.boardService.all() gl.boardService.all()
.then((resp) => { .then((resp) => {
...@@ -60,6 +61,8 @@ $(() => { ...@@ -60,6 +61,8 @@ $(() => {
} }
}); });
this.state.lists = _.sortBy(this.state.lists, 'position');
Store.addBlankState(); Store.addBlankState();
this.loading = false; this.loading = false;
}); });
...@@ -70,6 +73,9 @@ $(() => { ...@@ -70,6 +73,9 @@ $(() => {
el: '#js-boards-seach', el: '#js-boards-seach',
data: { data: {
filters: Store.state.filters filters: Store.state.filters
},
mounted () {
gl.issueBoards.newListDropdownInit();
} }
}); });
}); });
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.Board = Vue.extend({ gl.issueBoards.Board = Vue.extend({
template: '#js-board-template',
components: { components: {
'board-list': gl.issueBoards.BoardList, 'board-list': gl.issueBoards.BoardList,
'board-delete': gl.issueBoards.BoardDelete, 'board-delete': gl.issueBoards.BoardDelete,
...@@ -24,7 +25,6 @@ ...@@ -24,7 +25,6 @@
return { return {
detailIssue: Store.detail, detailIssue: Store.detail,
filters: Store.state.filters, filters: Store.state.filters,
showIssueForm: false
}; };
}, },
watch: { watch: {
...@@ -58,10 +58,10 @@ ...@@ -58,10 +58,10 @@
}, },
methods: { methods: {
showNewIssueForm() { showNewIssueForm() {
this.showIssueForm = !this.showIssueForm; this.$refs['board-list'].showIssueForm = !this.$refs['board-list'].showIssueForm;
} }
}, },
ready () { mounted () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({ const options = gl.issueBoards.getBoardSortableDefaultOptions({
disabled: this.disabled, disabled: this.disabled,
group: 'boards', group: 'boards',
...@@ -72,13 +72,9 @@ ...@@ -72,13 +72,9 @@
if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) { if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) {
const order = this.sortable.toArray(), const order = this.sortable.toArray(),
$board = this.$parent.$refs.board[e.oldIndex + 1], list = Store.findList('id', parseInt(e.item.dataset.id));
list = $board.list;
$board.$destroy(true);
this.$nextTick(() => { this.$nextTick(() => {
Store.state.lists.splice(e.newIndex, 0, list);
Store.moveList(list, order); Store.moveList(list, order);
}); });
} }
...@@ -87,8 +83,5 @@ ...@@ -87,8 +83,5 @@
this.sortable = Sortable.create(this.$el.parentNode, options); this.sortable = Sortable.create(this.$el.parentNode, options);
}, },
beforeDestroy () {
Store.state.lists.$remove(this.list);
}
}); });
})(); })();
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
}); });
}); });
Store.state.lists = _.sortBy(Store.state.lists, 'position');
// Save the labels // Save the labels
gl.boardService.generateDefaultLists() gl.boardService.generateDefaultLists()
.then((resp) => { .then((resp) => {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardCard = Vue.extend({ gl.issueBoards.BoardCard = Vue.extend({
template: '#js-board-list-card',
props: { props: {
list: Object, list: Object,
issue: Object, issue: Object,
...@@ -53,11 +54,6 @@ ...@@ -53,11 +54,6 @@
mouseDown () { mouseDown () {
this.showDetail = true; this.showDetail = true;
}, },
mouseMove () {
if (this.showDetail) {
this.showDetail = false;
}
},
showIssue (e) { showIssue (e) {
const targetTagName = e.target.tagName.toLowerCase(); const targetTagName = e.target.tagName.toLowerCase();
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
window.gl.issueBoards = window.gl.issueBoards || {}; window.gl.issueBoards = window.gl.issueBoards || {};
gl.issueBoards.BoardList = Vue.extend({ gl.issueBoards.BoardList = Vue.extend({
template: '#js-board-list-template',
components: { components: {
'board-card': gl.issueBoards.BoardCard, 'board-card': gl.issueBoards.BoardCard,
'board-new-issue': gl.issueBoards.BoardNewIssue 'board-new-issue': gl.issueBoards.BoardNewIssue
...@@ -19,20 +20,20 @@ ...@@ -19,20 +20,20 @@
issues: Array, issues: Array,
loading: Boolean, loading: Boolean,
issueLinkBase: String, issueLinkBase: String,
showIssueForm: Boolean
}, },
data () { data () {
return { return {
scrollOffset: 250, scrollOffset: 250,
filters: Store.state.filters, filters: Store.state.filters,
showCount: false showCount: false,
showIssueForm: false
}; };
}, },
watch: { watch: {
filters: { filters: {
handler () { handler () {
this.list.loadingMore = false; this.list.loadingMore = false;
this.$els.list.scrollTop = 0; this.$refs.list.scrollTop = 0;
}, },
deep: true deep: true
}, },
...@@ -51,15 +52,20 @@ ...@@ -51,15 +52,20 @@
}); });
} }
}, },
computed: {
orderedIssues () {
return _.sortBy(this.issues, 'priority');
},
},
methods: { methods: {
listHeight () { listHeight () {
return this.$els.list.getBoundingClientRect().height; return this.$refs.list.getBoundingClientRect().height;
}, },
scrollHeight () { scrollHeight () {
return this.$els.list.scrollHeight; return this.$refs.list.scrollHeight;
}, },
scrollTop () { scrollTop () {
return this.$els.list.scrollTop + this.listHeight(); return this.$refs.list.scrollTop + this.listHeight();
}, },
loadNextPage () { loadNextPage () {
const getIssues = this.list.nextPage(); const getIssues = this.list.nextPage();
...@@ -72,7 +78,7 @@ ...@@ -72,7 +78,7 @@
} }
}, },
}, },
ready () { mounted () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({ const options = gl.issueBoards.getBoardSortableDefaultOptions({
group: 'issues', group: 'issues',
sort: false, sort: false,
...@@ -81,23 +87,27 @@ ...@@ -81,23 +87,27 @@
onStart: (e) => { onStart: (e) => {
const card = this.$refs.issue[e.oldIndex]; const card = this.$refs.issue[e.oldIndex];
card.showDetail = false;
Store.moving.issue = card.issue; Store.moving.issue = card.issue;
Store.moving.list = card.list; Store.moving.list = card.list;
gl.issueBoards.onStart(); gl.issueBoards.onStart();
}, },
onAdd: (e) => { onAdd: (e) => {
gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue); // Add the element back to original list to allow Vue to handle DOM updates
e.from.appendChild(e.item);
this.$nextTick(() => {
// Update the issues once we know the element has been moved
gl.issueBoards.BoardsStore.moveIssueToList(Store.moving.list, this.list, Store.moving.issue);
});
}, },
onRemove: (e) => {
this.$refs.issue[e.oldIndex].$destroy(true);
}
}); });
this.sortable = Sortable.create(this.$els.list, options); this.sortable = Sortable.create(this.$refs.list, options);
// Scroll event on list to load more // Scroll event on list to load more
this.$els.list.onscroll = () => { this.$refs.list.onscroll = () => {
if ((this.scrollTop() > this.scrollHeight() - this.scrollOffset) && !this.list.loadingMore) { if ((this.scrollTop() > this.scrollHeight() - this.scrollOffset) && !this.list.loadingMore) {
this.loadNextPage(); this.loadNextPage();
} }
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
gl.issueBoards.BoardNewIssue = Vue.extend({ gl.issueBoards.BoardNewIssue = Vue.extend({
props: { props: {
list: Object, list: Object,
showIssueForm: Boolean
}, },
data() { data() {
return { return {
...@@ -15,11 +14,6 @@ ...@@ -15,11 +14,6 @@
error: false error: false
}; };
}, },
watch: {
showIssueForm () {
this.$els.input.focus();
}
},
methods: { methods: {
submit(e) { submit(e) {
e.preventDefault(); e.preventDefault();
...@@ -37,28 +31,30 @@ ...@@ -37,28 +31,30 @@
this.list.newIssue(issue) this.list.newIssue(issue)
.then((data) => { .then((data) => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions // Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$els.submitButton).enable(); $(this.$refs.submitButton).enable();
Store.detail.issue = issue; Store.detail.issue = issue;
}) })
.catch(() => { .catch(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions // Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$els.submitButton).enable(); $(this.$refs.submitButton).enable();
// Remove the issue // Remove the issue
this.list.removeIssue(issue); this.list.removeIssue(issue);
// Show error message // Show error message
this.error = true; this.error = true;
this.showIssueForm = true;
}); });
this.cancel(); this.cancel();
}, },
cancel() { cancel() {
this.showIssueForm = false;
this.title = ''; this.title = '';
this.$parent.showIssueForm = false;
} }
} },
mounted() {
this.$refs.input.focus();
},
}); });
})(); })();
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
this.detail.issue = {}; this.detail.issue = {};
} }
}, },
ready () { mounted () {
new IssuableContext(this.currentUser); new IssuableContext(this.currentUser);
new MilestoneSelect(); new MilestoneSelect();
new gl.DueDateSelectors(); new gl.DueDateSelectors();
......
/* eslint-disable */ /* eslint-disable */
$(() => { (() => {
window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};
const Store = gl.issueBoards.BoardsStore; const Store = gl.issueBoards.BoardsStore;
$(document).off('created.label').on('created.label', (e, label) => { $(document).off('created.label').on('created.label', (e, label) => {
...@@ -15,54 +18,58 @@ $(() => { ...@@ -15,54 +18,58 @@ $(() => {
}); });
}); });
$('.js-new-board-list').each(function () { gl.issueBoards.newListDropdownInit = () => {
const $this = $(this); $('.js-new-board-list').each(function () {
new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path')); const $this = $(this);
new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path'));
$this.glDropdown({ $this.glDropdown({
data(term, callback) { data(term, callback) {
$.get($this.attr('data-labels')) $.get($this.attr('data-labels'))
.then((resp) => { .then((resp) => {
callback(resp); callback(resp);
}); });
}, },
renderRow (label) { renderRow (label) {
const active = Store.findList('title', label.title), const active = Store.findList('title', label.title),
$li = $('<li />'), $li = $('<li />'),
$a = $('<a />', { $a = $('<a />', {
class: (active ? `is-active js-board-list-${active.id}` : ''), class: (active ? `is-active js-board-list-${active.id}` : ''),
text: label.title, text: label.title,
href: '#' href: '#'
}), }),
$labelColor = $('<span />', { $labelColor = $('<span />', {
class: 'dropdown-label-box', class: 'dropdown-label-box',
style: `background-color: ${label.color}` style: `background-color: ${label.color}`
}); });
return $li.append($a.prepend($labelColor)); return $li.append($a.prepend($labelColor));
}, },
search: { search: {
fields: ['title'] fields: ['title']
}, },
filterable: true, filterable: true,
selectable: true, selectable: true,
multiSelect: true, multiSelect: true,
clicked (label, $el, e) { clicked (label, $el, e) {
e.preventDefault(); e.preventDefault();
if (!Store.findList('title', label.title)) { if (!Store.findList('title', label.title)) {
Store.new({ Store.new({
title: label.title,
position: Store.state.lists.length - 2,
list_type: 'label',
label: {
id: label.id,
title: label.title, title: label.title,
color: label.color position: Store.state.lists.length - 2,
} list_type: 'label',
}); label: {
id: label.id,
title: label.title,
color: label.color
}
});
Store.state.lists = _.sortBy(Store.state.lists, 'position');
}
} }
} });
}); });
}); };
}); })();
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
fallbackOnBody: true, fallbackOnBody: true,
ghostClass: 'is-ghost', ghostClass: 'is-ghost',
filter: '.board-delete, .btn', filter: '.board-delete, .btn',
delay: gl.issueBoards.touchEnabled ? 100 : 50, delay: gl.issueBoards.touchEnabled ? 100 : 0,
scrollSensitivity: gl.issueBoards.touchEnabled ? 60 : 100, scrollSensitivity: gl.issueBoards.touchEnabled ? 60 : 100,
scrollSpeed: 20, scrollSpeed: 20,
onStart: gl.issueBoards.onStart, onStart: gl.issueBoards.onStart,
......
...@@ -42,7 +42,8 @@ class List { ...@@ -42,7 +42,8 @@ class List {
} }
destroy () { destroy () {
gl.issueBoards.BoardsStore.state.lists.$remove(this); const index = gl.issueBoards.BoardsStore.state.lists.indexOf(this);
gl.issueBoards.BoardsStore.state.lists.splice(index, 1);
gl.issueBoards.BoardsStore.updateNewListDropdown(this.id); gl.issueBoards.BoardsStore.updateNewListDropdown(this.id);
gl.boardService.destroyList(this.id); gl.boardService.destroyList(this.id);
......
...@@ -39,6 +39,8 @@ ...@@ -39,6 +39,8 @@
// Remove any new issues from the backlog // Remove any new issues from the backlog
// as they will be visible in the new list // as they will be visible in the new list
list.issues.forEach(backlogList.removeIssue.bind(backlogList)); list.issues.forEach(backlogList.removeIssue.bind(backlogList));
this.state.lists = _.sortBy(this.state.lists, 'position');
}); });
this.removeBlankState(); this.removeBlankState();
}, },
...@@ -58,6 +60,8 @@ ...@@ -58,6 +60,8 @@
title: 'Welcome to your Issue Board!', title: 'Welcome to your Issue Board!',
position: 0 position: 0
}); });
this.state.lists = _.sortBy(this.state.lists, 'position');
}, },
removeBlankState () { removeBlankState () {
this.removeList('blank'); this.removeList('blank');
......
/* eslint-disable */ /* eslint-disable wrap-iife, func-names, strict, indent, no-tabs, no-var, vars-on-top, no-param-reassign, object-shorthand, no-shadow, comma-dangle, prefer-template, consistent-return, no-mixed-operators, no-unused-vars, object-curly-spacing, no-unused-expressions, prefer-arrow-callback, max-len */
(function () { (function () {
'use strict'; 'use strict';
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, quotes, no-shadow, prefer-arrow-callback, prefer-template, consistent-return, padded-blocks, no-return-assign, new-parens, no-param-reassign, no-undef, max-len */
(function() { (function() {
this.Breakpoints = (function() { this.Breakpoints = (function() {
var BreakpointInstance, instance; var BreakpointInstance, instance;
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, no-else-return, object-shorthand, comma-dangle, padded-blocks, max-len */
(function() { (function() {
$(function() { $(function() {
var previewPath; var previewPath;
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-param-reassign, no-undef, quotes, yoda, no-else-return, consistent-return, comma-dangle, semi, object-shorthand, prefer-template, one-var, one-var-declaration-per-line, no-unused-vars, max-len, vars-on-top, padded-blocks, max-len */
(function() { (function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
...@@ -8,56 +8,55 @@ ...@@ -8,56 +8,55 @@
Build.state = null; Build.state = null;
function Build(options) { function Build(options) {
this.page_url = options.page_url; options = options || $('.js-build-options').data();
this.build_url = options.build_url; this.pageUrl = options.pageUrl;
this.build_status = options.build_status; this.buildUrl = options.buildUrl;
this.buildStatus = options.buildStatus;
this.state = options.state1; this.state = options.state1;
this.build_stage = options.build_stage; this.buildStage = options.buildStage;
this.hideSidebar = bind(this.hideSidebar, this);
this.toggleSidebar = bind(this.toggleSidebar, this);
this.updateDropdown = bind(this.updateDropdown, this); this.updateDropdown = bind(this.updateDropdown, this);
this.$document = $(document); this.$document = $(document);
clearInterval(Build.interval); clearInterval(Build.interval);
// Init breakpoint checker // Init breakpoint checker
this.bp = Breakpoints.get(); this.bp = Breakpoints.get();
this.initSidebar(); this.initSidebar();
this.$buildScroll = $('#js-build-scroll');
this.populateJobs(this.build_stage); this.populateJobs(this.buildStage);
this.updateStageDropdownText(this.build_stage); this.updateStageDropdownText(this.buildStage);
this.sidebarOnResize();
$(window).off('resize.build').on('resize.build', this.hideSidebar); this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this));
this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown); this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
$('#js-build-scroll > a').off('click').on('click', this.stepTrace); $(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this));
$('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace);
this.updateArtifactRemoveDate(); this.updateArtifactRemoveDate();
if ($('#build-trace').length) { if ($('#build-trace').length) {
this.getInitialBuildTrace(); this.getInitialBuildTrace();
this.initScrollButtons(); this.initScrollButtonAffix();
} }
if (this.build_status === "running" || this.build_status === "pending") { if (this.buildStatus === "running" || this.buildStatus === "pending") {
// Bind autoscroll button to follow build output
$('#autoscroll-button').on('click', function() { $('#autoscroll-button').on('click', function() {
var state; var state;
state = $(this).data("state"); state = $(this).data("state");
if ("enabled" === state) { if ("enabled" === state) {
$(this).data("state", "disabled"); $(this).data("state", "disabled");
return $(this).text("enable autoscroll"); return $(this).text("Enable autoscroll");
} else { } else {
$(this).data("state", "enabled"); $(this).data("state", "enabled");
return $(this).text("disable autoscroll"); return $(this).text("Disable autoscroll");
} }
//
// Bind autoscroll button to follow build output
//
}); });
Build.interval = setInterval((function(_this) { Build.interval = setInterval((function(_this) {
// Check for new build output if user still watching build page
// Only valid for runnig build when output changes during time
return function() { return function() {
if (window.location.href.split("#").first() === _this.page_url) { if (_this.location() === _this.pageUrl) {
return _this.getBuildTrace(); return _this.getBuildTrace();
} }
}; };
//
// Check for new build output if user still watching build page
// Only valid for runnig build when output changes during time
//
})(this), 4000); })(this), 4000);
} }
} }
...@@ -72,20 +71,23 @@ ...@@ -72,20 +71,23 @@
top: this.sidebarTranslationLimits.max top: this.sidebarTranslationLimits.max
}); });
this.$sidebar.niceScroll(); this.$sidebar.niceScroll();
this.hideSidebar();
this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar); this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.toggleSidebar);
this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this)); this.$document.off('scroll.translateSidebar').on('scroll.translateSidebar', this.translateSidebar.bind(this));
}; };
Build.prototype.location = function() {
return window.location.href.split("#")[0];
};
Build.prototype.getInitialBuildTrace = function() { Build.prototype.getInitialBuildTrace = function() {
var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped'] var removeRefreshStatuses = ['success', 'failed', 'canceled', 'skipped']
return $.ajax({ return $.ajax({
url: this.build_url, url: this.buildUrl,
dataType: 'json', dataType: 'json',
success: function(build_data) { success: function(buildData) {
$('.js-build-output').html(build_data.trace_html); $('.js-build-output').html(buildData.trace_html);
if (removeRefreshStatuses.indexOf(build_data.status) >= 0) { if (removeRefreshStatuses.indexOf(buildData.status) >= 0) {
return $('.js-build-refresh').remove(); return $('.js-build-refresh').remove();
} }
} }
...@@ -94,7 +96,7 @@ ...@@ -94,7 +96,7 @@
Build.prototype.getBuildTrace = function() { Build.prototype.getBuildTrace = function() {
return $.ajax({ return $.ajax({
url: this.page_url + "/trace.json?state=" + (encodeURIComponent(this.state)), url: this.pageUrl + "/trace.json?state=" + (encodeURIComponent(this.state)),
dataType: "json", dataType: "json",
success: (function(_this) { success: (function(_this) {
return function(log) { return function(log) {
...@@ -108,8 +110,8 @@ ...@@ -108,8 +110,8 @@
$('.js-build-output').html(log.html); $('.js-build-output').html(log.html);
} }
return _this.checkAutoscroll(); return _this.checkAutoscroll();
} else if (log.status !== _this.build_status) { } else if (log.status !== _this.buildStatus) {
return Turbolinks.visit(_this.page_url); return Turbolinks.visit(_this.pageUrl);
} }
}; };
})(this) })(this)
...@@ -122,12 +124,11 @@ ...@@ -122,12 +124,11 @@
} }
}; };
Build.prototype.initScrollButtons = function() { Build.prototype.initScrollButtonAffix = function() {
var $body, $buildScroll, $buildTrace; var $body, $buildTrace;
$buildScroll = $('#js-build-scroll');
$body = $('body'); $body = $('body');
$buildTrace = $('#build-trace'); $buildTrace = $('#build-trace');
return $buildScroll.affix({ return this.$buildScroll.affix({
offset: { offset: {
bottom: function() { bottom: function() {
return $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top); return $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top);
...@@ -136,18 +137,12 @@ ...@@ -136,18 +137,12 @@
}); });
}; };
Build.prototype.shouldHideSidebar = function() { Build.prototype.shouldHideSidebarForViewport = function() {
var bootstrapBreakpoint; var bootstrapBreakpoint;
bootstrapBreakpoint = this.bp.getBreakpointSize(); bootstrapBreakpoint = this.bp.getBreakpointSize();
return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm'; return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
}; };
Build.prototype.toggleSidebar = function() {
if (this.shouldHideSidebar()) {
return this.$sidebar.toggleClass('right-sidebar-expanded right-sidebar-collapsed');
}
};
Build.prototype.translateSidebar = function(e) { Build.prototype.translateSidebar = function(e) {
var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop); var newPosition = this.sidebarTranslationLimits.max - (document.body.scrollTop || document.documentElement.scrollTop);
if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min; if (newPosition < this.sidebarTranslationLimits.min) newPosition = this.sidebarTranslationLimits.min;
...@@ -156,12 +151,20 @@ ...@@ -156,12 +151,20 @@
}); });
}; };
Build.prototype.hideSidebar = function() { Build.prototype.toggleSidebar = function(shouldHide) {
if (this.shouldHideSidebar()) { var shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
return this.$sidebar.removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed'); this.$buildScroll.toggleClass('sidebar-expanded', shouldShow)
} else { .toggleClass('sidebar-collapsed', shouldHide);
return this.$sidebar.removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded'); this.$sidebar.toggleClass('right-sidebar-expanded', shouldShow)
} .toggleClass('right-sidebar-collapsed', shouldHide);
};
Build.prototype.sidebarOnResize = function() {
this.toggleSidebar(this.shouldHideSidebarForViewport());
};
Build.prototype.sidebarOnClick = function() {
if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
}; };
Build.prototype.updateArtifactRemoveDate = function() { Build.prototype.updateArtifactRemoveDate = function() {
...@@ -169,7 +172,7 @@ ...@@ -169,7 +172,7 @@
$date = $('.js-artifacts-remove'); $date = $('.js-artifacts-remove');
if ($date.length) { if ($date.length) {
date = $date.text(); date = $date.text();
return $date.text($.timefor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' ')); return $date.text(gl.utils.timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' '));
} }
}; };
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-unused-vars, no-return-assign, padded-blocks, max-len */
(function() { (function() {
this.BuildArtifacts = (function() { this.BuildArtifacts = (function() {
function BuildArtifacts() { function BuildArtifacts() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-undef, padded-blocks */
(function() { (function() {
this.Commit = (function() { this.Commit = (function() {
function Commit() { function Commit() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, no-undef, padded-blocks, max-len */
(function() { (function() {
this.CommitFile = (function() { this.CommitFile = (function() {
function CommitFile(file) { function CommitFile(file) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-use-before-define, prefer-arrow-callback, no-else-return, consistent-return, prefer-template, quotes, one-var, one-var-declaration-per-line, no-unused-vars, no-return-assign, comma-dangle, quote-props, no-unused-expressions, no-sequences, object-shorthand, padded-blocks, max-len */
(function() { (function() {
this.ImageFile = (function() { this.ImageFile = (function() {
var prepareFrames; var prepareFrames;
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, consistent-return, no-undef, no-return-assign, no-param-reassign, one-var, no-var, one-var-declaration-per-line, no-unused-vars, prefer-template, object-shorthand, comma-dangle, padded-blocks, max-len */
(function() { (function() {
this.CommitsList = (function() { this.CommitsList = (function() {
function CommitsList() {} function CommitsList() {}
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, no-var, object-shorthand, consistent-return, no-unused-vars, comma-dangle, vars-on-top, prefer-template, padded-blocks, max-len */
(function() { (function() {
this.Compare = (function() { this.Compare = (function() {
function Compare(opts) { function Compare(opts) {
...@@ -80,7 +80,8 @@ ...@@ -80,7 +80,8 @@
success: function(html) { success: function(html) {
loading.hide(); loading.hide();
$target.html(html); $target.html(html);
return $('.js-timeago', $target).timeago(); var className = '.' + $target[0].className.replace(' ', '.');
gl.utils.localTimeAgo($('.js-timeago', className));
} }
}); });
}; };
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, camelcase, one-var-declaration-per-line, no-else-return, padded-blocks, max-len */
(function() { (function() {
this.ConfirmDangerModal = (function() { this.ConfirmDangerModal = (function() {
function ConfirmDangerModal(form, text) { function ConfirmDangerModal(form, text) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-undef, prefer-template, quotes, no-unused-vars, prefer-arrow-callback, padded-blocks, max-len */
/*= require clipboard */ /*= require clipboard */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, max-len, one-var, camelcase, one-var-declaration-per-line, no-unused-vars, no-unused-expressions, no-sequences, object-shorthand, comma-dangle, prefer-arrow-callback, semi, radix, padded-blocks, max-len */
(function() { (function() {
this.Diff = (function() { this.Diff = (function() {
var UNFOLD_COUNT; var UNFOLD_COUNT;
...@@ -43,10 +43,6 @@ ...@@ -43,10 +43,6 @@
bottom: unfoldBottom, bottom: unfoldBottom,
offset: offset, offset: offset,
unfold: unfold, unfold: unfold,
// indent is used to compensate for single space indent to fit
// '+' and '-' prepended to diff lines,
// see https://gitlab.com/gitlab-org/gitlab-ce/issues/707
indent: 1,
view: file.data('view') view: file.data('view')
}; };
return $.get(link, params, function(response) { return $.get(link, params, function(response) {
......
/* eslint-disable */ /* eslint-disable */
((w) => { (() => {
w.CommentAndResolveBtn = Vue.extend({ const CommentAndResolveBtn = Vue.extend({
props: { props: {
discussionId: String, discussionId: String,
textareaIsEmpty: Boolean },
data() {
return {
textareaIsEmpty: true
}
}, },
computed: { computed: {
discussion: function () { discussion: function () {
...@@ -35,7 +39,7 @@ ...@@ -35,7 +39,7 @@
} }
} }
}, },
ready: function () { mounted: function () {
const $textarea = $(`#new-discussion-note-form-${this.discussionId} .note-textarea`); const $textarea = $(`#new-discussion-note-form-${this.discussionId} .note-textarea`);
this.textareaIsEmpty = $textarea.val() === ''; this.textareaIsEmpty = $textarea.val() === '';
...@@ -47,4 +51,6 @@ ...@@ -47,4 +51,6 @@
$(`#new-discussion-note-form-${this.discussionId} .note-textarea`).off('input.comment-and-resolve-btn'); $(`#new-discussion-note-form-${this.discussionId} .note-textarea`).off('input.comment-and-resolve-btn');
} }
}); });
Vue.component('comment-and-resolve-btn', CommentAndResolveBtn);
})(window); })(window);
/* eslint-disable */ /* eslint-disable */
((w) => { (() => {
w.ResolveBtn = Vue.extend({ const ResolveBtn = Vue.extend({
props: { props: {
noteId: Number, noteId: Number,
discussionId: String, discussionId: String,
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
}, },
methods: { methods: {
updateTooltip: function () { updateTooltip: function () {
$(this.$els.button) $(this.$refs.button)
.tooltip('hide') .tooltip('hide')
.tooltip('fixTitle'); .tooltip('fixTitle');
}, },
...@@ -89,8 +89,8 @@ ...@@ -89,8 +89,8 @@
}); });
} }
}, },
compiled: function () { mounted: function () {
$(this.$els.button).tooltip({ $(this.$refs.button).tooltip({
container: 'body' container: 'body'
}); });
}, },
...@@ -101,4 +101,6 @@ ...@@ -101,4 +101,6 @@
CommentsStore.create(this.discussionId, this.noteId, this.canResolve, this.resolved, this.resolvedBy); CommentsStore.create(this.discussionId, this.noteId, this.canResolve, this.resolved, this.resolvedBy);
} }
}); });
})(window);
Vue.component('resolve-btn', ResolveBtn);
})();
...@@ -13,6 +13,9 @@ ...@@ -13,6 +13,9 @@
computed: { computed: {
allResolved: function () { allResolved: function () {
return this.resolvedDiscussionCount === this.discussionCount; return this.resolvedDiscussionCount === this.discussionCount;
},
resolvedCountText() {
return this.discussionCount === 1 ? 'discussion' : 'discussions';
} }
} }
}); });
......
/* eslint-disable */ /* eslint-disable */
((w) => { (() => {
w.ResolveDiscussionBtn = Vue.extend({ const ResolveDiscussionBtn = Vue.extend({
props: { props: {
discussionId: String, discussionId: String,
mergeRequestId: Number, mergeRequestId: Number,
...@@ -54,4 +54,6 @@ ...@@ -54,4 +54,6 @@
CommentsStore.createDiscussion(this.discussionId, this.canResolve); CommentsStore.createDiscussion(this.discussionId, this.canResolve);
} }
}); });
})(window);
Vue.component('resolve-discussion-btn', ResolveDiscussionBtn);
})();
...@@ -8,24 +8,35 @@ ...@@ -8,24 +8,35 @@
//= require_directory ./components //= require_directory ./components
$(() => { $(() => {
window.DiffNotesApp = new Vue({ const COMPONENT_SELECTOR = 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn';
el: '#diff-notes-app',
components: { window.gl = window.gl || {};
'resolve-btn': ResolveBtn, window.gl.diffNoteApps = {};
'resolve-discussion-btn': ResolveDiscussionBtn,
'comment-and-resolve-btn': CommentAndResolveBtn gl.diffNotesCompileComponents = () => {
}, const $components = $(COMPONENT_SELECTOR).filter(function () {
methods: { return $(this).closest('resolve-count').length !== 1;
compileComponents: function () { });
const $components = $('resolve-btn, resolve-discussion-btn, jump-to-discussion');
if ($components.length) { if ($components) {
$components.each(function () { $components.each(function () {
DiffNotesApp.$compile($(this).get(0)); const $this = $(this);
}); const noteId = $this.attr(':note-id');
const tmp = Vue.extend({
template: $this.get(0).outerHTML
});
const tmpApp = new tmp().$mount();
if (noteId) {
gl.diffNoteApps[`note_${noteId}`] = tmpApp;
} }
}
$this.replaceWith(tmpApp.$el);
});
} }
}); };
gl.diffNotesCompileComponents();
new Vue({ new Vue({
el: '#resolve-count-app', el: '#resolve-count-app',
......
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
case 'projects:boards:index': case 'projects:boards:index':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
break; break;
case 'projects:builds:show':
new Build();
break;
case 'projects:merge_requests:index': case 'projects:merge_requests:index':
case 'projects:issues:index': case 'projects:issues:index':
Issuable.init(); Issuable.init();
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, one-var, no-var, one-var-declaration-per-line, no-unused-vars, camelcase, no-undef, quotes, no-useless-concat, prefer-template, quote-props, comma-dangle, object-shorthand, consistent-return, no-plusplus, prefer-arrow-callback, padded-blocks, max-len */
/*= require preview_markdown */ /*= require preview_markdown */
......
//= require vue
//= require vue-resource
//= require_tree ../services/
//= require ./environment_item
/* globals Vue, EnvironmentsService */
/* eslint-disable no-param-reassign */
(() => { // eslint-disable-line
window.gl = window.gl || {};
/**
* Given the visibility prop provided by the url query parameter and which
* changes according to the active tab we need to filter which environments
* should be visible.
*
* The environments array is a recursive tree structure and we need to filter
* both root level environments and children environments.
*
* In order to acomplish that, both `filterState` and `filterEnvironmnetsByState`
* functions work together.
* The first one works as the filter that verifies if the given environment matches
* the given state.
* The second guarantees both root level and children elements are filtered as well.
*/
const filterState = state => environment => environment.state === state && environment;
/**
* Given the filter function and the array of environments will return only
* the environments that match the state provided to the filter function.
*
* @param {Function} fn
* @param {Array} array
* @return {Array}
*/
const filterEnvironmnetsByState = (fn, arr) => arr.map((item) => {
if (item.children) {
const filteredChildren = filterEnvironmnetsByState(fn, item.children).filter(Boolean);
if (filteredChildren.length) {
item.children = filteredChildren;
return item;
}
}
return fn(item);
}).filter(Boolean);
window.gl.environmentsList.EnvironmentsComponent = Vue.component('environment-component', {
props: {
store: {
type: Object,
required: true,
default: () => ({}),
},
},
components: {
'environment-item': window.gl.environmentsList.EnvironmentItem,
},
data() {
const environmentsData = document.querySelector('#environments-list-view').dataset;
return {
state: this.store.state,
visibility: 'available',
isLoading: false,
cssContainerClass: environmentsData.cssClass,
endpoint: environmentsData.environmentsDataEndpoint,
canCreateDeployment: environmentsData.canCreateDeployment,
canReadEnvironment: environmentsData.canReadEnvironment,
canCreateEnvironment: environmentsData.canCreateEnvironment,
projectEnvironmentsPath: environmentsData.projectEnvironmentsPath,
projectStoppedEnvironmentsPath: environmentsData.projectStoppedEnvironmentsPath,
newEnvironmentPath: environmentsData.newEnvironmentPath,
helpPagePath: environmentsData.helpPagePath,
};
},
computed: {
filteredEnvironments() {
return filterEnvironmnetsByState(filterState(this.visibility), this.state.environments);
},
scope() {
return this.$options.getQueryParameter('scope');
},
canReadEnvironmentParsed() {
return this.$options.convertPermissionToBoolean(this.canReadEnvironment);
},
canCreateDeploymentParsed() {
return this.$options.convertPermissionToBoolean(this.canCreateDeployment);
},
canCreateEnvironmentParsed() {
return this.$options.convertPermissionToBoolean(this.canCreateEnvironment);
},
},
/**
* Fetches all the environmnets and stores them.
* Toggles loading property.
*/
created() {
gl.environmentsService = new EnvironmentsService(this.endpoint);
const scope = this.$options.getQueryParameter('scope');
if (scope) {
this.visibility = scope;
}
this.isLoading = true;
return gl.environmentsService.all()
.then(resp => resp.json())
.then((json) => {
this.store.storeEnvironments(json);
this.isLoading = false;
});
},
/**
* Transforms the url parameter into an object and
* returns the one requested.
*
* @param {String} param
* @returns {String} The value of the requested parameter.
*/
getQueryParameter(parameter) {
return window.location.search.substring(1).split('&').reduce((acc, param) => {
const paramSplited = param.split('=');
acc[paramSplited[0]] = paramSplited[1];
return acc;
}, {})[parameter];
},
/**
* Converts permission provided as strings to booleans.
* @param {String} string
* @returns {Boolean}
*/
convertPermissionToBoolean(string) {
return string === 'true';
},
methods: {
toggleRow(model) {
return this.store.toggleFolder(model.name);
},
},
template: `
<div :class="cssContainerClass">
<div class="top-area">
<ul v-if="!isLoading" class="nav-links">
<li v-bind:class="{ 'active': scope === undefined }">
<a :href="projectEnvironmentsPath">
Available
<span
class="badge js-available-environments-count"
v-html="state.availableCounter"></span>
</a>
</li>
<li v-bind:class="{ 'active' : scope === 'stopped' }">
<a :href="projectStoppedEnvironmentsPath">
Stopped
<span
class="badge js-stopped-environments-count"
v-html="state.stoppedCounter"></span>
</a>
</li>
</ul>
<div v-if="canCreateEnvironmentParsed && !isLoading" class="nav-controls">
<a :href="newEnvironmentPath" class="btn btn-create">
New environment
</a>
</div>
</div>
<div class="environments-container">
<div class="environments-list-loading text-center" v-if="isLoading">
<i class="fa fa-spinner spin"></i>
</div>
<div
class="blank-state blank-state-no-icon"
v-if="!isLoading && state.environments.length === 0">
<h2 class="blank-state-title">
You don't have any environments right now.
</h2>
<p class="blank-state-text">
Environments are places where code gets deployed, such as staging or production.
<br />
<a :href="helpPagePath">
Read more about environments
</a>
</p>
<a
v-if="canCreateEnvironmentParsed"
:href="newEnvironmentPath"
class="btn btn-create">
New Environment
</a>
</div>
<div
class="table-holder"
v-if="!isLoading && state.environments.length > 0">
<table class="table ci-table environments">
<thead>
<tr>
<th>Environment</th>
<th>Last deployment</th>
<th>Build</th>
<th>Commit</th>
<th></th>
<th class="hidden-xs"></th>
</tr>
</thead>
<tbody>
<template v-for="model in filteredEnvironments"
v-bind:model="model">
<tr
is="environment-item"
:model="model"
:toggleRow="toggleRow.bind(model)"
:can-create-deployment="canCreateDeploymentParsed"
:can-read-environment="canReadEnvironmentParsed"></tr>
<tr v-if="model.isOpen && model.children && model.children.length > 0"
is="environment-item"
v-for="children in model.children"
:model="children"
:toggleRow="toggleRow.bind(children)">
</tr>
</template>
</tbody>
</table>
</div>
</div>
</div>
`,
});
})();
/*= require vue */
/* global Vue */
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.ActionsComponent = Vue.component('actions-component', {
props: {
actions: {
type: Array,
required: false,
default: () => [],
},
},
/**
* Appends the svg icon that were render in the index page.
* In order to reuse the svg instead of copy and paste in this template
* we need to render it outside this component using =custom_icon partial.
*
* TODO: Remove this when webpack is merged.
*
*/
mounted() {
const playIcon = document.querySelector('.play-icon-svg.hidden svg');
const dropdownContainer = this.$el.querySelector('.dropdown-play-icon-container');
const actionContainers = this.$el.querySelectorAll('.action-play-icon-container');
// Phantomjs does not have support to iterate a nodelist.
const actionsArray = [].slice.call(actionContainers);
if (playIcon && actionsArray && dropdownContainer) {
dropdownContainer.appendChild(playIcon.cloneNode(true));
actionsArray.forEach((element) => {
element.appendChild(playIcon.cloneNode(true));
});
}
},
template: `
<div class="inline">
<div class="dropdown">
<a class="dropdown-new btn btn-default" data-toggle="dropdown">
<span class="dropdown-play-icon-container">
</span>
<i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu dropdown-menu-align-right">
<li v-for="action in actions">
<a :href="action.play_path"
data-method="post"
rel="nofollow"
class="js-manual-action-link">
<span class="action-play-icon-container">
</span>
<span v-html="action.name"></span>
</a>
</li>
</ul>
</div>
</div>
`,
});
})();
/*= require vue */
/* global Vue */
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.ExternalUrlComponent = Vue.component('external-url-component', {
props: {
external_url: {
type: String,
default: '',
},
},
template: `
<a class="btn external_url" :href="external_url" target="_blank">
<i class="fa fa-external-link"></i>
</a>
`,
});
})();
/*= require vue */
/* global Vue */
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.RollbackComponent = Vue.component('rollback-component', {
props: {
retry_url: {
type: String,
default: '',
},
is_last_deployment: {
type: Boolean,
default: true,
},
},
template: `
<a class="btn" :href="retry_url" data-method="post" rel="nofollow">
<span v-if="is_last_deployment">
Re-deploy
</span>
<span v-else>
Rollback
</span>
</a>
`,
});
})();
/*= require vue */
/* global Vue */
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
window.gl.environmentsList.StopComponent = Vue.component('stop-component', {
props: {
stop_url: {
type: String,
default: '',
},
},
template: `
<a
class="btn stop-env-link"
:href="stop_url"
data-confirm="Are you sure you want to stop this environment?"
data-method="post"
rel="nofollow">
<i class="fa fa-stop stop-env-icon"></i>
</a>
`,
});
})();
//= require vue
//= require_tree ./stores/
//= require ./components/environment
//= require ./vue_resource_interceptor
$(() => {
window.gl = window.gl || {};
if (window.gl.EnvironmentsListApp) {
window.gl.EnvironmentsListApp.$destroy(true);
}
const Store = window.gl.environmentsList.EnvironmentsStore;
window.gl.EnvironmentsListApp = new window.gl.environmentsList.EnvironmentsComponent({
el: document.querySelector('#environments-list-view'),
propsData: {
store: Store.create(),
},
});
});
/* globals Vue */
/* eslint-disable no-unused-vars, no-param-reassign */
class EnvironmentsService {
constructor(root) {
Vue.http.options.root = root;
this.environments = Vue.resource(root);
Vue.http.interceptors.push((request, next) => {
// needed in order to not break the tests.
if ($.rails) {
request.headers['X-CSRF-Token'] = $.rails.csrfToken();
}
next();
});
}
all() {
return this.environments.get();
}
}
/* eslint-disable no-param-reassign */
(() => {
window.gl = window.gl || {};
window.gl.environmentsList = window.gl.environmentsList || {};
gl.environmentsList.EnvironmentsStore = {
state: {},
create() {
this.state.environments = [];
this.state.stoppedCounter = 0;
this.state.availableCounter = 0;
return this;
},
/**
* In order to display a tree view we need to modify the received
* data in to a tree structure based on `environment_type`
* sorted alphabetically.
* In each children a `vue-` property will be added. This property will be
* used to know if an item is a children mostly for css purposes. This is
* needed because the children row is a fragment instance and therfore does
* not accept non-prop attributes.
*
*
* @example
* it will transform this:
* [
* { name: "environment", environment_type: "review" },
* { name: "environment_1", environment_type: null }
* { name: "environment_2, environment_type: "review" }
* ]
* into this:
* [
* { name: "review", children:
* [
* { name: "environment", environment_type: "review", vue-isChildren: true},
* { name: "environment_2", environment_type: "review", vue-isChildren: true}
* ]
* },
* {name: "environment_1", environment_type: null}
* ]
*
*
* @param {Array} environments List of environments.
* @returns {Array} Tree structured array with the received environments.
*/
storeEnvironments(environments = []) {
this.state.stoppedCounter = this.countByState(environments, 'stopped');
this.state.availableCounter = this.countByState(environments, 'available');
const environmentsTree = environments.reduce((acc, environment) => {
if (environment.environment_type !== null) {
const occurs = acc.filter(element => element.children &&
element.name === environment.environment_type);
environment['vue-isChildren'] = true;
if (occurs.length) {
acc[acc.indexOf(occurs[0])].children.push(environment);
acc[acc.indexOf(occurs[0])].children.sort(this.sortByName);
} else {
acc.push({
name: environment.environment_type,
children: [environment],
isOpen: false,
'vue-isChildren': environment['vue-isChildren'],
});
}
} else {
acc.push(environment);
}
return acc;
}, []).sort(this.sortByName);
this.state.environments = environmentsTree;
return environmentsTree;
},
/**
* Toggles folder open property given the environment type.
*
* @param {String} envType
* @return {Array}
*/
toggleFolder(envType) {
const environments = this.state.environments;
const environmentsCopy = environments.map((env) => {
if (env['vue-isChildren'] && env.name === envType) {
env.isOpen = !env.isOpen;
}
return env;
});
this.state.environments = environmentsCopy;
return environmentsCopy;
},
/**
* Given an array of environments, returns the number of environments
* that have the given state.
*
* @param {Array} environments
* @param {String} state
* @returns {Number}
*/
countByState(environments, state) {
return environments.filter(env => env.state === state).length;
},
/**
* Sorts the two objects provided by their name.
*
* @param {Object} a
* @param {Object} b
* @returns {Number}
*/
sortByName(a, b) {
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
return nameA < nameB ? -1 : nameA > nameB ? 1 : 0; // eslint-disable-line
},
};
})();
/* global Vue */
Vue.http.interceptors.push((request, next) => {
Vue.activeResources = Vue.activeResources ? Vue.activeResources + 1 : 1;
next((response) => {
if (typeof response.data === 'string') {
response.data = JSON.parse(response.data); // eslint-disable-line
}
Vue.activeResources--; // eslint-disable-line
});
});
/* eslint-disable */ /* eslint-disable no-extend-native, func-names, space-before-function-paren, semi, space-infix-ops, max-len */
Array.prototype.first = function() { Array.prototype.first = function() {
return this[0]; return this[0];
} }
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, object-shorthand, comma-dangle, padded-blocks, max-len */
// Disable an element and add the 'disabled' Bootstrap class // Disable an element and add the 'disabled' Bootstrap class
(function() { (function() {
$.fn.extend({ $.fn.extend({
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, max-len, one-var, one-var-declaration-per-line, quotes, prefer-template, newline-per-chained-call, comma-dangle, new-cap, no-else-return, padded-blocks, consistent-return, no-undef, max-len */
(function() { (function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, no-param-reassign, quotes, quote-props, prefer-template, comma-dangle, padded-blocks, max-len */
(function() { (function() {
this.Flash = (function() { this.Flash = (function() {
var hideFlash; var hideFlash;
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
}, },
// Team Members // Team Members
Members: { Members: {
template: '<li>${username} <small>${title}</small></li>' template: '<li>${avatarTag} ${username} <small>${title}</small></li>'
}, },
Labels: { Labels: {
template: '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>' template: '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>'
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
}, },
DefaultOptions: { DefaultOptions: {
sorter: function(query, items, searchKey) { sorter: function(query, items, searchKey) {
// Highlight first item only if at least one char was typed
this.setting.highlightFirst = this.setting.alwaysHighlightFirst || query.length > 0;
if ((items[0].name != null) && items[0].name === 'loading') { if ((items[0].name != null) && items[0].name === 'loading') {
return items; return items;
} }
...@@ -110,13 +112,14 @@ ...@@ -110,13 +112,14 @@
insertTpl: '${atwho-at}${username}', insertTpl: '${atwho-at}${username}',
searchKey: 'search', searchKey: 'search',
data: ['loading'], data: ['loading'],
alwaysHighlightFirst: true,
callbacks: { callbacks: {
sorter: this.DefaultOptions.sorter, sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter, filter: this.DefaultOptions.filter,
beforeInsert: this.DefaultOptions.beforeInsert, beforeInsert: this.DefaultOptions.beforeInsert,
beforeSave: function(members) { beforeSave: function(members) {
return $.map(members, function(m) { return $.map(members, function(m) {
var title; let title = '';
if (m.username == null) { if (m.username == null) {
return m; return m;
} }
...@@ -124,8 +127,14 @@ ...@@ -124,8 +127,14 @@
if (m.count) { if (m.count) {
title += " (" + m.count + ")"; title += " (" + m.count + ")";
} }
const autoCompleteAvatar = m.avatar_url || m.username.charAt(0).toUpperCase();
const imgAvatar = `<img src="${m.avatar_url}" alt="${m.username}" class="avatar avatar-inline center s26"/>`;
const txtAvatar = `<div class="avatar center avatar-inline s26">${autoCompleteAvatar}</div>`;
return { return {
username: m.username, username: m.username,
avatarTag: autoCompleteAvatar.length === 1 ? txtAvatar : imgAvatar,
title: gl.utils.sanitize(title), title: gl.utils.sanitize(title),
search: gl.utils.sanitize(m.username + " " + m.name) search: gl.utils.sanitize(m.username + " " + m.name)
}; };
...@@ -182,6 +191,7 @@ ...@@ -182,6 +191,7 @@
insertTpl: '${atwho-at}"${title}"', insertTpl: '${atwho-at}"${title}"',
data: ['loading'], data: ['loading'],
callbacks: { callbacks: {
sorter: this.DefaultOptions.sorter,
beforeSave: function(milestones) { beforeSave: function(milestones) {
return $.map(milestones, function(m) { return $.map(milestones, function(m) {
if (m.title == null) { if (m.title == null) {
...@@ -236,6 +246,7 @@ ...@@ -236,6 +246,7 @@
displayTpl: this.Labels.template, displayTpl: this.Labels.template,
insertTpl: '${atwho-at}${title}', insertTpl: '${atwho-at}${title}',
callbacks: { callbacks: {
sorter: this.DefaultOptions.sorter,
beforeSave: function(merges) { beforeSave: function(merges) {
var sanitizeLabelTitle; var sanitizeLabelTitle;
sanitizeLabelTitle = function(title) { sanitizeLabelTitle = function(title) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, space-before-blocks, prefer-rest-params, max-len, vars-on-top, no-plusplus, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, semi, no-return-assign, no-else-return, camelcase, no-undef, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, padded-blocks, prefer-template, no-param-reassign, no-loop-func, no-extra-semi, keyword-spacing, no-mixed-operators, max-len */
(function() { (function() {
var GitLabDropdown, GitLabDropdownFilter, GitLabDropdownRemote, var GitLabDropdown, GitLabDropdownFilter, GitLabDropdownRemote,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
...@@ -249,7 +249,7 @@ ...@@ -249,7 +249,7 @@
_this.fullData = data; _this.fullData = data;
_this.parseData(_this.fullData); _this.parseData(_this.fullData);
_this.focusTextInput(); _this.focusTextInput();
if (_this.options.filterable && _this.filter && _this.filter.input) { if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val().trim() !== '') {
return _this.filter.input.trigger('input'); return _this.filter.input.trigger('input');
} }
}; };
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-undef, no-new, padded-blocks, max-len */
(function() { (function() {
this.GLForm = (function() { this.GLForm = (function() {
function GLForm(form) { function GLForm(form) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren */
// This is a manifest file that'll be compiled into including all the files listed below. // This is a manifest file that'll be compiled into including all the files listed below.
// Add new JavaScript code in separate files in this directory and they'll automatically // Add new JavaScript code in separate files in this directory and they'll automatically
// be included in the compiled file accessible from http://example.com/assets/application.js // be included in the compiled file accessible from http://example.com/assets/application.js
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-return-assign, padded-blocks, max-len */
(function() { (function() {
this.StatGraph = (function() { this.StatGraph = (function() {
function StatGraph() {} function StatGraph() {}
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, no-undef, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign, padded-blocks, max-len */
/*= require d3 */ /*= require d3 */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, one-var, no-var, space-before-blocks, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, padded-blocks, no-undef, newline-per-chained-call, no-else-return, max-len */
/*= require d3 */ /*= require d3 */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, object-shorthand, no-var, one-var, camelcase, one-var-declaration-per-line, no-plusplus, comma-dangle, no-param-reassign, no-return-assign, quotes, prefer-arrow-callback, wrap-iife, consistent-return, no-unused-vars, max-len, no-cond-assign, no-else-return, padded-blocks, max-len */
(function() { (function() {
window.ContributorsStatGraphUtil = { window.ContributorsStatGraphUtil = {
parse_log: function(log) { parse_log: function(log) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, quotes, no-var, one-var, one-var-declaration-per-line, no-useless-escape, padded-blocks, max-len */
(function() { (function() {
this.GroupAvatar = (function() { this.GroupAvatar = (function() {
function GroupAvatar() { function GroupAvatar() {
......
/* eslint-disable */
(function(global) {
class GroupLabelSubscription {
constructor(container) {
const $container = $(container);
this.$dropdown = $container.find('.dropdown');
this.$subscribeButtons = $container.find('.js-subscribe-button');
this.$unsubscribeButtons = $container.find('.js-unsubscribe-button');
this.$subscribeButtons.on('click', this.subscribe.bind(this));
this.$unsubscribeButtons.on('click', this.unsubscribe.bind(this));
}
unsubscribe(event) {
event.preventDefault();
const url = this.$unsubscribeButtons.attr('data-url');
$.ajax({
type: 'POST',
url: url
}).done(() => {
this.toggleSubscriptionButtons();
this.$unsubscribeButtons.removeAttr('data-url');
});
}
subscribe(event) {
event.preventDefault();
const $btn = $(event.currentTarget);
const url = $btn.attr('data-url');
this.$unsubscribeButtons.attr('data-url', url);
$.ajax({
type: 'POST',
url: url
}).done(() => {
this.toggleSubscriptionButtons();
});
}
toggleSubscriptionButtons() {
this.$dropdown.toggleClass('hidden');
this.$subscribeButtons.toggleClass('hidden');
this.$unsubscribeButtons.toggleClass('hidden');
}
}
global.GroupLabelSubscription = GroupLabelSubscription;
})(window.gl || (window.gl = {}));
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, wrap-iife, one-var, camelcase, one-var-declaration-per-line, quotes, object-shorthand, no-undef, prefer-arrow-callback, comma-dangle, consistent-return, yoda, prefer-rest-params, prefer-spread, no-unused-vars, prefer-template, padded-blocks, max-len */
(function() { (function() {
var slice = [].slice; var slice = [].slice;
......
/* eslint-disable */ /* eslint-disable wrap-iife, func-names, space-before-function-paren, padded-blocks, prefer-arrow-callback, no-var, max-len */
(function() { (function() {
$(document).on('todo:toggle', function(e, count) { $(document).on('todo:toggle', function(e, count) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, camelcase, no-var, one-var, one-var-declaration-per-line, prefer-template, quotes, object-shorthand, comma-dangle, no-unused-vars, prefer-arrow-callback, no-else-return, padded-blocks, vars-on-top, no-new, no-undef, max-len */
(function() { (function() {
this.ImporterStatus = (function() { this.ImporterStatus = (function() {
function ImporterStatus(jobs_url, import_url) { function ImporterStatus(jobs_url, import_url) {
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
Issuable.initSearch(); Issuable.initSearch();
Issuable.initChecks(); Issuable.initChecks();
Issuable.initResetFilters(); Issuable.initResetFilters();
Issuable.resetIncomingEmailToken();
return Issuable.initLabelFilterRemove(); return Issuable.initLabelFilterRemove();
}, },
initTemplates: function() { initTemplates: function() {
...@@ -154,6 +155,27 @@ ...@@ -154,6 +155,27 @@
this.issuableBulkActions.willUpdateLabels = false; this.issuableBulkActions.willUpdateLabels = false;
} }
return true; return true;
},
resetIncomingEmailToken: function() {
$('.incoming-email-token-reset').on('click', function(e) {
e.preventDefault();
$.ajax({
type: 'PUT',
url: $('.incoming-email-token-reset').attr('href'),
dataType: 'json',
success: function(response) {
$('#issue_email').val(response.new_issue_address).focus();
},
beforeSend: function() {
$('.incoming-email-token-reset').text('resetting...');
},
complete: function() {
$('.incoming-email-token-reset').text('reset it');
}
});
});
} }
}; };
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, no-undef, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, padded-blocks, max-len */
(function() { (function() {
this.IssuableContext = (function() { this.IssuableContext = (function() {
function IssuableContext(currentUser) { function IssuableContext(currentUser) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-undef, no-new, quotes, object-shorthand, no-unused-vars, comma-dangle, radix, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, padded-blocks, max-len */
(function() { (function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-undef, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, padded-blocks, max-len */
/*= require flash */ /*= require flash */
/*= require jquery.waitforimages */ /*= require jquery.waitforimages */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, object-shorthand, no-unused-vars, no-shadow, one-var, one-var-declaration-per-line, comma-dangle, padded-blocks, max-len */
(function() { (function() {
this.IssueStatusSelect = (function() { this.IssueStatusSelect = (function() {
function IssueStatusSelect() { function IssueStatusSelect() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, space-before-blocks, prefer-rest-params, wrap-iife, vars-on-top, no-unused-vars, padded-blocks, max-len */
(function() { (function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, no-undef, semi, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread, padded-blocks, max-len */
(function() { (function() {
this.LabelsSelect = (function() { this.LabelsSelect = (function() {
function LabelsSelect() { function LabelsSelect() {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, no-unused-vars, one-var, one-var-declaration-per-line, indent, vars-on-top, padded-blocks, max-len */
(function() { (function() {
var hideEndFade; var hideEndFade;
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren */
/*= require Chart */ /*= require Chart */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren */
/*= require cropper */ /*= require cropper */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren */
/*= require d3 */ /*= require d3 */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren */
/*= require raphael */ /*= require raphael */
/*= require g.raphael */ /*= require g.raphael */
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-param-reassign, no-void, prefer-template, no-var, new-cap, prefer-arrow-callback, consistent-return, padded-blocks, max-len */
(function() { (function() {
(function(w) { (function(w) {
if (w.gl == null) { if (w.gl == null) {
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-unused-expressions, no-param-reassign, no-else-return, quotes, object-shorthand, comma-dangle, camelcase, one-var, vars-on-top, one-var-declaration-per-line, no-return-assign, consistent-return, padded-blocks, max-len */
(function() { (function() {
(function(w) { (function(w) {
var base; var base;
...@@ -119,7 +119,6 @@ ...@@ -119,7 +119,6 @@
parser.href = url; parser.href = url;
return parser; return parser;
}; };
gl.utils.cleanupBeforeFetch = function() { gl.utils.cleanupBeforeFetch = function() {
// Unbind scroll events // Unbind scroll events
$(document).off('scroll'); $(document).off('scroll');
...@@ -127,23 +126,10 @@ ...@@ -127,23 +126,10 @@
$('.has-tooltip, [data-toggle="tooltip"]').tooltip('destroy'); $('.has-tooltip, [data-toggle="tooltip"]').tooltip('destroy');
}; };
return jQuery.timefor = function(time, suffix, expiredLabel) { gl.utils.isMetaKey = function(e) {
var suffixFromNow, timefor; return e.metaKey || e.ctrlKey || e.altKey || e.shiftKey;
if (!time) {
return '';
}
suffix || (suffix = 'remaining');
expiredLabel || (expiredLabel = 'Past due');
jQuery.timeago.settings.allowFuture = true;
suffixFromNow = jQuery.timeago.settings.strings.suffixFromNow;
jQuery.timeago.settings.strings.suffixFromNow = suffix;
timefor = $.timeago(time);
if (timefor.indexOf('ago') > -1) {
timefor = expiredLabel;
}
jQuery.timeago.settings.strings.suffixFromNow = suffixFromNow;
return timefor;
}; };
})(window); })(window);
}).call(this); }).call(this);
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, no-undef, comma-dangle, no-unused-expressions, prefer-template, padded-blocks, max-len */
(function() { (function() {
(function(w) { (function(w) {
var base; var base;
...@@ -22,51 +22,64 @@ ...@@ -22,51 +22,64 @@
if (setTimeago == null) { if (setTimeago == null) {
setTimeago = true; setTimeago = true;
} }
$timeagoEls.each(function() { $timeagoEls.each(function() {
var $el; var $el = $(this);
$el = $(this); $el.attr('title', gl.utils.formatDate($el.attr('datetime')));
return $el.attr('title', gl.utils.formatDate($el.attr('datetime')));
if (setTimeago) {
// Recreate with custom template
$el.tooltip({
template: '<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
});
}
gl.utils.renderTimeago($el);
}); });
if (setTimeago) {
$timeagoEls.timeago();
$timeagoEls.tooltip('destroy');
// Recreate with custom template
return $timeagoEls.tooltip({
template: '<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
});
}
}; };
w.gl.utils.shortTimeAgo = function($el) { w.gl.utils.getTimeago = function() {
var shortLocale, tmpLocale; var locale = function(number, index) {
shortLocale = { return [
prefixAgo: null, ['less than a minute ago', 'a while'],
prefixFromNow: null, ['less than a minute ago', 'in %s seconds'],
suffixAgo: 'ago', ['about a minute ago', 'in 1 minute'],
suffixFromNow: 'from now', ['%s minutes ago', 'in %s minutes'],
seconds: '1 min', ['about an hour ago', 'in 1 hour'],
minute: '1 min', ['about %s hours ago', 'in %s hours'],
minutes: '%d mins', ['a day ago', 'in 1 day'],
hour: '1 hr', ['%s days ago', 'in %s days'],
hours: '%d hrs', ['a week ago', 'in 1 week'],
day: '1 day', ['%s weeks ago', 'in %s weeks'],
days: '%d days', ['a month ago', 'in 1 month'],
month: '1 month', ['%s months ago', 'in %s months'],
months: '%d months', ['a year ago', 'in 1 year'],
year: '1 year', ['%s years ago', 'in %s years']
years: '%d years', ][index];
wordSeparator: ' ',
numbers: []
}; };
tmpLocale = $.timeago.settings.strings;
$el.each(function(el) { timeago.register('gl_en', locale);
var $el1; return timeago();
$el1 = $(this); };
return $el1.attr('title', gl.utils.formatDate($el.attr('datetime')));
}); w.gl.utils.timeFor = function(time, suffix, expiredLabel) {
$.timeago.settings.strings = shortLocale; var timefor;
$el.timeago(); if (!time) {
$.timeago.settings.strings = tmpLocale; return '';
}
suffix || (suffix = 'remaining');
expiredLabel || (expiredLabel = 'Past due');
timefor = gl.utils.getTimeago().format(time).replace('in', '');
if (timefor.indexOf('ago') > -1) {
timefor = expiredLabel;
} else {
timefor = timefor.trim() + ' ' + suffix;
}
return timefor;
};
w.gl.utils.renderTimeago = function($element) {
var timeagoInstance = gl.utils.getTimeago();
timeagoInstance.render($element, 'gl_en');
}; };
w.gl.utils.getDayDifference = function(a, b) { w.gl.utils.getDayDifference = function(a, b) {
...@@ -75,7 +88,7 @@ ...@@ -75,7 +88,7 @@
var date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate()); var date2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((date2 - date1) / millisecondsPerDay); return Math.floor((date2 - date1) / millisecondsPerDay);
} };
})(window); })(window);
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, consistent-return, no-undef, prefer-arrow-callback, no-return-assign, object-shorthand, comma-dangle, no-param-reassign, padded-blocks, max-len */
(function() { (function() {
(function(w) { (function(w) {
var notificationGranted, notifyMe, notifyPermissions; var notificationGranted, notifyMe, notifyPermissions;
......
/* eslint-disable */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, semi, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, padded-blocks, max-len */
(function() { (function() {
(function(w) { (function(w) {
var base; var base;
...@@ -112,6 +112,9 @@ ...@@ -112,6 +112,9 @@
gl.text.removeListeners = function(form) { gl.text.removeListeners = function(form) {
return $('.js-md', form).off(); return $('.js-md', form).off();
}; };
gl.text.humanize = function(string) {
return string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1);
}
return gl.text.truncate = function(string, maxLength) { return gl.text.truncate = function(string, maxLength) {
return string.substr(0, (maxLength - 3)) + '...'; return string.substr(0, (maxLength - 3)) + '...';
}; };
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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