Merge branch 'master' into 42886-followup-to-new-design-for-cancel-stop-pipeline-confirmation

This commit is contained in:
Shah El-Rahman 2018-02-21 17:59:42 -06:00
commit ad860cc0ef
413 changed files with 5817 additions and 6920 deletions

View File

@ -15,7 +15,7 @@ engines:
enabled: false enabled: false
rubocop: rubocop:
enabled: true enabled: true
channel: "gitlab-rubocop-0-52" channel: "gitlab-rubocop-0-52-1"
ratings: ratings:
paths: paths:
- Gemfile.lock - Gemfile.lock

View File

@ -323,69 +323,69 @@ setup-test-env:
- tmp/tests - tmp/tests
- config/secrets.yml - config/secrets.yml
rspec-pg 0 27: *rspec-metadata-pg rspec-pg 0 28: *rspec-metadata-pg
rspec-pg 1 27: *rspec-metadata-pg rspec-pg 1 28: *rspec-metadata-pg
rspec-pg 2 27: *rspec-metadata-pg rspec-pg 2 28: *rspec-metadata-pg
rspec-pg 3 27: *rspec-metadata-pg rspec-pg 3 28: *rspec-metadata-pg
rspec-pg 4 27: *rspec-metadata-pg rspec-pg 4 28: *rspec-metadata-pg
rspec-pg 5 27: *rspec-metadata-pg rspec-pg 5 28: *rspec-metadata-pg
rspec-pg 6 27: *rspec-metadata-pg rspec-pg 6 28: *rspec-metadata-pg
rspec-pg 7 27: *rspec-metadata-pg rspec-pg 7 28: *rspec-metadata-pg
rspec-pg 8 27: *rspec-metadata-pg rspec-pg 8 28: *rspec-metadata-pg
rspec-pg 9 27: *rspec-metadata-pg rspec-pg 9 28: *rspec-metadata-pg
rspec-pg 10 27: *rspec-metadata-pg rspec-pg 10 28: *rspec-metadata-pg
rspec-pg 11 27: *rspec-metadata-pg rspec-pg 11 28: *rspec-metadata-pg
rspec-pg 12 27: *rspec-metadata-pg rspec-pg 12 28: *rspec-metadata-pg
rspec-pg 13 27: *rspec-metadata-pg rspec-pg 13 28: *rspec-metadata-pg
rspec-pg 14 27: *rspec-metadata-pg rspec-pg 14 28: *rspec-metadata-pg
rspec-pg 15 27: *rspec-metadata-pg rspec-pg 15 28: *rspec-metadata-pg
rspec-pg 16 27: *rspec-metadata-pg rspec-pg 16 28: *rspec-metadata-pg
rspec-pg 17 27: *rspec-metadata-pg rspec-pg 17 28: *rspec-metadata-pg
rspec-pg 18 27: *rspec-metadata-pg rspec-pg 18 28: *rspec-metadata-pg
rspec-pg 19 27: *rspec-metadata-pg rspec-pg 19 28: *rspec-metadata-pg
rspec-pg 20 27: *rspec-metadata-pg rspec-pg 20 28: *rspec-metadata-pg
rspec-pg 21 27: *rspec-metadata-pg rspec-pg 21 28: *rspec-metadata-pg
rspec-pg 22 27: *rspec-metadata-pg rspec-pg 22 28: *rspec-metadata-pg
rspec-pg 23 27: *rspec-metadata-pg rspec-pg 23 28: *rspec-metadata-pg
rspec-pg 24 27: *rspec-metadata-pg rspec-pg 24 28: *rspec-metadata-pg
rspec-pg 25 27: *rspec-metadata-pg rspec-pg 25 28: *rspec-metadata-pg
rspec-pg 26 27: *rspec-metadata-pg rspec-pg 26 28: *rspec-metadata-pg
rspec-pg 27 28: *rspec-metadata-pg
rspec-mysql 0 27: *rspec-metadata-mysql rspec-mysql 0 28: *rspec-metadata-mysql
rspec-mysql 1 27: *rspec-metadata-mysql rspec-mysql 1 28: *rspec-metadata-mysql
rspec-mysql 2 27: *rspec-metadata-mysql rspec-mysql 2 28: *rspec-metadata-mysql
rspec-mysql 3 27: *rspec-metadata-mysql rspec-mysql 3 28: *rspec-metadata-mysql
rspec-mysql 4 27: *rspec-metadata-mysql rspec-mysql 4 28: *rspec-metadata-mysql
rspec-mysql 5 27: *rspec-metadata-mysql rspec-mysql 5 28: *rspec-metadata-mysql
rspec-mysql 6 27: *rspec-metadata-mysql rspec-mysql 6 28: *rspec-metadata-mysql
rspec-mysql 7 27: *rspec-metadata-mysql rspec-mysql 7 28: *rspec-metadata-mysql
rspec-mysql 8 27: *rspec-metadata-mysql rspec-mysql 8 28: *rspec-metadata-mysql
rspec-mysql 9 27: *rspec-metadata-mysql rspec-mysql 9 28: *rspec-metadata-mysql
rspec-mysql 10 27: *rspec-metadata-mysql rspec-mysql 10 28: *rspec-metadata-mysql
rspec-mysql 11 27: *rspec-metadata-mysql rspec-mysql 11 28: *rspec-metadata-mysql
rspec-mysql 12 27: *rspec-metadata-mysql rspec-mysql 12 28: *rspec-metadata-mysql
rspec-mysql 13 27: *rspec-metadata-mysql rspec-mysql 13 28: *rspec-metadata-mysql
rspec-mysql 14 27: *rspec-metadata-mysql rspec-mysql 14 28: *rspec-metadata-mysql
rspec-mysql 15 27: *rspec-metadata-mysql rspec-mysql 15 28: *rspec-metadata-mysql
rspec-mysql 16 27: *rspec-metadata-mysql rspec-mysql 16 28: *rspec-metadata-mysql
rspec-mysql 17 27: *rspec-metadata-mysql rspec-mysql 17 28: *rspec-metadata-mysql
rspec-mysql 18 27: *rspec-metadata-mysql rspec-mysql 18 28: *rspec-metadata-mysql
rspec-mysql 19 27: *rspec-metadata-mysql rspec-mysql 19 28: *rspec-metadata-mysql
rspec-mysql 20 27: *rspec-metadata-mysql rspec-mysql 20 28: *rspec-metadata-mysql
rspec-mysql 21 27: *rspec-metadata-mysql rspec-mysql 21 28: *rspec-metadata-mysql
rspec-mysql 22 27: *rspec-metadata-mysql rspec-mysql 22 28: *rspec-metadata-mysql
rspec-mysql 23 27: *rspec-metadata-mysql rspec-mysql 23 28: *rspec-metadata-mysql
rspec-mysql 24 27: *rspec-metadata-mysql rspec-mysql 24 28: *rspec-metadata-mysql
rspec-mysql 25 27: *rspec-metadata-mysql rspec-mysql 25 28: *rspec-metadata-mysql
rspec-mysql 26 27: *rspec-metadata-mysql rspec-mysql 26 28: *rspec-metadata-mysql
rspec-mysql 27 28: *rspec-metadata-mysql
spinach-pg 0 3: *spinach-metadata-pg spinach-pg 0 2: *spinach-metadata-pg
spinach-pg 1 3: *spinach-metadata-pg spinach-pg 1 2: *spinach-metadata-pg
spinach-pg 2 3: *spinach-metadata-pg
spinach-mysql 0 3: *spinach-metadata-mysql spinach-mysql 0 2: *spinach-metadata-mysql
spinach-mysql 1 3: *spinach-metadata-mysql spinach-mysql 1 2: *spinach-metadata-mysql
spinach-mysql 2 3: *spinach-metadata-mysql
# Static analysis jobs # Static analysis jobs
.ruby-static-analysis: &ruby-static-analysis .ruby-static-analysis: &ruby-static-analysis
@ -607,22 +607,24 @@ karma:
codequality: codequality:
<<: *except-docs <<: *except-docs
<<: *pull-cache <<: *pull-cache
before_script: []
image: docker:latest
stage: test stage: test
variables: image: docker:latest
SETUP_DB: "false" before_script: []
DOCKER_DRIVER: overlay
services: services:
- docker:dind - docker:dind
variables:
SETUP_DB: "false"
DOCKER_DRIVER: overlay2
CODECLIMATE_FORMAT: json
cache: {}
dependencies: []
script: script:
- cp .rubocop.yml .rubocop.yml.bak - ./scripts/codequality analyze -f json > raw_codeclimate.json || true
- grep -v "rubocop-gitlab-security" .rubocop.yml.bak > .rubocop.yml # The following line keeps only the fields used in the MR widget, reducing the JSON artifact size
- docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc dev.gitlab.org:5005/gitlab/gitlab-build-images:gitlab-codeclimate-v2 analyze -f json > raw_codeclimate.json - cat raw_codeclimate.json | docker run -i stedolan/jq -c 'map({check_name,description,fingerprint,location})' > codeclimate.json
- cat raw_codeclimate.json | docker run -i stedolan/jq -c 'map({check_name,fingerprint,location})' > codeclimate.json
- mv .rubocop.yml.bak .rubocop.yml
artifacts: artifacts:
paths: [codeclimate.json] paths: [codeclimate.json]
expire_in: 1 week
sast: sast:
<<: *except-docs <<: *except-docs

View File

@ -81,7 +81,7 @@ gem 'gollum-lib', '~> 4.2', require: false
gem 'gollum-rugged_adapter', '~> 0.4.4', require: false gem 'gollum-rugged_adapter', '~> 0.4.4', require: false
# Language detection # Language detection
gem 'github-linguist', '~> 4.7.0', require: 'linguist' gem 'github-linguist', '~> 5.3.3', require: 'linguist'
# API # API
gem 'grape', '~> 1.0' gem 'grape', '~> 1.0'
@ -401,6 +401,7 @@ gem 'sys-filesystem', '~> 1.1.6'
# SSH host key support # SSH host key support
gem 'net-ssh', '~> 4.1.0' gem 'net-ssh', '~> 4.1.0'
gem 'sshkey', '~> 1.9.0'
# Required for ED25519 SSH host key support # Required for ED25519 SSH host key support
group :ed25519 do group :ed25519 do
@ -414,7 +415,7 @@ gem 'gitaly-proto', '~> 0.84.0', require: 'gitaly'
# Locked until https://github.com/google/protobuf/issues/4210 is closed # Locked until https://github.com/google/protobuf/issues/4210 is closed
gem 'google-protobuf', '= 3.5.1' gem 'google-protobuf', '= 3.5.1'
gem 'toml-rb', '~> 0.3.15', require: false gem 'toml-rb', '~> 1.0.0', require: false
# Feature toggles # Feature toggles
gem 'flipper', '~> 0.11.0' gem 'flipper', '~> 0.11.0'

View File

@ -288,11 +288,11 @@ GEM
gitaly-proto (0.84.0) gitaly-proto (0.84.0)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
grpc (~> 1.0) grpc (~> 1.0)
github-linguist (4.7.6) github-linguist (5.3.3)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.5)
escape_utils (~> 1.1.0) escape_utils (~> 1.1.0)
mime-types (>= 1.19) mime-types (>= 1.19)
rugged (>= 0.23.0b) rugged (>= 0.25.1)
github-markup (1.6.1) github-markup (1.6.1)
gitlab-flowdock-git-hook (1.0.1) gitlab-flowdock-git-hook (1.0.1)
flowdock (~> 0.7) flowdock (~> 0.7)
@ -895,6 +895,7 @@ GEM
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sqlite3 (1.3.13) sqlite3 (1.3.13)
sshkey (1.9.0)
stackprof (0.2.10) stackprof (0.2.10)
state_machines (0.4.0) state_machines (0.4.0)
state_machines-activemodel (0.4.0) state_machines-activemodel (0.4.0)
@ -923,7 +924,7 @@ GEM
timfel-krb5-auth (0.8.3) timfel-krb5-auth (0.8.3)
toml (0.1.2) toml (0.1.2)
parslet (~> 1.5.0) parslet (~> 1.5.0)
toml-rb (0.3.15) toml-rb (1.0.0)
citrus (~> 3.0, > 3.0) citrus (~> 3.0, > 3.0)
truncato (0.7.10) truncato (0.7.10)
htmlentities (~> 4.3.1) htmlentities (~> 4.3.1)
@ -1057,7 +1058,7 @@ DEPENDENCIES
gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0) gettext_i18n_rails_js (~> 1.2.0)
gitaly-proto (~> 0.84.0) gitaly-proto (~> 0.84.0)
github-linguist (~> 4.7.0) github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1) gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.6.2) gitlab-markup (~> 1.6.2)
gitlab-styles (~> 2.3) gitlab-styles (~> 2.3)
@ -1192,6 +1193,7 @@ DEPENDENCIES
spring-commands-rspec (~> 1.0.4) spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.1.0) spring-commands-spinach (~> 1.1.0)
sprockets (~> 3.7.0) sprockets (~> 3.7.0)
sshkey (~> 1.9.0)
stackprof (~> 0.2.10) stackprof (~> 0.2.10)
state_machines-activerecord (~> 0.4.0) state_machines-activerecord (~> 0.4.0)
sys-filesystem (~> 1.1.6) sys-filesystem (~> 1.1.6)
@ -1199,7 +1201,7 @@ DEPENDENCIES
test_after_commit (~> 1.1) test_after_commit (~> 1.1)
thin (~> 1.7.0) thin (~> 1.7.0)
timecop (~> 0.8.0) timecop (~> 0.8.0)
toml-rb (~> 0.3.15) toml-rb (~> 1.0.0)
truncato (~> 0.7.9) truncato (~> 0.7.9)
u2f (~> 0.2.1) u2f (~> 0.2.1)
uglifier (~> 2.7.2) uglifier (~> 2.7.2)

View File

@ -312,7 +312,7 @@ class AwardsHandler {
} }
getAwardUrl() { getAwardUrl() {
return this.getVotesBlock().data('award-url'); return this.getVotesBlock().data('awardUrl');
} }
checkMutuality(votesBlock, emoji) { checkMutuality(votesBlock, emoji) {

View File

@ -2,7 +2,7 @@ import Clipboard from 'clipboard';
function showTooltip(target, title) { function showTooltip(target, title) {
const $target = $(target); const $target = $(target);
const originalTitle = $target.data('original-title'); const originalTitle = $target.data('originalTitle');
if (!$target.data('hideTooltip')) { if (!$target.data('hideTooltip')) {
$target $target

View File

@ -43,7 +43,7 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
const $form = $(e.target).closest('form'); const $form = $(e.target).closest('form');
const $submitButton = $form.find('input[type=submit], button[type=submit]').first(); const $submitButton = $form.find('input[type=submit], button[type=submit]').first();
if (!$submitButton.attr('disabled')) { if (!$submitButton.prop('disabled')) {
$submitButton.trigger('click', [e]); $submitButton.trigger('click', [e]);
if (!isInIssuePage()) { if (!isInIssuePage()) {

View File

@ -40,7 +40,7 @@ $.fn.requiresInput = function requiresInput() {
// based on the option selected // based on the option selected
function hideOrShowHelpBlock(form) { function hideOrShowHelpBlock(form) {
const selected = $('.js-select-namespace option:selected'); const selected = $('.js-select-namespace option:selected');
if (selected.length && selected.data('options-parent') === 'groups') { if (selected.length && selected.data('optionsParent') === 'groups') {
form.find('.help-block').hide(); form.find('.help-block').hide();
} else if (selected.length) { } else if (selected.length) {
form.find('.help-block').show(); form.find('.help-block').show();

View File

@ -4,16 +4,16 @@ import NewCommitForm from '../new_commit_form';
import EditBlob from './edit_blob'; import EditBlob from './edit_blob';
import BlobFileDropzone from '../blob/blob_file_dropzone'; import BlobFileDropzone from '../blob/blob_file_dropzone';
$(() => { export default () => {
const editBlobForm = $('.js-edit-blob-form'); const editBlobForm = $('.js-edit-blob-form');
const uploadBlobForm = $('.js-upload-blob-form'); const uploadBlobForm = $('.js-upload-blob-form');
const deleteBlobForm = $('.js-delete-blob-form'); const deleteBlobForm = $('.js-delete-blob-form');
if (editBlobForm.length) { if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relative-url-root'); const urlRoot = editBlobForm.data('relativeUrlRoot');
const assetsPath = editBlobForm.data('assets-prefix'); const assetsPath = editBlobForm.data('assetsPrefix');
const blobLanguage = editBlobForm.data('blob-language'); const blobLanguage = editBlobForm.data('blobLanguage');
const currentAction = $('.js-file-title').data('current-action'); const currentAction = $('.js-file-title').data('currentAction');
new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction); new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction);
new NewCommitForm(editBlobForm); new NewCommitForm(editBlobForm);
@ -34,4 +34,4 @@ $(() => {
if (deleteBlobForm.length) { if (deleteBlobForm.length) {
new NewCommitForm(deleteBlobForm); new NewCommitForm(deleteBlobForm);
} }
}); };

View File

@ -59,7 +59,7 @@ export default class EditBlob {
if (paneId === '#preview') { if (paneId === '#preview') {
this.$toggleButton.hide(); this.$toggleButton.hide();
axios.post(currentLink.data('preview-url'), { axios.post(currentLink.data('previewUrl'), {
content: this.editor.getValue(), content: this.editor.getValue(),
}) })
.then(({ data }) => { .then(({ data }) => {

View File

@ -25,7 +25,7 @@ $(document).off('created.label').on('created.label', (e, label) => {
gl.issueBoards.newListDropdownInit = () => { gl.issueBoards.newListDropdownInit = () => {
$('.js-new-board-list').each(function () { $('.js-new-board-list').each(function () {
const $this = $(this); const $this = $(this);
new CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path')); new CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespacePath'), $this.data('projectPath'));
$this.glDropdown({ $this.glDropdown({
data(term, callback) { data(term, callback) {

View File

@ -1,7 +1,8 @@
/* eslint-disable class-methods-use-this */ /* eslint-disable class-methods-use-this */
import FilteredSearchContainer from '../filtered_search/container'; import FilteredSearchContainer from '../filtered_search/container';
import FilteredSearchManager from '../filtered_search/filtered_search_manager';
export default class FilteredSearchBoards extends gl.FilteredSearchManager { export default class FilteredSearchBoards extends FilteredSearchManager {
constructor(store, updateUrl = false, cantEdit = []) { constructor(store, updateUrl = false, cantEdit = []) {
super('boards'); super('boards');

View File

@ -13,6 +13,6 @@ import 'bootstrap-sass/assets/javascripts/bootstrap/popover';
// custom jQuery functions // custom jQuery functions
$.fn.extend({ $.fn.extend({
disable() { return $(this).attr('disabled', 'disabled').addClass('disabled'); }, disable() { return $(this).prop('disabled', true).addClass('disabled'); },
enable() { return $(this).removeAttr('disabled').removeClass('disabled'); }, enable() { return $(this).prop('disabled', false).removeClass('disabled'); },
}); });

View File

@ -13,7 +13,7 @@ export default class Compare {
$dropdown = $(dropdown); $dropdown = $(dropdown);
return $dropdown.glDropdown({ return $dropdown.glDropdown({
selectable: true, selectable: true,
fieldName: $dropdown.data('field-name'), fieldName: $dropdown.data('fieldName'),
filterable: true, filterable: true,
id: function(obj, $el) { id: function(obj, $el) {
return $el.data('id'); return $el.data('id');

View File

@ -9,7 +9,7 @@ export default function initCompareAutocomplete() {
$dropdown = $(this); $dropdown = $(this);
selected = $dropdown.data('selected'); selected = $dropdown.data('selected');
const $dropdownContainer = $dropdown.closest('.dropdown'); const $dropdownContainer = $dropdown.closest('.dropdown');
const $fieldInput = $(`input[name="${$dropdown.data('field-name')}"]`, $dropdownContainer); const $fieldInput = $(`input[name="${$dropdown.data('fieldName')}"]`, $dropdownContainer);
const $filterInput = $('input[type="search"]', $dropdownContainer); const $filterInput = $('input[type="search"]', $dropdownContainer);
$dropdown.glDropdown({ $dropdown.glDropdown({
data: function(term, callback) { data: function(term, callback) {
@ -25,7 +25,7 @@ export default function initCompareAutocomplete() {
selectable: true, selectable: true,
filterable: true, filterable: true,
filterRemote: true, filterRemote: true,
fieldName: $dropdown.data('field-name'), fieldName: $dropdown.data('fieldName'),
filterInput: 'input[type="search"]', filterInput: 'input[type="search"]',
renderRow: function(ref) { renderRow: function(ref) {
var link; var link;

View File

@ -68,7 +68,7 @@ export default class Diff {
} }
const file = $target.parents('.diff-file'); const file = $target.parents('.diff-file');
const link = file.data('blob-diff-path'); const link = file.data('blobDiffPath');
const view = file.data('view'); const view = file.data('view');
const params = { since, to, bottom, offset, unfold, view }; const params = { since, to, bottom, offset, unfold, view };
@ -121,7 +121,7 @@ export default class Diff {
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
diffViewType() { diffViewType() {
return $('.inline-parallel-buttons a.active').data('view-type'); return $('.inline-parallel-buttons a.active').data('viewType');
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
lineNumbers(line) { lineNumbers(line) {

View File

@ -15,7 +15,7 @@ import './components/resolve_discussion_btn';
import './components/diff_note_avatars'; import './components/diff_note_avatars';
import './components/new_issue_for_discussion'; import './components/new_issue_for_discussion';
$(() => { export default () => {
const projectPathHolder = document.querySelector('.merge-request') || document.querySelector('.commit-box'); const projectPathHolder = document.querySelector('.merge-request') || document.querySelector('.commit-box');
const projectPath = projectPathHolder.dataset.projectPath; const projectPath = projectPathHolder.dataset.projectPath;
const COMPONENT_SELECTOR = 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn, new-issue-for-discussion-btn'; const COMPONENT_SELECTOR = 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn, new-issue-for-discussion-btn';
@ -75,4 +75,4 @@ $(() => {
}); });
$(window).trigger('resize.nav'); $(window).trigger('resize.nav');
}); };

View File

@ -43,283 +43,21 @@ var Dispatcher;
}); });
switch (page) { switch (page) {
case 'projects:environments:metrics':
import('./pages/projects/environments/metrics')
.then(callDefault)
.catch(fail);
break;
case 'projects:merge_requests:index': case 'projects:merge_requests:index':
case 'projects:issues:index': case 'projects:issues:index':
case 'projects:issues:show': case 'projects:issues:show':
shortcut_handler = true;
break;
case 'projects:milestones:index':
import('./pages/projects/milestones/index')
.then(callDefault)
.catch(fail);
break;
case 'projects:milestones:show':
import('./pages/projects/milestones/show')
.then(callDefault)
.catch(fail);
break;
case 'groups:milestones:show':
import('./pages/groups/milestones/show')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:milestones:show':
import('./pages/dashboard/milestones/show')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:issues':
import('./pages/dashboard/issues')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:merge_requests':
import('./pages/dashboard/merge_requests')
.then(callDefault)
.catch(fail);
break;
case 'groups:issues':
import('./pages/groups/issues')
.then(callDefault)
.catch(fail);
break;
case 'groups:merge_requests':
import('./pages/groups/merge_requests')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:todos:index':
import('./pages/dashboard/todos/index')
.then(callDefault)
.catch(fail);
break;
case 'admin:jobs:index':
import('./pages/admin/jobs/index')
.then(callDefault)
.catch(fail);
break;
case 'admin:projects:index':
import('./pages/admin/projects/index/index')
.then(callDefault)
.catch(fail);
break;
case 'admin:users:index':
import('./pages/admin/users/shared')
.then(callDefault)
.catch(fail);
break;
case 'admin:users:show':
import('./pages/admin/users/shared')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:projects:index':
case 'dashboard:projects:starred':
import('./pages/dashboard/projects')
.then(callDefault)
.catch(fail);
break;
case 'explore:projects:index':
case 'explore:projects:trending':
case 'explore:projects:starred':
import('./pages/explore/projects')
.then(callDefault)
.catch(fail);
break;
case 'explore:groups:index':
import('./pages/explore/groups')
.then(callDefault)
.catch(fail);
break;
case 'projects:milestones:new':
case 'projects:milestones:create':
import('./pages/projects/milestones/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:milestones:edit':
case 'projects:milestones:update':
import('./pages/projects/milestones/edit')
.then(callDefault)
.catch(fail);
break;
case 'groups:milestones:new':
case 'groups:milestones:create':
import('./pages/groups/milestones/new')
.then(callDefault)
.catch(fail);
break;
case 'groups:milestones:edit':
case 'groups:milestones:update':
import('./pages/groups/milestones/edit')
.then(callDefault)
.catch(fail);
break;
case 'projects:compare:show':
import('./pages/projects/compare/show')
.then(callDefault)
.catch(fail);
break;
case 'projects:branches:new':
import('./pages/projects/branches/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:branches:create':
import('./pages/projects/branches/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:branches:index':
import('./pages/projects/branches/index')
.then(callDefault)
.catch(fail);
break;
case 'projects:issues:new': case 'projects:issues:new':
import('./pages/projects/issues/new')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:issues:edit': case 'projects:issues:edit':
import('./pages/projects/issues/edit')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:merge_requests:creations:new': case 'projects:merge_requests:creations:new':
import('./pages/projects/merge_requests/creations/new')
.then(callDefault)
.catch(fail);
case 'projects:merge_requests:creations:diffs': case 'projects:merge_requests:creations:diffs':
import('./pages/projects/merge_requests/creations/diffs')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:merge_requests:edit': case 'projects:merge_requests:edit':
import('./pages/projects/merge_requests/edit')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:tags:new':
import('./pages/projects/tags/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:snippets:show':
import('./pages/projects/snippets/show')
.then(callDefault)
.catch(fail);
break;
case 'projects:snippets:new':
case 'projects:snippets:create':
import('./pages/projects/snippets/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:services:edit':
import('./pages/projects/services/edit')
.then(callDefault)
.catch(fail);
break;
case 'projects:snippets:edit':
case 'projects:snippets:update':
import('./pages/projects/snippets/edit')
.then(callDefault)
.catch(fail);
break;
case 'snippets:new':
import('./pages/snippets/new')
.then(callDefault)
.catch(fail);
break;
case 'snippets:edit':
import('./pages/snippets/edit')
.then(callDefault)
.catch(fail);
break;
case 'snippets:create':
import('./pages/snippets/new')
.then(callDefault)
.catch(fail);
break;
case 'snippets:update':
import('./pages/snippets/edit')
.then(callDefault)
.catch(fail);
break;
case 'projects:releases:edit':
import('./pages/projects/releases/edit')
.then(callDefault)
.catch(fail);
break;
case 'projects:merge_requests:show': case 'projects:merge_requests:show':
import('./pages/projects/merge_requests/show')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'dashboard:activity':
import('./pages/dashboard/activity')
.then(callDefault)
.catch(fail);
break;
case 'projects:commit:show': case 'projects:commit:show':
import('./pages/projects/commit/show')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:commit:pipelines':
import('./pages/projects/commit/pipelines')
.then(callDefault)
.catch(fail);
break;
case 'projects:activity': case 'projects:activity':
import('./pages/projects/activity')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:commits:show': case 'projects:commits:show':
import('./pages/projects/commits/show')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:show': case 'projects:show':
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'projects:edit':
import('./pages/projects/edit')
.then(callDefault)
.catch(fail);
break;
case 'projects:imports:show':
import('./pages/projects/imports/show')
.then(callDefault)
.catch(fail);
break;
case 'projects:pipelines:new':
case 'projects:pipelines:create':
import('./pages/projects/pipelines/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:pipelines:builds':
case 'projects:pipelines:failures':
case 'projects:pipelines:show':
import('./pages/projects/pipelines/builds')
.then(callDefault)
.catch(fail);
break;
case 'groups:activity': case 'groups:activity':
import('./pages/groups/activity') import('./pages/groups/activity')
.then(callDefault) .then(callDefault)
@ -436,11 +174,6 @@ var Dispatcher;
.catch(fail); .catch(fail);
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'help:index':
import('./pages/help')
.then(callDefault)
.catch(fail);
break;
case 'search:show': case 'search:show':
import('./pages/search/show') import('./pages/search/show')
.then(callDefault) .then(callDefault)
@ -472,11 +205,6 @@ var Dispatcher;
.then(callDefault) .then(callDefault)
.catch(fail); .catch(fail);
break; break;
case 'snippets:show':
import('./pages/snippets/show')
.then(callDefault)
.catch(fail);
break;
case 'import:fogbugz:new_user_map': case 'import:fogbugz:new_user_map':
import('./pages/import/fogbugz/new_user_map') import('./pages/import/fogbugz/new_user_map')
.then(callDefault) .then(callDefault)
@ -492,18 +220,6 @@ var Dispatcher;
.then(callDefault) .then(callDefault)
.catch(fail); .catch(fail);
break; break;
case 'projects:clusters:show':
case 'projects:clusters:update':
case 'projects:clusters:destroy':
import('./pages/projects/clusters/show')
.then(callDefault)
.catch(fail);
break;
case 'projects:clusters:index':
import('./pages/projects/clusters/index')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:groups:index': case 'dashboard:groups:index':
import('./pages/dashboard/groups/index') import('./pages/dashboard/groups/index')
.then(callDefault) .then(callDefault)
@ -511,20 +227,7 @@ var Dispatcher;
break; break;
} }
switch (path[0]) { switch (path[0]) {
case 'sessions':
import('./pages/sessions')
.then(callDefault)
.catch(fail);
break;
case 'omniauth_callbacks':
import('./pages/omniauth_callbacks')
.then(callDefault)
.catch(fail);
break;
case 'admin': case 'admin':
import('./pages/admin')
.then(callDefault)
.catch(fail);
switch (path[1]) { switch (path[1]) {
case 'broadcast_messages': case 'broadcast_messages':
import('./pages/admin/broadcast_messages') import('./pages/admin/broadcast_messages')

View File

@ -4,10 +4,7 @@ function addMousetrapClick(el, key) {
el.addEventListener('click', () => Mousetrap.trigger(key)); el.addEventListener('click', () => Mousetrap.trigger(key));
} }
function domContentLoaded() { export default () => {
addMousetrapClick(document.querySelector('.js-trigger-shortcut'), '?'); addMousetrapClick(document.querySelector('.js-trigger-shortcut'), '?');
addMousetrapClick(document.querySelector('.js-trigger-search-bar'), 's'); addMousetrapClick(document.querySelector('.js-trigger-search-bar'), 's');
} };
document.addEventListener('DOMContentLoaded', domContentLoaded);

View File

@ -17,9 +17,9 @@ class DueDateSelect {
this.$value = $block.find('.value'); this.$value = $block.find('.value');
this.$valueContent = $block.find('.value-content'); this.$valueContent = $block.find('.value-content');
this.$sidebarValue = $('.js-due-date-sidebar-value', $block); this.$sidebarValue = $('.js-due-date-sidebar-value', $block);
this.fieldName = $dropdown.data('field-name'); this.fieldName = $dropdown.data('fieldName');
this.abilityName = $dropdown.data('ability-name'); this.abilityName = $dropdown.data('abilityName');
this.issueUpdateURL = $dropdown.data('issue-update'); this.issueUpdateURL = $dropdown.data('issueUpdate');
this.rawSelectedDate = null; this.rawSelectedDate = null;
this.displayedDate = null; this.displayedDate = null;

View File

@ -25,7 +25,7 @@ export default {
if (!this.userCanCreateNote) { if (!this.userCanCreateNote) {
// data-can-create-note is an empty string when true, otherwise undefined // data-can-create-note is an empty string when true, otherwise undefined
this.userCanCreateNote = $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('can-create-note') === ''; this.userCanCreateNote = $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('canCreateNote') === '';
} }
this.isParallelView = Cookies.get('diff_view') === 'parallel'; this.isParallelView = Cookies.get('diff_view') === 'parallel';

View File

@ -1,4 +1,5 @@
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import FilteredSearchTokenizer from '../filtered_search_tokenizer';
export default { export default {
name: 'RecentSearchesDropdownContent', name: 'RecentSearchesDropdownContent',
@ -23,7 +24,7 @@ export default {
processedItems() { processedItems() {
return this.items.map((item) => { return this.items.map((item) => {
const { tokens, searchToken } const { tokens, searchToken }
= gl.FilteredSearchTokenizer.processTokens(item, this.allowedKeys); = FilteredSearchTokenizer.processTokens(item, this.allowedKeys);
const resultantTokens = tokens.map(token => ({ const resultantTokens = tokens.map(token => ({
prefix: `${token.key}:`, prefix: `${token.key}:`,

View File

@ -1,9 +1,10 @@
import Flash from '../flash'; import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax'; import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter'; import Filter from '../droplab/plugins/filter';
import './filtered_search_dropdown'; import FilteredSearchDropdown from './filtered_search_dropdown';
import DropdownUtils from './dropdown_utils';
class DropdownEmoji extends gl.FilteredSearchDropdown { export default class DropdownEmoji extends FilteredSearchDropdown {
constructor(options = {}) { constructor(options = {}) {
super(options); super(options);
this.config = { this.config = {
@ -49,7 +50,7 @@ class DropdownEmoji extends gl.FilteredSearchDropdown {
itemClicked(e) { itemClicked(e) {
super.itemClicked(e, (selected) => { super.itemClicked(e, (selected) => {
const name = selected.querySelector('.js-data-value').innerText.trim(); const name = selected.querySelector('.js-data-value').innerText.trim();
return gl.DropdownUtils.getEscapedText(name); return DropdownUtils.getEscapedText(name);
}); });
} }
@ -76,6 +77,3 @@ class DropdownEmoji extends gl.FilteredSearchDropdown {
.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init(); .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
} }
} }
window.gl = window.gl || {};
gl.DropdownEmoji = DropdownEmoji;

View File

@ -1,14 +1,17 @@
import Filter from '~/droplab/plugins/filter'; import Filter from '~/droplab/plugins/filter';
import './filtered_search_dropdown'; import FilteredSearchDropdown from './filtered_search_dropdown';
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
class DropdownHint extends gl.FilteredSearchDropdown { export default class DropdownHint extends FilteredSearchDropdown {
constructor(options = {}) { constructor(options = {}) {
const { input, tokenKeys } = options; const { input, tokenKeys } = options;
super(options); super(options);
this.config = { this.config = {
Filter: { Filter: {
template: 'hint', template: 'hint',
filterFunction: gl.DropdownUtils.filterHint.bind(null, { filterFunction: DropdownUtils.filterHint.bind(null, {
input, input,
allowedKeys: tokenKeys.getKeys(), allowedKeys: tokenKeys.getKeys(),
}), }),
@ -45,10 +48,10 @@ class DropdownHint extends gl.FilteredSearchDropdown {
}); });
if (searchTerms.length > 0) { if (searchTerms.length > 0) {
gl.FilteredSearchVisualTokens.addSearchVisualToken(searchTerms.join(' ')); FilteredSearchVisualTokens.addSearchVisualToken(searchTerms.join(' '));
} }
gl.FilteredSearchDropdownManager.addWordToInput(token.replace(':', ''), '', false, this.container); FilteredSearchDropdownManager.addWordToInput(token.replace(':', ''), '', false, this.container);
} }
this.dismissDropdown(); this.dismissDropdown();
this.dispatchInputEvent(); this.dispatchInputEvent();
@ -73,6 +76,3 @@ class DropdownHint extends gl.FilteredSearchDropdown {
this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init(); this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init();
} }
} }
window.gl = window.gl || {};
gl.DropdownHint = DropdownHint;

View File

@ -1,9 +1,10 @@
import Flash from '../flash'; import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax'; import Ajax from '../droplab/plugins/ajax';
import Filter from '../droplab/plugins/filter'; import Filter from '../droplab/plugins/filter';
import './filtered_search_dropdown'; import FilteredSearchDropdown from './filtered_search_dropdown';
import DropdownUtils from './dropdown_utils';
class DropdownNonUser extends gl.FilteredSearchDropdown { export default class DropdownNonUser extends FilteredSearchDropdown {
constructor(options = {}) { constructor(options = {}) {
const { input, endpoint, symbol, preprocessing } = options; const { input, endpoint, symbol, preprocessing } = options;
super(options); super(options);
@ -21,7 +22,7 @@ class DropdownNonUser extends gl.FilteredSearchDropdown {
}, },
}, },
Filter: { Filter: {
filterFunction: gl.DropdownUtils.filterWithSymbol.bind(null, this.symbol, input), filterFunction: DropdownUtils.filterWithSymbol.bind(null, this.symbol, input),
template: 'title', template: 'title',
}, },
}; };
@ -30,7 +31,7 @@ class DropdownNonUser extends gl.FilteredSearchDropdown {
itemClicked(e) { itemClicked(e) {
super.itemClicked(e, (selected) => { super.itemClicked(e, (selected) => {
const title = selected.querySelector('.js-data-value').innerText.trim(); const title = selected.querySelector('.js-data-value').innerText.trim();
return `${this.symbol}${gl.DropdownUtils.getEscapedText(title)}`; return `${this.symbol}${DropdownUtils.getEscapedText(title)}`;
}); });
} }
@ -45,6 +46,3 @@ class DropdownNonUser extends gl.FilteredSearchDropdown {
.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init(); .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
} }
} }
window.gl = window.gl || {};
gl.DropdownNonUser = DropdownNonUser;

View File

@ -1,9 +1,11 @@
import Flash from '../flash'; import Flash from '../flash';
import AjaxFilter from '../droplab/plugins/ajax_filter'; import AjaxFilter from '../droplab/plugins/ajax_filter';
import './filtered_search_dropdown'; import FilteredSearchDropdown from './filtered_search_dropdown';
import { addClassIfElementExists } from '../lib/utils/dom_utils'; import { addClassIfElementExists } from '../lib/utils/dom_utils';
import DropdownUtils from './dropdown_utils';
import FilteredSearchTokenizer from './filtered_search_tokenizer';
class DropdownUser extends gl.FilteredSearchDropdown { export default class DropdownUser extends FilteredSearchDropdown {
constructor(options = {}) { constructor(options = {}) {
const { tokenKeys } = options; const { tokenKeys } = options;
super(options); super(options);
@ -56,8 +58,8 @@ class DropdownUser extends gl.FilteredSearchDropdown {
} }
getSearchInput() { getSearchInput() {
const query = gl.DropdownUtils.getSearchInput(this.input); const query = DropdownUtils.getSearchInput(this.input);
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get()); const { lastToken } = FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get());
let value = lastToken || ''; let value = lastToken || '';
@ -78,6 +80,3 @@ class DropdownUser extends gl.FilteredSearchDropdown {
this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init(); this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init();
} }
} }
window.gl = window.gl || {};
gl.DropdownUser = DropdownUser;

View File

@ -1,7 +1,10 @@
import _ from 'underscore'; import _ from 'underscore';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
import FilteredSearchTokenizer from './filtered_search_tokenizer';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
class DropdownUtils { export default class DropdownUtils {
static getEscapedText(text) { static getEscapedText(text) {
let escapedText = text; let escapedText = text;
const hasSpace = text.indexOf(' ') !== -1; const hasSpace = text.indexOf(' ') !== -1;
@ -24,7 +27,7 @@ class DropdownUtils {
static filterWithSymbol(filterSymbol, input, item) { static filterWithSymbol(filterSymbol, input, item) {
const updatedItem = item; const updatedItem = item;
const searchInput = gl.DropdownUtils.getSearchInput(input); const searchInput = DropdownUtils.getSearchInput(input);
const title = updatedItem.title.toLowerCase(); const title = updatedItem.title.toLowerCase();
let value = searchInput.toLowerCase(); let value = searchInput.toLowerCase();
@ -114,9 +117,9 @@ class DropdownUtils {
static filterHint(config, item) { static filterHint(config, item) {
const { input, allowedKeys } = config; const { input, allowedKeys } = config;
const updatedItem = item; const updatedItem = item;
const searchInput = gl.DropdownUtils.getSearchQuery(input); const searchInput = DropdownUtils.getSearchQuery(input);
const { lastToken, tokens } = const { lastToken, tokens } =
gl.FilteredSearchTokenizer.processTokens(searchInput, allowedKeys); FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
const lastKey = lastToken.key || lastToken || ''; const lastKey = lastToken.key || lastToken || '';
const allowMultiple = item.type === 'array'; const allowMultiple = item.type === 'array';
const itemInExistingTokens = tokens.some(t => t.key === item.hint); const itemInExistingTokens = tokens.some(t => t.key === item.hint);
@ -140,7 +143,7 @@ class DropdownUtils {
const dataValue = selected.getAttribute('data-value'); const dataValue = selected.getAttribute('data-value');
if (dataValue) { if (dataValue) {
gl.FilteredSearchDropdownManager.addWordToInput(filter, dataValue, true); FilteredSearchDropdownManager.addWordToInput(filter, dataValue, true);
} }
// Return boolean based on whether it was set // Return boolean based on whether it was set
@ -190,7 +193,7 @@ class DropdownUtils {
} }
} else if (token.classList.contains('input-token')) { } else if (token.classList.contains('input-token')) {
const { isLastVisualTokenValid } = const { isLastVisualTokenValid } =
gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const input = FilteredSearchContainer.container.querySelector('.filtered-search'); const input = FilteredSearchContainer.container.querySelector('.filtered-search');
const inputValue = input && input.value; const inputValue = input && input.value;
@ -211,7 +214,7 @@ class DropdownUtils {
static getSearchInput(filteredSearchInput) { static getSearchInput(filteredSearchInput) {
const inputValue = filteredSearchInput.value; const inputValue = filteredSearchInput.value;
const { right } = gl.DropdownUtils.getInputSelectionPosition(filteredSearchInput); const { right } = DropdownUtils.getInputSelectionPosition(filteredSearchInput);
return inputValue.slice(0, right); return inputValue.slice(0, right);
} }
@ -252,6 +255,3 @@ class DropdownUtils {
}; };
} }
} }
window.gl = window.gl || {};
gl.DropdownUtils = DropdownUtils;

View File

@ -1,6 +1,9 @@
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger'; const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
class FilteredSearchDropdown { export default class FilteredSearchDropdown {
constructor({ droplab, dropdown, input, filter }) { constructor({ droplab, dropdown, input, filter }) {
this.droplab = droplab; this.droplab = droplab;
this.hookId = input && input.id; this.hookId = input && input.id;
@ -30,11 +33,11 @@ class FilteredSearchDropdown {
const { selected } = e.detail; const { selected } = e.detail;
if (selected.tagName === 'LI' && selected.innerHTML) { if (selected.tagName === 'LI' && selected.innerHTML) {
const dataValueSet = gl.DropdownUtils.setDataValueIfSelected(this.filter, selected); const dataValueSet = DropdownUtils.setDataValueIfSelected(this.filter, selected);
if (!dataValueSet) { if (!dataValueSet) {
const value = getValueFunction(selected); const value = getValueFunction(selected);
gl.FilteredSearchDropdownManager.addWordToInput(this.filter, value, true); FilteredSearchDropdownManager.addWordToInput(this.filter, value, true);
} }
this.resetFilters(); this.resetFilters();
@ -117,6 +120,3 @@ class FilteredSearchDropdown {
} }
} }
} }
window.gl = window.gl || {};
gl.FilteredSearchDropdown = FilteredSearchDropdown;

View File

@ -1,13 +1,20 @@
import _ from 'underscore'; import _ from 'underscore';
import DropLab from '~/droplab/drop_lab'; import DropLab from '~/droplab/drop_lab';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
import FilteredSearchTokenKeys from './filtered_search_token_keys';
import DropdownUtils from './dropdown_utils';
import DropdownHint from './dropdown_hint';
import DropdownEmoji from './dropdown_emoji';
import DropdownNonUser from './dropdown_non_user';
import DropdownUser from './dropdown_user';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
class FilteredSearchDropdownManager { export default class FilteredSearchDropdownManager {
constructor(baseEndpoint = '', tokenizer, page, isGroup, filteredSearchTokenKeys) { constructor(baseEndpoint = '', tokenizer, page, isGroup, filteredSearchTokenKeys) {
this.container = FilteredSearchContainer.container; this.container = FilteredSearchContainer.container;
this.baseEndpoint = baseEndpoint.replace(/\/$/, ''); this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
this.tokenizer = tokenizer; this.tokenizer = tokenizer;
this.filteredSearchTokenKeys = filteredSearchTokenKeys; this.filteredSearchTokenKeys = filteredSearchTokenKeys || FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search'); this.filteredSearchInput = this.container.querySelector('.filtered-search');
this.page = page; this.page = page;
@ -33,24 +40,24 @@ class FilteredSearchDropdownManager {
const allowedMappings = { const allowedMappings = {
hint: { hint: {
reference: null, reference: null,
gl: 'DropdownHint', gl: DropdownHint,
element: this.container.querySelector('#js-dropdown-hint'), element: this.container.querySelector('#js-dropdown-hint'),
}, },
}; };
const availableMappings = { const availableMappings = {
author: { author: {
reference: null, reference: null,
gl: 'DropdownUser', gl: DropdownUser,
element: this.container.querySelector('#js-dropdown-author'), element: this.container.querySelector('#js-dropdown-author'),
}, },
assignee: { assignee: {
reference: null, reference: null,
gl: 'DropdownUser', gl: DropdownUser,
element: this.container.querySelector('#js-dropdown-assignee'), element: this.container.querySelector('#js-dropdown-assignee'),
}, },
milestone: { milestone: {
reference: null, reference: null,
gl: 'DropdownNonUser', gl: DropdownNonUser,
extraArguments: { extraArguments: {
endpoint: `${this.baseEndpoint}/milestones.json`, endpoint: `${this.baseEndpoint}/milestones.json`,
symbol: '%', symbol: '%',
@ -59,17 +66,17 @@ class FilteredSearchDropdownManager {
}, },
label: { label: {
reference: null, reference: null,
gl: 'DropdownNonUser', gl: DropdownNonUser,
extraArguments: { extraArguments: {
endpoint: `${this.baseEndpoint}/labels.json`, endpoint: `${this.baseEndpoint}/labels.json`,
symbol: '~', symbol: '~',
preprocessing: gl.DropdownUtils.duplicateLabelPreprocessing, preprocessing: DropdownUtils.duplicateLabelPreprocessing,
}, },
element: this.container.querySelector('#js-dropdown-label'), element: this.container.querySelector('#js-dropdown-label'),
}, },
'my-reaction': { 'my-reaction': {
reference: null, reference: null,
gl: 'DropdownEmoji', gl: DropdownEmoji,
element: this.container.querySelector('#js-dropdown-my-reaction'), element: this.container.querySelector('#js-dropdown-my-reaction'),
}, },
}; };
@ -86,11 +93,11 @@ class FilteredSearchDropdownManager {
static addWordToInput(tokenName, tokenValue = '', clicked = false) { static addWordToInput(tokenName, tokenValue = '', clicked = false) {
const input = FilteredSearchContainer.container.querySelector('.filtered-search'); const input = FilteredSearchContainer.container.querySelector('.filtered-search');
gl.FilteredSearchVisualTokens.addFilterVisualToken(tokenName, tokenValue); FilteredSearchVisualTokens.addFilterVisualToken(tokenName, tokenValue);
input.value = ''; input.value = '';
if (clicked) { if (clicked) {
gl.FilteredSearchVisualTokens.moveInputToTheRight(); FilteredSearchVisualTokens.moveInputToTheRight();
} }
} }
@ -131,9 +138,9 @@ class FilteredSearchDropdownManager {
const extraArguments = mappingKey.extraArguments || {}; const extraArguments = mappingKey.extraArguments || {};
const glArguments = Object.assign({}, defaultArguments, extraArguments); const glArguments = Object.assign({}, defaultArguments, extraArguments);
// Passing glArguments to `new gl[glClass](<arguments>)` // Passing glArguments to `new glClass(<arguments>)`
mappingKey.reference = mappingKey.reference =
new (Function.prototype.bind.apply(gl[glClass], [null, glArguments]))(); new (Function.prototype.bind.apply(glClass, [null, glArguments]))();
} }
if (firstLoad) { if (firstLoad) {
@ -171,7 +178,7 @@ class FilteredSearchDropdownManager {
} }
setDropdown() { setDropdown() {
const query = gl.DropdownUtils.getSearchQuery(true); const query = DropdownUtils.getSearchQuery(true);
const { lastToken, searchToken } = const { lastToken, searchToken } =
this.tokenizer.processTokens(query, this.filteredSearchTokenKeys.getKeys()); this.tokenizer.processTokens(query, this.filteredSearchTokenKeys.getKeys());
@ -216,6 +223,3 @@ class FilteredSearchDropdownManager {
this.droplab.destroy(); this.droplab.destroy();
} }
} }
window.gl = window.gl || {};
gl.FilteredSearchDropdownManager = FilteredSearchDropdownManager;

View File

@ -1,15 +1,23 @@
import _ from 'underscore'; import _ from 'underscore';
import {
getParameterByName,
getUrlParamsArray,
} from '~/lib/utils/common_utils';
import { visitUrl } from '../lib/utils/url_utility'; import { visitUrl } from '../lib/utils/url_utility';
import Flash from '../flash'; import Flash from '../flash';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
import RecentSearchesRoot from './recent_searches_root';
import FilteredSearchTokenKeys from './filtered_search_token_keys'; import FilteredSearchTokenKeys from './filtered_search_token_keys';
import RecentSearchesRoot from './recent_searches_root';
import RecentSearchesStore from './stores/recent_searches_store'; import RecentSearchesStore from './stores/recent_searches_store';
import RecentSearchesService from './services/recent_searches_service'; import RecentSearchesService from './services/recent_searches_service';
import eventHub from './event_hub'; import eventHub from './event_hub';
import { addClassIfElementExists } from '../lib/utils/dom_utils'; import { addClassIfElementExists } from '../lib/utils/dom_utils';
import FilteredSearchTokenizer from './filtered_search_tokenizer';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
import FilteredSearchVisualTokens from './filtered_search_visual_tokens';
import DropdownUtils from './dropdown_utils';
class FilteredSearchManager { export default class FilteredSearchManager {
constructor({ constructor({
page, page,
filteredSearchTokenKeys = FilteredSearchTokenKeys, filteredSearchTokenKeys = FilteredSearchTokenKeys,
@ -66,8 +74,8 @@ class FilteredSearchManager {
}); });
if (this.filteredSearchInput) { if (this.filteredSearchInput) {
this.tokenizer = gl.FilteredSearchTokenizer; this.tokenizer = FilteredSearchTokenizer;
this.dropdownManager = new gl.FilteredSearchDropdownManager( this.dropdownManager = new FilteredSearchDropdownManager(
this.filteredSearchInput.getAttribute('data-base-endpoint') || '', this.filteredSearchInput.getAttribute('data-base-endpoint') || '',
this.tokenizer, this.tokenizer,
this.page, this.page,
@ -85,7 +93,6 @@ class FilteredSearchManager {
this.bindEvents(); this.bindEvents();
this.loadSearchParamsFromURL(); this.loadSearchParamsFromURL();
this.dropdownManager.setDropdown(); this.dropdownManager.setDropdown();
this.cleanupWrapper = this.cleanup.bind(this); this.cleanupWrapper = this.cleanup.bind(this);
document.addEventListener('beforeunload', this.cleanupWrapper); document.addEventListener('beforeunload', this.cleanupWrapper);
} }
@ -197,8 +204,8 @@ class FilteredSearchManager {
// 8 = Backspace Key // 8 = Backspace Key
// 46 = Delete Key // 46 = Delete Key
if (e.keyCode === 8 || e.keyCode === 46) { if (e.keyCode === 8 || e.keyCode === 46) {
const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); const { lastVisualToken } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { tokenName, tokenValue } = gl.DropdownUtils.getVisualTokenValues(lastVisualToken); const { tokenName, tokenValue } = DropdownUtils.getVisualTokenValues(lastVisualToken);
const canEdit = tokenName && this.canEdit && this.canEdit(tokenName, tokenValue); const canEdit = tokenName && this.canEdit && this.canEdit(tokenName, tokenValue);
if (this.filteredSearchInput.value === '' && lastVisualToken && canEdit) { if (this.filteredSearchInput.value === '' && lastVisualToken && canEdit) {
@ -206,8 +213,8 @@ class FilteredSearchManager {
if (backspaceCount === 2) { if (backspaceCount === 2) {
backspaceCount = 0; backspaceCount = 0;
this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial(); this.filteredSearchInput.value = FilteredSearchVisualTokens.getLastTokenPartial();
gl.FilteredSearchVisualTokens.removeLastTokenPartial(); FilteredSearchVisualTokens.removeLastTokenPartial();
} }
} }
@ -275,7 +282,7 @@ class FilteredSearchManager {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
const button = e.target.closest('.selectable'); const button = e.target.closest('.selectable');
gl.FilteredSearchVisualTokens.selectToken(button, true); FilteredSearchVisualTokens.selectToken(button, true);
this.removeSelectedToken(); this.removeSelectedToken();
} }
} }
@ -287,7 +294,7 @@ class FilteredSearchManager {
const isElementTokensContainer = e.target.classList.contains('tokens-container'); const isElementTokensContainer = e.target.classList.contains('tokens-container');
if ((!isElementInFilteredSearch && !isElementInFilterDropdown) || isElementTokensContainer) { if ((!isElementInFilteredSearch && !isElementInFilterDropdown) || isElementTokensContainer) {
gl.FilteredSearchVisualTokens.moveInputToTheRight(); FilteredSearchVisualTokens.moveInputToTheRight();
this.dropdownManager.resetDropdowns(); this.dropdownManager.resetDropdowns();
} }
} }
@ -300,13 +307,13 @@ class FilteredSearchManager {
if (token && canEdit) { if (token && canEdit) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
gl.FilteredSearchVisualTokens.editToken(token); FilteredSearchVisualTokens.editToken(token);
this.tokenChange(); this.tokenChange();
} }
} }
toggleClearSearchButton() { toggleClearSearchButton() {
const query = gl.DropdownUtils.getSearchQuery(); const query = DropdownUtils.getSearchQuery();
const hidden = 'hidden'; const hidden = 'hidden';
const hasHidden = this.clearSearchButton.classList.contains(hidden); const hasHidden = this.clearSearchButton.classList.contains(hidden);
@ -318,7 +325,7 @@ class FilteredSearchManager {
} }
handleInputPlaceholder() { handleInputPlaceholder() {
const query = gl.DropdownUtils.getSearchQuery(); const query = DropdownUtils.getSearchQuery();
const placeholder = 'Search or filter results...'; const placeholder = 'Search or filter results...';
const currentPlaceholder = this.filteredSearchInput.placeholder; const currentPlaceholder = this.filteredSearchInput.placeholder;
@ -338,7 +345,7 @@ class FilteredSearchManager {
} }
removeSelectedToken() { removeSelectedToken() {
gl.FilteredSearchVisualTokens.removeSelectedToken(); FilteredSearchVisualTokens.removeSelectedToken();
this.handleInputPlaceholder(); this.handleInputPlaceholder();
this.toggleClearSearchButton(); this.toggleClearSearchButton();
this.dropdownManager.updateCurrentDropdownOffset(); this.dropdownManager.updateCurrentDropdownOffset();
@ -358,7 +365,7 @@ class FilteredSearchManager {
let canClearToken = t.classList.contains('js-visual-token'); let canClearToken = t.classList.contains('js-visual-token');
if (canClearToken) { if (canClearToken) {
const { tokenName, tokenValue } = gl.DropdownUtils.getVisualTokenValues(t); const { tokenName, tokenValue } = DropdownUtils.getVisualTokenValues(t);
canClearToken = this.canEdit && this.canEdit(tokenName, tokenValue); canClearToken = this.canEdit && this.canEdit(tokenName, tokenValue);
} }
@ -386,12 +393,12 @@ class FilteredSearchManager {
const { tokens, searchToken } const { tokens, searchToken }
= this.tokenizer.processTokens(input.value, this.filteredSearchTokenKeys.getKeys()); = this.tokenizer.processTokens(input.value, this.filteredSearchTokenKeys.getKeys());
const { isLastVisualTokenValid } const { isLastVisualTokenValid }
= gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (isLastVisualTokenValid) { if (isLastVisualTokenValid) {
tokens.forEach((t) => { tokens.forEach((t) => {
input.value = input.value.replace(`${t.key}:${t.symbol}${t.value}`, ''); input.value = input.value.replace(`${t.key}:${t.symbol}${t.value}`, '');
gl.FilteredSearchVisualTokens.addFilterVisualToken(t.key, `${t.symbol}${t.value}`); FilteredSearchVisualTokens.addFilterVisualToken(t.key, `${t.symbol}${t.value}`);
}); });
const fragments = searchToken.split(':'); const fragments = searchToken.split(':');
@ -404,10 +411,10 @@ class FilteredSearchManager {
const searchTerms = inputValues.join(' '); const searchTerms = inputValues.join(' ');
input.value = input.value.replace(searchTerms, ''); input.value = input.value.replace(searchTerms, '');
gl.FilteredSearchVisualTokens.addSearchVisualToken(searchTerms); FilteredSearchVisualTokens.addSearchVisualToken(searchTerms);
} }
gl.FilteredSearchVisualTokens.addFilterVisualToken(tokenKey); FilteredSearchVisualTokens.addFilterVisualToken(tokenKey);
input.value = input.value.replace(`${tokenKey}:`, ''); input.value = input.value.replace(`${tokenKey}:`, '');
} }
} else { } else {
@ -415,7 +422,7 @@ class FilteredSearchManager {
const valueCompletedRegex = /([~%@]{0,1}".+")|([~%@]{0,1}'.+')|^((?![~%@]')(?![~%@]")(?!')(?!")).*/g; const valueCompletedRegex = /([~%@]{0,1}".+")|([~%@]{0,1}'.+')|^((?![~%@]')(?![~%@]")(?!')(?!")).*/g;
if (searchToken.match(valueCompletedRegex) && input.value[input.value.length - 1] === ' ') { if (searchToken.match(valueCompletedRegex) && input.value[input.value.length - 1] === ' ') {
gl.FilteredSearchVisualTokens.addFilterVisualToken(searchToken); FilteredSearchVisualTokens.addFilterVisualToken(searchToken);
// Trim the last space as seen in the if statement above // Trim the last space as seen in the if statement above
input.value = input.value.replace(searchToken, '').trim(); input.value = input.value.replace(searchToken, '').trim();
@ -431,7 +438,7 @@ class FilteredSearchManager {
saveCurrentSearchQuery() { saveCurrentSearchQuery() {
// Don't save before we have fetched the already saved searches // Don't save before we have fetched the already saved searches
this.fetchingRecentSearchesPromise.then(() => { this.fetchingRecentSearchesPromise.then(() => {
const searchQuery = gl.DropdownUtils.getSearchQuery(); const searchQuery = DropdownUtils.getSearchQuery();
if (searchQuery.length > 0) { if (searchQuery.length > 0) {
const resultantSearches = this.recentSearchesStore.addRecentSearch(searchQuery); const resultantSearches = this.recentSearchesStore.addRecentSearch(searchQuery);
this.recentSearchesService.save(resultantSearches); this.recentSearchesService.save(resultantSearches);
@ -447,7 +454,7 @@ class FilteredSearchManager {
} }
loadSearchParamsFromURL() { loadSearchParamsFromURL() {
const urlParams = gl.utils.getUrlParamsArray(); const urlParams = getUrlParamsArray();
const params = this.getAllParams(urlParams); const params = this.getAllParams(urlParams);
const usernameParams = this.getUsernameParams(); const usernameParams = this.getUsernameParams();
let hasFilteredSearch = false; let hasFilteredSearch = false;
@ -463,7 +470,7 @@ class FilteredSearchManager {
if (condition) { if (condition) {
hasFilteredSearch = true; hasFilteredSearch = true;
const canEdit = this.canEdit && this.canEdit(condition.tokenKey); const canEdit = this.canEdit && this.canEdit(condition.tokenKey);
gl.FilteredSearchVisualTokens.addFilterVisualToken( FilteredSearchVisualTokens.addFilterVisualToken(
condition.tokenKey, condition.tokenKey,
condition.value, condition.value,
canEdit, canEdit,
@ -492,7 +499,7 @@ class FilteredSearchManager {
hasFilteredSearch = true; hasFilteredSearch = true;
const canEdit = this.canEdit && this.canEdit(sanitizedKey, sanitizedValue); const canEdit = this.canEdit && this.canEdit(sanitizedKey, sanitizedValue);
gl.FilteredSearchVisualTokens.addFilterVisualToken( FilteredSearchVisualTokens.addFilterVisualToken(
sanitizedKey, sanitizedKey,
`${symbol}${quotationsToUse}${sanitizedValue}${quotationsToUse}`, `${symbol}${quotationsToUse}${sanitizedValue}${quotationsToUse}`,
canEdit, canEdit,
@ -503,7 +510,7 @@ class FilteredSearchManager {
hasFilteredSearch = true; hasFilteredSearch = true;
const tokenName = 'assignee'; const tokenName = 'assignee';
const canEdit = this.canEdit && this.canEdit(tokenName); const canEdit = this.canEdit && this.canEdit(tokenName);
gl.FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, canEdit); FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, canEdit);
} }
} else if (!match && keyParam === 'author_id') { } else if (!match && keyParam === 'author_id') {
const id = parseInt(value, 10); const id = parseInt(value, 10);
@ -511,7 +518,7 @@ class FilteredSearchManager {
hasFilteredSearch = true; hasFilteredSearch = true;
const tokenName = 'author'; const tokenName = 'author';
const canEdit = this.canEdit && this.canEdit(tokenName); const canEdit = this.canEdit && this.canEdit(tokenName);
gl.FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, canEdit); FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, canEdit);
} }
} else if (!match && keyParam === 'search') { } else if (!match && keyParam === 'search') {
hasFilteredSearch = true; hasFilteredSearch = true;
@ -543,13 +550,13 @@ class FilteredSearchManager {
search(state = null) { search(state = null) {
const paths = []; const paths = [];
const searchQuery = gl.DropdownUtils.getSearchQuery(); const searchQuery = DropdownUtils.getSearchQuery();
this.saveCurrentSearchQuery(); this.saveCurrentSearchQuery();
const { tokens, searchToken } const { tokens, searchToken }
= this.tokenizer.processTokens(searchQuery, this.filteredSearchTokenKeys.getKeys()); = this.tokenizer.processTokens(searchQuery, this.filteredSearchTokenKeys.getKeys());
const currentState = state || gl.utils.getParameterByName('state') || 'opened'; const currentState = state || getParameterByName('state') || 'opened';
paths.push(`state=${currentState}`); paths.push(`state=${currentState}`);
tokens.forEach((token) => { tokens.forEach((token) => {
@ -628,6 +635,3 @@ class FilteredSearchManager {
return true; return true;
} }
} }
window.gl = window.gl || {};
gl.FilteredSearchManager = FilteredSearchManager;

View File

@ -1,6 +1,6 @@
import './filtered_search_token_keys'; import './filtered_search_token_keys';
class FilteredSearchTokenizer { export default class FilteredSearchTokenizer {
static processTokens(input, allowedKeys) { static processTokens(input, allowedKeys) {
// Regex extracts `(token):(symbol)(value)` // Regex extracts `(token):(symbol)(value)`
// Values that start with a double quote must end in a double quote (same for single) // Values that start with a double quote must end in a double quote (same for single)
@ -50,6 +50,3 @@ class FilteredSearchTokenizer {
}; };
} }
} }
window.gl = window.gl || {};
gl.FilteredSearchTokenizer = FilteredSearchTokenizer;

View File

@ -3,8 +3,9 @@ import AjaxCache from '../lib/utils/ajax_cache';
import Flash from '../flash'; import Flash from '../flash';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
import UsersCache from '../lib/utils/users_cache'; import UsersCache from '../lib/utils/users_cache';
import DropdownUtils from './dropdown_utils';
class FilteredSearchVisualTokens { export default class FilteredSearchVisualTokens {
static getLastVisualTokenBeforeInput() { static getLastVisualTokenBeforeInput() {
const inputLi = FilteredSearchContainer.container.querySelector('.input-token'); const inputLi = FilteredSearchContainer.container.querySelector('.input-token');
const lastVisualToken = inputLi && inputLi.previousElementSibling; const lastVisualToken = inputLi && inputLi.previousElementSibling;
@ -74,7 +75,7 @@ class FilteredSearchVisualTokens {
let processed = labels; let processed = labels;
if (!labels.preprocessed) { if (!labels.preprocessed) {
processed = gl.DropdownUtils.duplicateLabelPreprocessing(labels); processed = DropdownUtils.duplicateLabelPreprocessing(labels);
AjaxCache.override(labelsEndpoint, processed); AjaxCache.override(labelsEndpoint, processed);
processed.preprocessed = true; processed.preprocessed = true;
} }
@ -90,7 +91,7 @@ class FilteredSearchVisualTokens {
return AjaxCache.retrieve(labelsEndpoint) return AjaxCache.retrieve(labelsEndpoint)
.then(FilteredSearchVisualTokens.preprocessLabel.bind(null, labelsEndpoint)) .then(FilteredSearchVisualTokens.preprocessLabel.bind(null, labelsEndpoint))
.then((labels) => { .then((labels) => {
const matchingLabel = (labels || []).find(label => `~${gl.DropdownUtils.getEscapedText(label.title)}` === tokenValue); const matchingLabel = (labels || []).find(label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue);
if (!matchingLabel) { if (!matchingLabel) {
return; return;
@ -259,11 +260,11 @@ class FilteredSearchVisualTokens {
static tokenizeInput() { static tokenizeInput() {
const input = FilteredSearchContainer.container.querySelector('.filtered-search'); const input = FilteredSearchContainer.container.querySelector('.filtered-search');
const { isLastVisualTokenValid } = const { isLastVisualTokenValid } =
gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (input.value) { if (input.value) {
if (isLastVisualTokenValid) { if (isLastVisualTokenValid) {
gl.FilteredSearchVisualTokens.addSearchVisualToken(input.value); FilteredSearchVisualTokens.addSearchVisualToken(input.value);
} else { } else {
FilteredSearchVisualTokens.addValueToPreviousVisualTokenElement(input.value); FilteredSearchVisualTokens.addValueToPreviousVisualTokenElement(input.value);
} }
@ -324,12 +325,12 @@ class FilteredSearchVisualTokens {
if (!tokenContainer.lastElementChild.isEqualNode(inputLi)) { if (!tokenContainer.lastElementChild.isEqualNode(inputLi)) {
const { isLastVisualTokenValid } = const { isLastVisualTokenValid } =
gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (!isLastVisualTokenValid) { if (!isLastVisualTokenValid) {
const lastPartial = gl.FilteredSearchVisualTokens.getLastTokenPartial(); const lastPartial = FilteredSearchVisualTokens.getLastTokenPartial();
gl.FilteredSearchVisualTokens.removeLastTokenPartial(); FilteredSearchVisualTokens.removeLastTokenPartial();
gl.FilteredSearchVisualTokens.addSearchVisualToken(lastPartial); FilteredSearchVisualTokens.addSearchVisualToken(lastPartial);
} }
tokenContainer.removeChild(inputLi); tokenContainer.removeChild(inputLi);
@ -337,6 +338,3 @@ class FilteredSearchVisualTokens {
} }
} }
} }
window.gl = window.gl || {};
gl.FilteredSearchVisualTokens = FilteredSearchVisualTokens;

View File

@ -485,7 +485,7 @@ GitLabDropdown = (function() {
$target = $(e.target); $target = $(e.target);
if ($target && !$target.hasClass('dropdown-menu-close') && if ($target && !$target.hasClass('dropdown-menu-close') &&
!$target.hasClass('dropdown-menu-close-icon') && !$target.hasClass('dropdown-menu-close-icon') &&
!$target.data('is-link')) { !$target.data('isLink')) {
e.stopPropagation(); e.stopPropagation();
return false; return false;
} else { } else {

View File

@ -12,7 +12,7 @@ export default class GLForm {
this.destroy(); this.destroy();
// Setup the form // Setup the form
this.setupForm(); this.setupForm();
this.form.data('gl-form', this); this.form.data('glForm', this);
} }
destroy() { destroy() {
@ -21,7 +21,7 @@ export default class GLForm {
if (this.autoComplete) { if (this.autoComplete) {
this.autoComplete.destroy(); this.autoComplete.destroy();
} }
this.form.data('gl-form', null); this.form.data('glForm', null);
} }
setupForm() { setupForm() {

View File

@ -11,7 +11,7 @@ export default class GpgBadges {
badges.html('<i class="fa fa-spinner fa-spin"></i>'); badges.html('<i class="fa fa-spinner fa-spin"></i>');
const params = parseQueryStringIntoObject(form.serialize()); const params = parseQueryStringIntoObject(form.serialize());
return axios.get(form.data('signatures-path'), { params }) return axios.get(form.data('signaturesPath'), { params })
.then(({ data }) => { .then(({ data }) => {
data.signatures.forEach((signature) => { data.signatures.forEach((signature) => {
badges.filter(`[data-commit-sha="${signature.commit_sha}"]`).replaceWith(signature.html); badges.filter(`[data-commit-sha="${signature.commit_sha}"]`).replaceWith(signature.html);

View File

@ -1,4 +0,0 @@
import Chart from 'vendor/Chart';
// export to global scope
window.Chart = Chart;

View File

@ -7,8 +7,8 @@ export default function groupsSelect() {
window.GROUP_SELECT_PER_PAGE = 20; window.GROUP_SELECT_PER_PAGE = 20;
$('.ajax-groups-select').each(function setAjaxGroupsSelect2() { $('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
const $select = $(this); const $select = $(this);
const allAvailable = $select.data('all-available'); const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skip-groups') || []; const skipGroups = $select.data('skipGroups') || [];
$select.select2({ $select.select2({
placeholder: 'Search for a group', placeholder: 'Search for a group',
multiple: $select.hasClass('multiselect'), multiple: $select.hasClass('multiselect'),

View File

@ -1,6 +1,8 @@
// We will render the icons list here // We will render the icons list here
if ($('#user-content-gitlab-icons').length > 0) { export default () => {
const $iconsHeader = $('#user-content-gitlab-icons'); if ($('#user-content-gitlab-icons').length > 0) {
const $iconsList = $('<div id="iconsList">ICONS</div>'); const $iconsHeader = $('#user-content-gitlab-icons');
$($iconsList).insertAfter($iconsHeader.parent()); const $iconsList = $('<div id="iconsList">ICONS</div>');
} $($iconsList).insertAfter($iconsHeader.parent());
}
};

View File

@ -1,12 +1,13 @@
document.addEventListener('DOMContentLoaded', () => { export default () => {
const modal = $('#modal_merge_info').modal({ const modal = $('#modal_merge_info');
modal: true,
show: false, if (modal) {
}); modal.modal({
$('.how_to_merge_link').on('click', () => { modal: true,
modal.show(); show: false,
}); });
$('.modal-header .close').on('click', () => {
modal.hide(); $('.how_to_merge_link').on('click', modal.show);
}); $('.modal-header .close').on('click', modal.hide);
}); }
};

View File

@ -6,6 +6,11 @@ monacoContext.require.config({
}, },
}); });
// ignore CDN config and use local assets path for service worker which cannot be cross-domain
const relativeRootPath = (gon && gon.relative_url_root) || '';
const monacoPath = `${relativeRootPath}/assets/webpack/monaco-editor/vs`;
window.MonacoEnvironment = { getWorkerUrl: () => `${monacoPath}/base/worker/workerMain.js` };
// eslint-disable-next-line no-underscore-dangle // eslint-disable-next-line no-underscore-dangle
window.__monaco_context__ = monacoContext; window.__monaco_context__ = monacoContext;
export default monacoContext.require; export default monacoContext.require;

View File

@ -6,8 +6,8 @@ export default class IntegrationSettingsForm {
this.$form = $(formSelector); this.$form = $(formSelector);
// Form Metadata // Form Metadata
this.canTestService = this.$form.data('can-test'); this.canTestService = this.$form.data('canTest');
this.testEndPoint = this.$form.data('test-url'); this.testEndPoint = this.$form.data('testUrl');
// Form Child Elements // Form Child Elements
this.$serviceToggle = this.$form.find('#service_active'); this.$serviceToggle = this.$form.find('#service_active');

View File

@ -78,6 +78,7 @@
taskListUpdateSuccess(data) { taskListUpdateSuccess(data) {
try { try {
this.checkForSpam(data); this.checkForSpam(data);
this.closeRecaptcha();
} catch (error) { } catch (error) {
if (error && error.name === 'SpamError') this.openRecaptcha(); if (error && error.name === 'SpamError') this.openRecaptcha();
} }

View File

@ -1,6 +1,6 @@
export default function issueStatusSelect() { export default function issueStatusSelect() {
$('.js-issue-status').each((i, el) => { $('.js-issue-status').each((i, el) => {
const fieldName = $(el).data('field-name'); const fieldName = $(el).data('fieldName');
return $(el).glDropdown({ return $(el).glDropdown({
selectable: true, selectable: true,
fieldName, fieldName,

View File

@ -3,7 +3,7 @@ import JobMediator from './job_details_mediator';
import jobHeader from './components/header.vue'; import jobHeader from './components/header.vue';
import detailsBlock from './components/sidebar_details_block.vue'; import detailsBlock from './components/sidebar_details_block.vue';
document.addEventListener('DOMContentLoaded', () => { export default () => {
const dataset = document.getElementById('js-job-details-vue').dataset; const dataset = document.getElementById('js-job-details-vue').dataset;
const mediator = new JobMediator({ endpoint: dataset.endpoint }); const mediator = new JobMediator({ endpoint: dataset.endpoint });
@ -55,4 +55,4 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
}, },
}); });
}); };

View File

@ -25,19 +25,19 @@ export default class LabelsSelect {
$dropdown = $(dropdown); $dropdown = $(dropdown);
$dropdownContainer = $dropdown.closest('.labels-filter'); $dropdownContainer = $dropdown.closest('.labels-filter');
$toggleText = $dropdown.find('.dropdown-toggle-text'); $toggleText = $dropdown.find('.dropdown-toggle-text');
namespacePath = $dropdown.data('namespace-path'); namespacePath = $dropdown.data('namespacePath');
projectPath = $dropdown.data('project-path'); projectPath = $dropdown.data('projectPath');
labelUrl = $dropdown.data('labels'); labelUrl = $dropdown.data('labels');
issueUpdateURL = $dropdown.data('issueUpdate'); issueUpdateURL = $dropdown.data('issueUpdate');
selectedLabel = $dropdown.data('selected'); selectedLabel = $dropdown.data('selected');
if ((selectedLabel != null) && !$dropdown.hasClass('js-multiselect')) { if ((selectedLabel != null) && !$dropdown.hasClass('js-multiselect')) {
selectedLabel = selectedLabel.split(','); selectedLabel = selectedLabel.split(',');
} }
showNo = $dropdown.data('show-no'); showNo = $dropdown.data('showNo');
showAny = $dropdown.data('show-any'); showAny = $dropdown.data('showAny');
showMenuAbove = $dropdown.data('showMenuAbove'); showMenuAbove = $dropdown.data('showMenuAbove');
defaultLabel = $dropdown.data('default-label'); defaultLabel = $dropdown.data('defaultLabel');
abilityName = $dropdown.data('ability-name'); abilityName = $dropdown.data('abilityName');
$selectbox = $dropdown.closest('.selectbox'); $selectbox = $dropdown.closest('.selectbox');
$block = $selectbox.closest('.block'); $block = $selectbox.closest('.block');
$form = $dropdown.closest('form, .js-issuable-update'); $form = $dropdown.closest('form, .js-issuable-update');
@ -45,11 +45,11 @@ export default class LabelsSelect {
$sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip'); $sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip');
$value = $block.find('.value'); $value = $block.find('.value');
$loading = $block.find('.block-loading').fadeOut(); $loading = $block.find('.block-loading').fadeOut();
fieldName = $dropdown.data('field-name'); fieldName = $dropdown.data('fieldName');
useId = $dropdown.is('.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown'); useId = $dropdown.is('.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown');
propertyName = useId ? 'id' : 'title'; propertyName = useId ? 'id' : 'title';
initialSelected = $selectbox initialSelected = $selectbox
.find('input[name="' + $dropdown.data('field-name') + '"]') .find('input[name="' + $dropdown.data('fieldName') + '"]')
.map(function () { .map(function () {
return this.value; return this.value;
}).get(); }).get();
@ -268,7 +268,7 @@ export default class LabelsSelect {
return defaultLabel; return defaultLabel;
} }
}, },
fieldName: $dropdown.data('field-name'), fieldName: $dropdown.data('fieldName'),
id: function(label) { id: function(label) {
if (label.id <= 0) return label.title; if (label.id <= 0) return label.title;

View File

@ -4,7 +4,7 @@ import initFlyOutNav from './fly_out_nav';
function hideEndFade($scrollingTabs) { function hideEndFade($scrollingTabs) {
$scrollingTabs.each(function scrollTabsLoop() { $scrollingTabs.each(function scrollTabsLoop() {
const $this = $(this); const $this = $(this);
$this.siblings('.fade-right').toggleClass('scrolling', $this.width() < $this.prop('scrollWidth')); $this.siblings('.fade-right').toggleClass('scrolling', Math.round($this.width()) < $this.prop('scrollWidth'));
}); });
} }

View File

@ -138,7 +138,7 @@ textUtils.init = function(form) {
return $('.js-md', form).off('click').on('click', function() { return $('.js-md', form).off('click').on('click', function() {
var $this; var $this;
$this = $(this); $this = $(this);
return self.updateText($this.closest('.md-area').find('textarea'), $this.data('md-tag'), $this.data('md-block'), !$this.data('md-prepend')); return self.updateText($this.closest('.md-area').find('textarea'), $this.data('mdTag'), $this.data('mdBlock'), !$this.data('mdPrepend'));
}); });
}; };

View File

@ -83,7 +83,7 @@ LineHighlighter.prototype.clickHandler = function(event) {
var current, lineNumber, range; var current, lineNumber, range;
event.preventDefault(); event.preventDefault();
this.clearHighlight(); this.clearHighlight();
lineNumber = $(event.target).closest('a').data('line-number'); lineNumber = $(event.target).closest('a').data('lineNumber');
current = this.hashToRange(this._hash); current = this.hashToRange(this._hash);
if (!(current[0] && event.shiftKey)) { if (!(current[0] && event.shiftKey)) {
// If there's no current selection, or there is but Shift wasn't held, // If there's no current selection, or there is but Shift wasn't held,

View File

@ -61,7 +61,7 @@ gl.lazyLoader = new LazyLoader({
observerNode: '#content-body', observerNode: '#content-body',
}); });
$(() => { document.addEventListener('DOMContentLoaded', () => {
const $body = $('body'); const $body = $('body');
const $document = $(document); const $document = $(document);
const $window = $(window); const $window = $(window);
@ -220,7 +220,7 @@ $(() => {
$document.on('click', '.js-confirm-danger', (e) => { $document.on('click', '.js-confirm-danger', (e) => {
const btn = $(e.target); const btn = $(e.target);
const form = btn.closest('form'); const form = btn.closest('form');
const text = btn.data('confirm-danger-message'); const text = btn.data('confirmDangerMessage');
e.preventDefault(); e.preventDefault();
// eslint-disable-next-line no-new // eslint-disable-next-line no-new

View File

@ -19,7 +19,7 @@ export default class Members {
isSelectable(selected, $el) { isSelectable(selected, $el) {
return !$el.hasClass('is-active'); return !$el.hasClass('is-active');
}, },
fieldName: $btn.data('field-name'), fieldName: $btn.data('fieldName'),
id(selected, $el) { id(selected, $el) {
return $el.data('id'); return $el.data('id');
}, },
@ -51,7 +51,7 @@ export default class Members {
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
getMemberListItems($el) { getMemberListItems($el) {
const $memberListItem = $el.is('.member') ? $el : $(`#${$el.data('el-id')}`); const $memberListItem = $el.is('.member') ? $el : $(`#${$el.data('elId')}`);
return { return {
$memberListItem, $memberListItem,

View File

@ -361,7 +361,7 @@ export default class MergeRequestTabs {
} }
diffViewType() { diffViewType() {
return $('.inline-parallel-buttons a.active').data('view-type'); return $('.inline-parallel-buttons a.active').data('viewType');
} }
isDiffAction(action) { isDiffAction(action) {

View File

@ -24,19 +24,19 @@ export default class MilestoneSelect {
$els.each((i, dropdown) => { $els.each((i, dropdown) => {
let collapsedSidebarLabelTemplate, milestoneLinkNoneTemplate, milestoneLinkTemplate, selectedMilestone, selectedMilestoneDefault; let collapsedSidebarLabelTemplate, milestoneLinkNoneTemplate, milestoneLinkTemplate, selectedMilestone, selectedMilestoneDefault;
const $dropdown = $(dropdown); const $dropdown = $(dropdown);
const projectId = $dropdown.data('project-id'); const projectId = $dropdown.data('projectId');
const milestonesUrl = $dropdown.data('milestones'); const milestonesUrl = $dropdown.data('milestones');
const issueUpdateURL = $dropdown.data('issueUpdate'); const issueUpdateURL = $dropdown.data('issueUpdate');
const showNo = $dropdown.data('show-no'); const showNo = $dropdown.data('showNo');
const showAny = $dropdown.data('show-any'); const showAny = $dropdown.data('showAny');
const showMenuAbove = $dropdown.data('showMenuAbove'); const showMenuAbove = $dropdown.data('showMenuAbove');
const showUpcoming = $dropdown.data('show-upcoming'); const showUpcoming = $dropdown.data('showUpcoming');
const showStarted = $dropdown.data('show-started'); const showStarted = $dropdown.data('showStarted');
const useId = $dropdown.data('use-id'); const useId = $dropdown.data('useId');
const defaultLabel = $dropdown.data('default-label'); const defaultLabel = $dropdown.data('defaultLabel');
const defaultNo = $dropdown.data('default-no'); const defaultNo = $dropdown.data('defaultNo');
const issuableId = $dropdown.data('issuable-id'); const issuableId = $dropdown.data('issuableId');
const abilityName = $dropdown.data('ability-name'); const abilityName = $dropdown.data('abilityName');
const $selectBox = $dropdown.closest('.selectbox'); const $selectBox = $dropdown.closest('.selectbox');
const $block = $selectBox.closest('.block'); const $block = $selectBox.closest('.block');
const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon'); const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
@ -114,7 +114,7 @@ export default class MilestoneSelect {
} }
}, },
defaultLabel: defaultLabel, defaultLabel: defaultLabel,
fieldName: $dropdown.data('field-name'), fieldName: $dropdown.data('fieldName'),
text: milestone => _.escape(milestone.title), text: milestone => _.escape(milestone.title),
id: (milestone) => { id: (milestone) => {
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) { if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
@ -166,7 +166,7 @@ export default class MilestoneSelect {
} }
if (boardsStore) { if (boardsStore) {
boardsStore[$dropdown.data('field-name')] = selected.name; boardsStore[$dropdown.data('fieldName')] = selected.name;
e.preventDefault(); e.preventDefault();
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) { } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
return Issuable.filterResults($dropdown.closest('form')); return Issuable.filterResults($dropdown.closest('form'));

View File

@ -219,7 +219,7 @@ export default class Notes {
} }
editNote = $textarea.closest('.note'); editNote = $textarea.closest('.note');
if (editNote.length) { if (editNote.length) {
originalText = $textarea.closest('form').data('original-note'); originalText = $textarea.closest('form').data('originalNote');
newText = $textarea.val(); newText = $textarea.val();
if (originalText !== newText) { if (originalText !== newText) {
if (!confirm('Are you sure you want to cancel editing this comment?')) { if (!confirm('Are you sure you want to cancel editing this comment?')) {
@ -609,9 +609,9 @@ export default class Notes {
*/ */
addDiscussionNote($form, note, isNewDiffComment) { addDiscussionNote($form, note, isNewDiffComment) {
if ($form.attr('data-resolve-all') != null) { if ($form.attr('data-resolve-all') != null) {
var projectPath = $form.data('project-path'); var projectPath = $form.data('projectPath');
var discussionId = $form.data('discussion-id'); var discussionId = $form.data('discussionId');
var mergeRequestId = $form.data('noteable-iid'); var mergeRequestId = $form.data('noteableIid');
if (ResolveService != null) { if (ResolveService != null) {
ResolveService.toggleResolveForDiscussion(mergeRequestId, discussionId); ResolveService.toggleResolveForDiscussion(mergeRequestId, discussionId);
@ -751,7 +751,7 @@ export default class Notes {
form.removeClass('current-note-edit-form'); form.removeClass('current-note-edit-form');
form.find('.js-finish-edit-warning').hide(); form.find('.js-finish-edit-warning').hide();
// Replace markdown textarea text with original note text. // Replace markdown textarea text with original note text.
return form.find('.js-note-text').val(form.find('form.edit-note').data('original-note')); return form.find('.js-note-text').val(form.find('form.edit-note').data('originalNote'));
} }
/** /**
@ -776,7 +776,7 @@ export default class Notes {
var $note, $notes; var $note, $notes;
$note = $(el); $note = $(el);
$notes = $note.closest('.discussion-notes'); $notes = $note.closest('.discussion-notes');
const discussionId = $('.notes', $notes).data('discussion-id'); const discussionId = $('.notes', $notes).data('discussionId');
if (typeof gl.diffNotesCompileComponents !== 'undefined') { if (typeof gl.diffNotesCompileComponents !== 'undefined') {
if (gl.diffNoteApps[noteElId]) { if (gl.diffNoteApps[noteElId]) {
@ -897,7 +897,7 @@ export default class Notes {
// DiffNote // DiffNote
form.find('#note_position').val(dataHolder.attr('data-position')); form.find('#note_position').val(dataHolder.attr('data-position'));
form.find('.js-note-discard').show().removeClass('js-note-discard').addClass('js-close-discussion-note-form').text(form.find('.js-close-discussion-note-form').data('cancel-text')); form.find('.js-note-discard').show().removeClass('js-note-discard').addClass('js-close-discussion-note-form').text(form.find('.js-close-discussion-note-form').data('cancelText'));
form.find('.js-note-target-close').remove(); form.find('.js-note-target-close').remove();
form.find('.js-note-new-discussion').remove(); form.find('.js-note-new-discussion').remove();
this.setupNoteForm(form); this.setupNoteForm(form);
@ -1037,7 +1037,7 @@ export default class Notes {
removeDiscussionNoteForm(form) { removeDiscussionNoteForm(form) {
var glForm, row; var glForm, row;
row = form.closest('tr'); row = form.closest('tr');
glForm = form.data('gl-form'); glForm = form.data('glForm');
glForm.destroy(); glForm.destroy();
form.find('.js-note-text').data('autosave').reset(); form.find('.js-note-text').data('autosave').reset();
// show the reply button (will only work for replies) // show the reply button (will only work for replies)
@ -1122,8 +1122,8 @@ export default class Notes {
return discardbtn.show(); return discardbtn.show();
} }
} else { } else {
reopentext = reopenbtn.data('original-text'); reopentext = reopenbtn.data('originalText');
closetext = closebtn.data('original-text'); closetext = closebtn.data('originalText');
if (reopenbtn.text() !== reopentext) { if (reopenbtn.text() !== reopentext) {
reopenbtn.text(reopentext); reopenbtn.text(reopentext);
} }
@ -1150,9 +1150,9 @@ export default class Notes {
var $originalContentEl = $note.find('.original-note-content'); var $originalContentEl = $note.find('.original-note-content');
var originalContent = $originalContentEl.text().trim(); var originalContent = $originalContentEl.text().trim();
var postUrl = $originalContentEl.data('post-url'); var postUrl = $originalContentEl.data('postUrl');
var targetId = $originalContentEl.data('target-id'); var targetId = $originalContentEl.data('targetId');
var targetType = $originalContentEl.data('target-type'); var targetType = $originalContentEl.data('targetType');
this.glForm = new GLForm($editForm.find('form'), this.enableGFM); this.glForm = new GLForm($editForm.find('form'), this.enableGFM);
@ -1513,9 +1513,9 @@ export default class Notes {
// If comment intends to resolve discussion, do the same. // If comment intends to resolve discussion, do the same.
if (isDiscussionResolve) { if (isDiscussionResolve) {
$form $form
.attr('data-discussion-id', $submitBtn.data('discussion-id')) .attr('data-discussion-id', $submitBtn.data('discussionId'))
.attr('data-resolve-all', 'true') .attr('data-resolve-all', 'true')
.attr('data-project-path', $submitBtn.data('project-path')); .attr('data-project-path', $submitBtn.data('projectPath'));
} }
// Show final note element on UI // Show final note element on UI
@ -1587,7 +1587,7 @@ export default class Notes {
this.addNoteError($form); this.addNoteError($form);
}); });
return $closeBtn.text($closeBtn.data('original-text')); return $closeBtn.text($closeBtn.data('originalText'));
} }
/** /**
@ -1642,7 +1642,7 @@ export default class Notes {
this.updateNoteError(); this.updateNoteError();
}); });
return $closeBtn.text($closeBtn.data('original-text')); return $closeBtn.text($closeBtn.data('originalText'));
} }
} }

View File

@ -3,11 +3,11 @@ import Flash from './flash';
export default function notificationsDropdown() { export default function notificationsDropdown() {
$(document).on('click', '.update-notification', function updateNotificationCallback(e) { $(document).on('click', '.update-notification', function updateNotificationCallback(e) {
e.preventDefault(); e.preventDefault();
if ($(this).is('.is-active') && $(this).data('notification-level') === 'custom') { if ($(this).is('.is-active') && $(this).data('notificationLevel') === 'custom') {
return; return;
} }
const notificationLevel = $(this).data('notification-level'); const notificationLevel = $(this).data('notificationLevel');
const form = $(this).parents('.notification-form:first'); const form = $(this).parents('.notification-form:first');
form.find('.js-notification-loading').toggleClass('fa-bell fa-spin fa-spinner'); form.find('.js-notification-loading').toggleClass('fa-bell fa-spin fa-spinner');

View File

@ -56,7 +56,7 @@ export default {
}, },
initLoadMore() { initLoadMore() {
$(document).unbind('scroll'); $(document).off('scroll');
$(document).endlessScroll({ $(document).endlessScroll({
bottomPixels: ENDLESS_SCROLL_BOTTOM_PX, bottomPixels: ENDLESS_SCROLL_BOTTOM_PX,
fireDelay: ENDLESS_SCROLL_FIRE_DELAY_MS, fireDelay: ENDLESS_SCROLL_FIRE_DELAY_MS,

View File

@ -15,21 +15,21 @@ export default class AbuseReports {
const $messageCellElement = $(this); const $messageCellElement = $(this);
const reportMessage = $messageCellElement.text(); const reportMessage = $messageCellElement.text();
if (reportMessage.length > MAX_MESSAGE_LENGTH) { if (reportMessage.length > MAX_MESSAGE_LENGTH) {
$messageCellElement.data('original-message', reportMessage); $messageCellElement.data('originalMessage', reportMessage);
$messageCellElement.data('message-truncated', 'true'); $messageCellElement.data('messageTruncated', 'true');
$messageCellElement.text(truncate(reportMessage, MAX_MESSAGE_LENGTH)); $messageCellElement.text(truncate(reportMessage, MAX_MESSAGE_LENGTH));
} }
} }
toggleMessageTruncation() { toggleMessageTruncation() {
const $messageCellElement = $(this); const $messageCellElement = $(this);
const originalMessage = $messageCellElement.data('original-message'); const originalMessage = $messageCellElement.data('originalMessage');
if (!originalMessage) return; if (!originalMessage) return;
if ($messageCellElement.data('message-truncated') === 'true') { if ($messageCellElement.data('messageTruncated') === 'true') {
$messageCellElement.data('message-truncated', 'false'); $messageCellElement.data('messageTruncated', 'false');
$messageCellElement.text(originalMessage); $messageCellElement.text(originalMessage);
} else { } else {
$messageCellElement.data('message-truncated', 'true'); $messageCellElement.data('messageTruncated', 'true');
$messageCellElement.text(`${originalMessage.substr(0, (MAX_MESSAGE_LENGTH - 3))}...`); $messageCellElement.text(`${originalMessage.substr(0, (MAX_MESSAGE_LENGTH - 3))}...`);
} }
} }

View File

@ -16,9 +16,9 @@ export default function adminInit() {
$('input#user_force_random_password').on('change', function randomPasswordClick() { $('input#user_force_random_password').on('change', function randomPasswordClick() {
const $elems = $('#user_password, #user_password_confirmation'); const $elems = $('#user_password, #user_password_confirmation');
if ($(this).attr('checked')) { if ($(this).attr('checked')) {
$elems.val('').attr('disabled', true); $elems.val('').prop('disabled', true);
} else { } else {
$elems.removeAttr('disabled'); $elems.prop('disabled', false);
} }
}); });

View File

@ -14,7 +14,7 @@ export default function initBroadcastMessagesForm() {
$('div.broadcast-message-preview').css('color', previewColor); $('div.broadcast-message-preview').css('color', previewColor);
}); });
const previewPath = $('textarea#broadcast_message_message').data('preview-path'); const previewPath = $('textarea#broadcast_message_message').data('previewPath');
$('textarea#broadcast_message_message').on('input', _.debounce(function onMessageInput() { $('textarea#broadcast_message_message').on('input', _.debounce(function onMessageInput() {
const message = $(this).val(); const message = $(this).val();

View File

@ -1,3 +1,3 @@
import initAdmin from './admin'; import initAdmin from './admin';
export default () => initAdmin(); document.addEventListener('DOMContentLoaded', initAdmin);

View File

@ -1,12 +1,10 @@
import Vue from 'vue'; import Vue from 'vue';
import Translate from '~/vue_shared/translate'; import Translate from '~/vue_shared/translate';
import stopJobsModal from './components/stop_jobs_modal.vue'; import stopJobsModal from './components/stop_jobs_modal.vue';
Vue.use(Translate); Vue.use(Translate);
export default () => { document.addEventListener('DOMContentLoaded', () => {
const stopJobsButton = document.getElementById('stop-jobs-button'); const stopJobsButton = document.getElementById('stop-jobs-button');
if (stopJobsButton) { if (stopJobsButton) {
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
@ -27,4 +25,4 @@ export default () => {
}, },
}); });
} }
}; });

View File

@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteProjectModal from './components/delete_project_modal.vue'; import deleteProjectModal from './components/delete_project_modal.vue';
export default () => { document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate); Vue.use(Translate);
const deleteProjectModalEl = document.getElementById('delete-project-modal'); const deleteProjectModalEl = document.getElementById('delete-project-modal');
@ -34,4 +34,4 @@ export default () => {
deleteModal.projectName = buttonProps.projectName; deleteModal.projectName = buttonProps.projectName;
} }
}); });
}; });

View File

@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteUserModal from './components/delete_user_modal.vue'; import deleteUserModal from './components/delete_user_modal.vue';
export default () => { document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate); Vue.use(Translate);
const deleteUserModalEl = document.getElementById('delete-user-modal'); const deleteUserModalEl = document.getElementById('delete-user-modal');
@ -40,4 +40,4 @@ export default () => {
deleteModal.username = buttonProps.username; deleteModal.username = buttonProps.username;
} }
}); });
}; });

View File

@ -1,3 +1,3 @@
import Activities from '~/activities'; import Activities from '~/activities';
export default () => new Activities(); document.addEventListener('DOMContentLoaded', () => new Activities());

View File

@ -1,5 +1,3 @@
import initGroupsList from '../../../../groups'; import initGroupsList from '~/groups';
export default () => { export default initGroupsList;
initGroupsList();
};

View File

@ -1,7 +1,7 @@
import projectSelect from '~/project_select'; import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters'; import initLegacyFilters from '~/init_legacy_filters';
export default () => { document.addEventListener('DOMContentLoaded', () => {
projectSelect(); projectSelect();
initLegacyFilters(); initLegacyFilters();
}; });

View File

@ -1,7 +1,7 @@
import projectSelect from '~/project_select'; import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters'; import initLegacyFilters from '~/init_legacy_filters';
export default () => { document.addEventListener('DOMContentLoaded', () => {
projectSelect(); projectSelect();
initLegacyFilters(); initLegacyFilters();
}; });

View File

@ -1,7 +1,9 @@
import Milestone from '~/milestone'; import Milestone from '~/milestone';
import Sidebar from '~/right_sidebar'; import Sidebar from '~/right_sidebar';
import MountMilestoneSidebar from '~/sidebar/mount_milestone_sidebar';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new Milestone(); // eslint-disable-line no-new new Milestone(); // eslint-disable-line no-new
new Sidebar(); // eslint-disable-line no-new new Sidebar(); // eslint-disable-line no-new
}; new MountMilestoneSidebar(); // eslint-disable-line no-new
});

View File

@ -1,3 +1,3 @@
import ProjectsList from '~/projects_list'; import ProjectsList from '~/projects_list';
export default () => new ProjectsList(); document.addEventListener('DOMContentLoaded', () => new ProjectsList());

View File

@ -1,3 +1,3 @@
import Todos from './todos'; import Todos from './todos';
export default () => new Todos(); document.addEventListener('DOMContentLoaded', () => new Todos());

View File

@ -2,7 +2,7 @@ import GroupsList from '~/groups_list';
import Landing from '~/landing'; import Landing from '~/landing';
import initGroupsList from '../../../groups'; import initGroupsList from '../../../groups';
export default function () { document.addEventListener('DOMContentLoaded', () => {
new GroupsList(); // eslint-disable-line no-new new GroupsList(); // eslint-disable-line no-new
initGroupsList(); initGroupsList();
const landingElement = document.querySelector('.js-explore-groups-landing'); const landingElement = document.querySelector('.js-explore-groups-landing');
@ -13,4 +13,4 @@ export default function () {
'explore_groups_landing_dismissed', 'explore_groups_landing_dismissed',
); );
exploreGroupsLanding.toggle(); exploreGroupsLanding.toggle();
} });

View File

@ -1,3 +1,3 @@
import ProjectsList from '~/projects_list'; import ProjectsList from '~/projects_list';
export default () => new ProjectsList(); document.addEventListener('DOMContentLoaded', () => new ProjectsList());

View File

@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search'; import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
export default () => { document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({ initFilteredSearch({
page: FILTERED_SEARCH.ISSUES, page: FILTERED_SEARCH.ISSUES,
}); });
projectSelect(); projectSelect();
}; });

View File

@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search'; import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
export default () => { document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({ initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS, page: FILTERED_SEARCH.MERGE_REQUESTS,
}); });
projectSelect(); projectSelect();
}; });

View File

@ -1,3 +1,3 @@
import initForm from '../../../../shared/milestones/form'; import initForm from '../../../../shared/milestones/form';
export default () => initForm(false); document.addEventListener('DOMContentLoaded', () => initForm(false));

View File

@ -1,3 +1,3 @@
import initForm from '../../../../shared/milestones/form'; import initForm from '../../../../shared/milestones/form';
export default () => initForm(false); document.addEventListener('DOMContentLoaded', () => initForm(false));

View File

@ -1,3 +1,3 @@
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show'; import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
export default initMilestonesShow; document.addEventListener('DOMContentLoaded', initMilestonesShow);

View File

@ -5,7 +5,7 @@ import notificationsDropdown from '~/notifications_dropdown';
import NotificationsForm from '~/notifications_form'; import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list'; import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
import initGroupsList from '../../../groups'; import initGroupsList from '~/groups';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup'); const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');

View File

@ -1,3 +0,0 @@
import VersionCheckImage from '../../version_check_image';
export default () => VersionCheckImage.bindErrorEvent($('img.js-version-status-badge'));

View File

@ -0,0 +1,7 @@
import VersionCheckImage from '~/version_check_image';
import docs from '~/docs/docs_bundle';
document.addEventListener('DOMContentLoaded', () => {
docs();
VersionCheckImage.bindErrorEvent($('img.js-version-status-badge'));
});

View File

@ -0,0 +1,3 @@
import initHelp from '~/help/help';
document.addEventListener('DOMContentLoaded', initHelp);

View File

@ -0,0 +1,3 @@
import initUIKit from '~/ui_development_kit';
document.addEventListener('DOMContentLoaded', initUIKit);

View File

@ -0,0 +1,3 @@
import initGitLabImportProject from '~/projects/project_import_gitlab_project';
document.addEventListener('DOMContentLoaded', initGitLabImportProject);

View File

@ -2,8 +2,10 @@
import Milestone from '~/milestone'; import Milestone from '~/milestone';
import Sidebar from '~/right_sidebar'; import Sidebar from '~/right_sidebar';
import MountMilestoneSidebar from '~/sidebar/mount_milestone_sidebar';
export default () => { export default () => {
new Milestone(); new Milestone();
new Sidebar(); new Sidebar();
new MountMilestoneSidebar();
}; };

View File

@ -1,5 +1,3 @@
import initU2F from '../../shared/sessions/u2f'; import initU2F from '../../shared/sessions/u2f';
export default () => { document.addEventListener('DOMContentLoaded', initU2F);
initU2F();
};

View File

@ -0,0 +1,3 @@
import initProfileAccount from '~/profile/account';
document.addEventListener('DOMContentLoaded', initProfileAccount);

View File

@ -1,7 +1,7 @@
import Activities from '~/activities'; import Activities from '~/activities';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
export default function () { document.addEventListener('DOMContentLoaded', () => {
new Activities(); // eslint-disable-line no-new new Activities(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
} });

View File

@ -0,0 +1,3 @@
import initBlobBundle from '~/blob_edit/blob_bundle';
document.addEventListener('DOMContentLoaded', initBlobBundle);

View File

@ -0,0 +1,3 @@
import initBlobBundle from '~/blob_edit/blob_bundle';
document.addEventListener('DOMContentLoaded', initBlobBundle);

View File

@ -1,7 +1,7 @@
import AjaxLoadingSpinner from '~/ajax_loading_spinner'; import AjaxLoadingSpinner from '~/ajax_loading_spinner';
import DeleteModal from '~/branches/branches_delete_modal'; import DeleteModal from '~/branches/branches_delete_modal';
export default () => { document.addEventListener('DOMContentLoaded', () => {
AjaxLoadingSpinner.init(); AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new new DeleteModal(); // eslint-disable-line no-new
}; });

View File

@ -1,3 +1,5 @@
import NewBranchForm from '~/new_branch_form'; import NewBranchForm from '~/new_branch_form';
export default () => new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML)); document.addEventListener('DOMContentLoaded', () => (
new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML))
));

View File

@ -0,0 +1,5 @@
import ClustersBundle from '~/clusters/clusters_bundle';
document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new
});

View File

@ -1,5 +1,5 @@
import ClustersIndex from '~/clusters/clusters_index'; import ClustersIndex from '~/clusters/clusters_index';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new ClustersIndex(); // eslint-disable-line no-new new ClustersIndex(); // eslint-disable-line no-new
}; });

View File

@ -1,5 +1,5 @@
import ClustersBundle from '~/clusters/clusters_bundle'; import ClustersBundle from '~/clusters/clusters_bundle';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new new ClustersBundle(); // eslint-disable-line no-new
}; });

View File

@ -0,0 +1,5 @@
import ClustersBundle from '~/clusters/clusters_bundle';
document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new
});

View File

@ -1,8 +1,8 @@
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown'; import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new MiniPipelineGraph({ new MiniPipelineGraph({
container: '.js-commit-pipeline-graph', container: '.js-commit-pipeline-graph',
}).bindEvents(); }).bindEvents();
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath); $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
}; });

View File

@ -7,7 +7,7 @@ import initNotes from '~/init_notes';
import initChangesDropdown from '~/init_changes_dropdown'; import initChangesDropdown from '~/init_changes_dropdown';
import { fetchCommitMergeRequests } from '~/commit_merge_requests'; import { fetchCommitMergeRequests } from '~/commit_merge_requests';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new Diff(); new Diff();
new ZenMode(); new ZenMode();
new ShortcutsNavigation(); new ShortcutsNavigation();
@ -19,4 +19,4 @@ export default () => {
initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - stickyBarPaddingTop); initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - stickyBarPaddingTop);
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath); $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
fetchCommitMergeRequests(); fetchCommitMergeRequests();
}; });

View File

@ -2,8 +2,8 @@ import CommitsList from '~/commits';
import GpgBadges from '~/gpg_badges'; import GpgBadges from '~/gpg_badges';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new CommitsList(document.querySelector('.js-project-commits-show').dataset.commitsLimit); // eslint-disable-line no-new new CommitsList(document.querySelector('.js-project-commits-show').dataset.commitsLimit); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
GpgBadges.fetch(); GpgBadges.fetch();
}; });

View File

@ -1,8 +1,8 @@
import Diff from '~/diff'; import Diff from '~/diff';
import initChangesDropdown from '~/init_changes_dropdown'; import initChangesDropdown from '~/init_changes_dropdown';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new Diff(); // eslint-disable-line no-new new Diff(); // eslint-disable-line no-new
const paddingTop = 16; const paddingTop = 16;
initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop); initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop);
}; });

View File

@ -4,11 +4,11 @@ import ProjectNew from '../shared/project_new';
import projectAvatar from '../shared/project_avatar'; import projectAvatar from '../shared/project_avatar';
import initProjectPermissionsSettings from '../shared/permissions'; import initProjectPermissionsSettings from '../shared/permissions';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new ProjectNew(); // eslint-disable-line no-new new ProjectNew(); // eslint-disable-line no-new
setupProjectEdit(); setupProjectEdit();
// Initialize expandable settings panels // Initialize expandable settings panels
initSettingsPanels(); initSettingsPanels();
projectAvatar(); projectAvatar();
initProjectPermissionsSettings(); initProjectPermissionsSettings();
}; });

Some files were not shown because too many files have changed in this diff Show More