Commit d3076ff0 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge commit '981b5905' into...

Merge commit '981b5905' into feature/gb/pipeline-variable-expressions

* commit '981b5905': (247 commits)
parents 76cf6c6a 981b5905
......@@ -15,7 +15,7 @@ engines:
enabled: false
rubocop:
enabled: true
channel: "gitlab-rubocop-0-52"
channel: "gitlab-rubocop-0-52-1"
ratings:
paths:
- Gemfile.lock
......
......@@ -323,69 +323,69 @@ setup-test-env:
- tmp/tests
- config/secrets.yml
rspec-pg 0 27: *rspec-metadata-pg
rspec-pg 1 27: *rspec-metadata-pg
rspec-pg 2 27: *rspec-metadata-pg
rspec-pg 3 27: *rspec-metadata-pg
rspec-pg 4 27: *rspec-metadata-pg
rspec-pg 5 27: *rspec-metadata-pg
rspec-pg 6 27: *rspec-metadata-pg
rspec-pg 7 27: *rspec-metadata-pg
rspec-pg 8 27: *rspec-metadata-pg
rspec-pg 9 27: *rspec-metadata-pg
rspec-pg 10 27: *rspec-metadata-pg
rspec-pg 11 27: *rspec-metadata-pg
rspec-pg 12 27: *rspec-metadata-pg
rspec-pg 13 27: *rspec-metadata-pg
rspec-pg 14 27: *rspec-metadata-pg
rspec-pg 15 27: *rspec-metadata-pg
rspec-pg 16 27: *rspec-metadata-pg
rspec-pg 17 27: *rspec-metadata-pg
rspec-pg 18 27: *rspec-metadata-pg
rspec-pg 19 27: *rspec-metadata-pg
rspec-pg 20 27: *rspec-metadata-pg
rspec-pg 21 27: *rspec-metadata-pg
rspec-pg 22 27: *rspec-metadata-pg
rspec-pg 23 27: *rspec-metadata-pg
rspec-pg 24 27: *rspec-metadata-pg
rspec-pg 25 27: *rspec-metadata-pg
rspec-pg 26 27: *rspec-metadata-pg
rspec-mysql 0 27: *rspec-metadata-mysql
rspec-mysql 1 27: *rspec-metadata-mysql
rspec-mysql 2 27: *rspec-metadata-mysql
rspec-mysql 3 27: *rspec-metadata-mysql
rspec-mysql 4 27: *rspec-metadata-mysql
rspec-mysql 5 27: *rspec-metadata-mysql
rspec-mysql 6 27: *rspec-metadata-mysql
rspec-mysql 7 27: *rspec-metadata-mysql
rspec-mysql 8 27: *rspec-metadata-mysql
rspec-mysql 9 27: *rspec-metadata-mysql
rspec-mysql 10 27: *rspec-metadata-mysql
rspec-mysql 11 27: *rspec-metadata-mysql
rspec-mysql 12 27: *rspec-metadata-mysql
rspec-mysql 13 27: *rspec-metadata-mysql
rspec-mysql 14 27: *rspec-metadata-mysql
rspec-mysql 15 27: *rspec-metadata-mysql
rspec-mysql 16 27: *rspec-metadata-mysql
rspec-mysql 17 27: *rspec-metadata-mysql
rspec-mysql 18 27: *rspec-metadata-mysql
rspec-mysql 19 27: *rspec-metadata-mysql
rspec-mysql 20 27: *rspec-metadata-mysql
rspec-mysql 21 27: *rspec-metadata-mysql
rspec-mysql 22 27: *rspec-metadata-mysql
rspec-mysql 23 27: *rspec-metadata-mysql
rspec-mysql 24 27: *rspec-metadata-mysql
rspec-mysql 25 27: *rspec-metadata-mysql
rspec-mysql 26 27: *rspec-metadata-mysql
spinach-pg 0 3: *spinach-metadata-pg
spinach-pg 1 3: *spinach-metadata-pg
spinach-pg 2 3: *spinach-metadata-pg
spinach-mysql 0 3: *spinach-metadata-mysql
spinach-mysql 1 3: *spinach-metadata-mysql
spinach-mysql 2 3: *spinach-metadata-mysql
rspec-pg 0 28: *rspec-metadata-pg
rspec-pg 1 28: *rspec-metadata-pg
rspec-pg 2 28: *rspec-metadata-pg
rspec-pg 3 28: *rspec-metadata-pg
rspec-pg 4 28: *rspec-metadata-pg
rspec-pg 5 28: *rspec-metadata-pg
rspec-pg 6 28: *rspec-metadata-pg
rspec-pg 7 28: *rspec-metadata-pg
rspec-pg 8 28: *rspec-metadata-pg
rspec-pg 9 28: *rspec-metadata-pg
rspec-pg 10 28: *rspec-metadata-pg
rspec-pg 11 28: *rspec-metadata-pg
rspec-pg 12 28: *rspec-metadata-pg
rspec-pg 13 28: *rspec-metadata-pg
rspec-pg 14 28: *rspec-metadata-pg
rspec-pg 15 28: *rspec-metadata-pg
rspec-pg 16 28: *rspec-metadata-pg
rspec-pg 17 28: *rspec-metadata-pg
rspec-pg 18 28: *rspec-metadata-pg
rspec-pg 19 28: *rspec-metadata-pg
rspec-pg 20 28: *rspec-metadata-pg
rspec-pg 21 28: *rspec-metadata-pg
rspec-pg 22 28: *rspec-metadata-pg
rspec-pg 23 28: *rspec-metadata-pg
rspec-pg 24 28: *rspec-metadata-pg
rspec-pg 25 28: *rspec-metadata-pg
rspec-pg 26 28: *rspec-metadata-pg
rspec-pg 27 28: *rspec-metadata-pg
rspec-mysql 0 28: *rspec-metadata-mysql
rspec-mysql 1 28: *rspec-metadata-mysql
rspec-mysql 2 28: *rspec-metadata-mysql
rspec-mysql 3 28: *rspec-metadata-mysql
rspec-mysql 4 28: *rspec-metadata-mysql
rspec-mysql 5 28: *rspec-metadata-mysql
rspec-mysql 6 28: *rspec-metadata-mysql
rspec-mysql 7 28: *rspec-metadata-mysql
rspec-mysql 8 28: *rspec-metadata-mysql
rspec-mysql 9 28: *rspec-metadata-mysql
rspec-mysql 10 28: *rspec-metadata-mysql
rspec-mysql 11 28: *rspec-metadata-mysql
rspec-mysql 12 28: *rspec-metadata-mysql
rspec-mysql 13 28: *rspec-metadata-mysql
rspec-mysql 14 28: *rspec-metadata-mysql
rspec-mysql 15 28: *rspec-metadata-mysql
rspec-mysql 16 28: *rspec-metadata-mysql
rspec-mysql 17 28: *rspec-metadata-mysql
rspec-mysql 18 28: *rspec-metadata-mysql
rspec-mysql 19 28: *rspec-metadata-mysql
rspec-mysql 20 28: *rspec-metadata-mysql
rspec-mysql 21 28: *rspec-metadata-mysql
rspec-mysql 22 28: *rspec-metadata-mysql
rspec-mysql 23 28: *rspec-metadata-mysql
rspec-mysql 24 28: *rspec-metadata-mysql
rspec-mysql 25 28: *rspec-metadata-mysql
rspec-mysql 26 28: *rspec-metadata-mysql
rspec-mysql 27 28: *rspec-metadata-mysql
spinach-pg 0 2: *spinach-metadata-pg
spinach-pg 1 2: *spinach-metadata-pg
spinach-mysql 0 2: *spinach-metadata-mysql
spinach-mysql 1 2: *spinach-metadata-mysql
# Static analysis jobs
.ruby-static-analysis: &ruby-static-analysis
......@@ -607,22 +607,24 @@ karma:
codequality:
<<: *except-docs
<<: *pull-cache
before_script: []
image: docker:latest
stage: test
variables:
SETUP_DB: "false"
DOCKER_DRIVER: overlay
image: docker:latest
before_script: []
services:
- docker:dind
variables:
SETUP_DB: "false"
DOCKER_DRIVER: overlay2
CODECLIMATE_FORMAT: json
cache: {}
dependencies: []
script:
- cp .rubocop.yml .rubocop.yml.bak
- grep -v "rubocop-gitlab-security" .rubocop.yml.bak > .rubocop.yml
- 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,fingerprint,location})' > codeclimate.json
- mv .rubocop.yml.bak .rubocop.yml
- ./scripts/codequality analyze -f json > raw_codeclimate.json || true
# The following line keeps only the fields used in the MR widget, reducing the JSON artifact size
- cat raw_codeclimate.json | docker run -i stedolan/jq -c 'map({check_name,description,fingerprint,location})' > codeclimate.json
artifacts:
paths: [codeclimate.json]
expire_in: 1 week
sast:
<<: *except-docs
......
This diff is collapsed.
......@@ -81,7 +81,7 @@ gem 'gollum-lib', '~> 4.2', require: false
gem 'gollum-rugged_adapter', '~> 0.4.4', require: false
# Language detection
gem 'github-linguist', '~> 4.7.0', require: 'linguist'
gem 'github-linguist', '~> 5.3.3', require: 'linguist'
# API
gem 'grape', '~> 1.0'
......@@ -401,6 +401,7 @@ gem 'sys-filesystem', '~> 1.1.6'
# SSH host key support
gem 'net-ssh', '~> 4.1.0'
gem 'sshkey', '~> 1.9.0'
# Required for ED25519 SSH host key support
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
gem 'google-protobuf', '= 3.5.1'
gem 'toml-rb', '~> 0.3.15', require: false
gem 'toml-rb', '~> 1.0.0', require: false
# Feature toggles
gem 'flipper', '~> 0.11.0'
......
......@@ -288,11 +288,11 @@ GEM
gitaly-proto (0.84.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (4.7.6)
charlock_holmes (~> 0.7.3)
github-linguist (5.3.3)
charlock_holmes (~> 0.7.5)
escape_utils (~> 1.1.0)
mime-types (>= 1.19)
rugged (>= 0.23.0b)
rugged (>= 0.25.1)
github-markup (1.6.1)
gitlab-flowdock-git-hook (1.0.1)
flowdock (~> 0.7)
......@@ -895,6 +895,7 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
sshkey (1.9.0)
stackprof (0.2.10)
state_machines (0.4.0)
state_machines-activemodel (0.4.0)
......@@ -923,7 +924,7 @@ GEM
timfel-krb5-auth (0.8.3)
toml (0.1.2)
parslet (~> 1.5.0)
toml-rb (0.3.15)
toml-rb (1.0.0)
citrus (~> 3.0, > 3.0)
truncato (0.7.10)
htmlentities (~> 4.3.1)
......@@ -1057,7 +1058,7 @@ DEPENDENCIES
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
gitaly-proto (~> 0.84.0)
github-linguist (~> 4.7.0)
github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.6.2)
gitlab-styles (~> 2.3)
......@@ -1192,6 +1193,7 @@ DEPENDENCIES
spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.1.0)
sprockets (~> 3.7.0)
sshkey (~> 1.9.0)
stackprof (~> 0.2.10)
state_machines-activerecord (~> 0.4.0)
sys-filesystem (~> 1.1.6)
......@@ -1199,7 +1201,7 @@ DEPENDENCIES
test_after_commit (~> 1.1)
thin (~> 1.7.0)
timecop (~> 0.8.0)
toml-rb (~> 0.3.15)
toml-rb (~> 1.0.0)
truncato (~> 0.7.9)
u2f (~> 0.2.1)
uglifier (~> 2.7.2)
......
10.5.0-pre
10.6.0-pre
......@@ -9,7 +9,7 @@ const Api = {
projectsPath: '/api/:version/projects.json',
projectPath: '/api/:version/projects/:id',
projectLabelsPath: '/:namespace_path/:project_path/labels',
groupLabelsPath: '/groups/:namespace_path/labels',
groupLabelsPath: '/groups/:namespace_path/-/labels',
licensePath: '/api/:version/templates/licenses/:key',
gitignorePath: '/api/:version/templates/gitignores/:key',
gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key',
......@@ -32,7 +32,7 @@ const Api = {
},
// Return groups list. Filtered by query
groups(query, options, callback) {
groups(query, options, callback = $.noop) {
const url = Api.buildUrl(Api.groupsPath);
return axios.get(url, {
params: Object.assign({
......
......@@ -312,7 +312,7 @@ class AwardsHandler {
}
getAwardUrl() {
return this.getVotesBlock().data('award-url');
return this.getVotesBlock().data('awardUrl');
}
checkMutuality(votesBlock, emoji) {
......
......@@ -2,7 +2,7 @@ import Clipboard from 'clipboard';
function showTooltip(target, title) {
const $target = $(target);
const originalTitle = $target.data('original-title');
const originalTitle = $target.data('originalTitle');
if (!$target.data('hideTooltip')) {
$target
......
......@@ -43,7 +43,7 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
const $form = $(e.target).closest('form');
const $submitButton = $form.find('input[type=submit], button[type=submit]').first();
if (!$submitButton.attr('disabled')) {
if (!$submitButton.prop('disabled')) {
$submitButton.trigger('click', [e]);
if (!isInIssuePage()) {
......
......@@ -40,7 +40,7 @@ $.fn.requiresInput = function requiresInput() {
// based on the option selected
function hideOrShowHelpBlock(form) {
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();
} else if (selected.length) {
form.find('.help-block').show();
......
......@@ -4,16 +4,16 @@ import NewCommitForm from '../new_commit_form';
import EditBlob from './edit_blob';
import BlobFileDropzone from '../blob/blob_file_dropzone';
$(() => {
export default () => {
const editBlobForm = $('.js-edit-blob-form');
const uploadBlobForm = $('.js-upload-blob-form');
const deleteBlobForm = $('.js-delete-blob-form');
if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relative-url-root');
const assetsPath = editBlobForm.data('assets-prefix');
const blobLanguage = editBlobForm.data('blob-language');
const currentAction = $('.js-file-title').data('current-action');
const urlRoot = editBlobForm.data('relativeUrlRoot');
const assetsPath = editBlobForm.data('assetsPrefix');
const blobLanguage = editBlobForm.data('blobLanguage');
const currentAction = $('.js-file-title').data('currentAction');
new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction);
new NewCommitForm(editBlobForm);
......@@ -34,4 +34,4 @@ $(() => {
if (deleteBlobForm.length) {
new NewCommitForm(deleteBlobForm);
}
});
};
......@@ -59,7 +59,7 @@ export default class EditBlob {
if (paneId === '#preview') {
this.$toggleButton.hide();
axios.post(currentLink.data('preview-url'), {
axios.post(currentLink.data('previewUrl'), {
content: this.editor.getValue(),
})
.then(({ data }) => {
......
......@@ -25,7 +25,7 @@ $(document).off('created.label').on('created.label', (e, label) => {
gl.issueBoards.newListDropdownInit = () => {
$('.js-new-board-list').each(function () {
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({
data(term, callback) {
......
/* eslint-disable class-methods-use-this */
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 = []) {
super('boards');
......
......@@ -7,7 +7,6 @@
mixins: [
pipelinesMixin,
],
props: {
endpoint: {
type: String,
......
......@@ -13,6 +13,6 @@ import 'bootstrap-sass/assets/javascripts/bootstrap/popover';
// custom jQuery functions
$.fn.extend({
disable() { return $(this).attr('disabled', 'disabled').addClass('disabled'); },
enable() { return $(this).removeAttr('disabled').removeClass('disabled'); },
disable() { return $(this).prop('disabled', true).addClass('disabled'); },
enable() { return $(this).prop('disabled', false).removeClass('disabled'); },
});
......@@ -13,7 +13,7 @@ export default class Compare {
$dropdown = $(dropdown);
return $dropdown.glDropdown({
selectable: true,
fieldName: $dropdown.data('field-name'),
fieldName: $dropdown.data('fieldName'),
filterable: true,
id: function(obj, $el) {
return $el.data('id');
......
......@@ -9,7 +9,7 @@ export default function initCompareAutocomplete() {
$dropdown = $(this);
selected = $dropdown.data('selected');
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);
$dropdown.glDropdown({
data: function(term, callback) {
......@@ -25,7 +25,7 @@ export default function initCompareAutocomplete() {
selectable: true,
filterable: true,
filterRemote: true,
fieldName: $dropdown.data('field-name'),
fieldName: $dropdown.data('fieldName'),
filterInput: 'input[type="search"]',
renderRow: function(ref) {
var link;
......
......@@ -37,7 +37,7 @@
>
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="mergeRequest.author.avatarUrl"/>
<user-avatar-image :img-src="mergeRequest.author.avatarUrl" />
<h5 class="item-title merge-merquest-title">
<a :href="mergeRequest.url">
{{ mergeRequest.title }}
......
......@@ -68,7 +68,7 @@ export default class Diff {
}
const file = $target.parents('.diff-file');
const link = file.data('blob-diff-path');
const link = file.data('blobDiffPath');
const view = file.data('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
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
lineNumbers(line) {
......
......@@ -15,7 +15,7 @@ import './components/resolve_discussion_btn';
import './components/diff_note_avatars';
import './components/new_issue_for_discussion';
$(() => {
export default () => {
const projectPathHolder = document.querySelector('.merge-request') || document.querySelector('.commit-box');
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';
......@@ -71,8 +71,8 @@ $(() => {
el: '#resolve-count-app',
components: {
'resolve-count': ResolveCount
}
},
});
$(window).trigger('resize.nav');
});
};
This diff is collapsed.
......@@ -4,10 +4,7 @@ function addMousetrapClick(el, key) {
el.addEventListener('click', () => Mousetrap.trigger(key));
}
function domContentLoaded() {
export default () => {
addMousetrapClick(document.querySelector('.js-trigger-shortcut'), '?');
addMousetrapClick(document.querySelector('.js-trigger-search-bar'), 's');
}
document.addEventListener('DOMContentLoaded', domContentLoaded);
};
......@@ -17,9 +17,9 @@ class DueDateSelect {
this.$value = $block.find('.value');
this.$valueContent = $block.find('.value-content');
this.$sidebarValue = $('.js-due-date-sidebar-value', $block);
this.fieldName = $dropdown.data('field-name');
this.abilityName = $dropdown.data('ability-name');
this.issueUpdateURL = $dropdown.data('issue-update');
this.fieldName = $dropdown.data('fieldName');
this.abilityName = $dropdown.data('abilityName');
this.issueUpdateURL = $dropdown.data('issueUpdate');
this.rawSelectedDate = null;
this.displayedDate = null;
......
......@@ -25,7 +25,7 @@ export default {
if (!this.userCanCreateNote) {
// 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';
......
import eventHub from '../event_hub';
import FilteredSearchTokenizer from '../filtered_search_tokenizer';
export default {
name: 'RecentSearchesDropdownContent',
......@@ -23,7 +24,7 @@ export default {
processedItems() {
return this.items.map((item) => {
const { tokens, searchToken }
= gl.FilteredSearchTokenizer.processTokens(item, this.allowedKeys);
= FilteredSearchTokenizer.processTokens(item, this.allowedKeys);
const resultantTokens = tokens.map(token => ({
prefix: `${token.key}:`,
......
import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax';
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 = {}) {
super(options);
this.config = {
......@@ -49,7 +50,7 @@ class DropdownEmoji extends gl.FilteredSearchDropdown {
itemClicked(e) {
super.itemClicked(e, (selected) => {
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();
}
}
window.gl = window.gl || {};
gl.DropdownEmoji = DropdownEmoji;
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 = {}) {
const { input, tokenKeys } = options;
super(options);
this.config = {
Filter: {
template: 'hint',
filterFunction: gl.DropdownUtils.filterHint.bind(null, {
filterFunction: DropdownUtils.filterHint.bind(null, {
input,
allowedKeys: tokenKeys.getKeys(),
}),
......@@ -45,10 +48,10 @@ class DropdownHint extends gl.FilteredSearchDropdown {
});
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.dispatchInputEvent();
......@@ -73,6 +76,3 @@ class DropdownHint extends gl.FilteredSearchDropdown {
this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init();
}
}
window.gl = window.gl || {};
gl.DropdownHint = DropdownHint;
import Flash from '../flash';
import Ajax from '../droplab/plugins/ajax';
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 = {}) {
const { input, endpoint, symbol, preprocessing } = options;
super(options);
......@@ -21,7 +22,7 @@ class DropdownNonUser extends gl.FilteredSearchDropdown {
},
},
Filter: {
filterFunction: gl.DropdownUtils.filterWithSymbol.bind(null, this.symbol, input),
filterFunction: DropdownUtils.filterWithSymbol.bind(null, this.symbol, input),
template: 'title',
},
};
......@@ -30,7 +31,7 @@ class DropdownNonUser extends gl.FilteredSearchDropdown {
itemClicked(e) {
super.itemClicked(e, (selected) => {
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();
}
}
window.gl = window.gl || {};
gl.DropdownNonUser = DropdownNonUser;
import Flash from '../flash';
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 DropdownUtils from './dropdown_utils';
import FilteredSearchTokenizer from './filtered_search_tokenizer';
class DropdownUser extends gl.FilteredSearchDropdown {
export default class DropdownUser extends FilteredSearchDropdown {
constructor(options = {}) {
const { tokenKeys } = options;
super(options);
......@@ -56,8 +58,8 @@ class DropdownUser extends gl.FilteredSearchDropdown {
}
getSearchInput() {
const query = gl.DropdownUtils.getSearchInput(this.input);
const { lastToken } = gl.FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get());
const query = DropdownUtils.getSearchInput(this.input);
const { lastToken } = FilteredSearchTokenizer.processTokens(query, this.tokenKeys.get());
let value = lastToken || '';
......@@ -78,6 +80,3 @@ class DropdownUser extends gl.FilteredSearchDropdown {
this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init();
}
}
window.gl = window.gl || {};
gl.DropdownUser = DropdownUser;
import _ from 'underscore';
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) {
let escapedText = text;
const hasSpace = text.indexOf(' ') !== -1;
......@@ -24,7 +27,7 @@ class DropdownUtils {
static filterWithSymbol(filterSymbol, input, item) {
const updatedItem = item;
const searchInput = gl.DropdownUtils.getSearchInput(input);
const searchInput = DropdownUtils.getSearchInput(input);
const title = updatedItem.title.toLowerCase();
let value = searchInput.toLowerCase();
......@@ -114,9 +117,9 @@ class DropdownUtils {
static filterHint(config, item) {
const { input, allowedKeys } = config;
const updatedItem = item;
const searchInput = gl.DropdownUtils.getSearchQuery(input);
const searchInput = DropdownUtils.getSearchQuery(input);
const { lastToken, tokens } =
gl.FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
const lastKey = lastToken.key || lastToken || '';
const allowMultiple = item.type === 'array';
const itemInExistingTokens = tokens.some(t => t.key === item.hint);
......@@ -140,7 +143,7 @@ class DropdownUtils {
const dataValue = selected.getAttribute('data-value');
if (dataValue) {
gl.FilteredSearchDropdownManager.addWordToInput(filter, dataValue, true);
FilteredSearchDropdownManager.addWordToInput(filter, dataValue, true);
}
// Return boolean based on whether it was set
......@@ -190,7 +193,7 @@ class DropdownUtils {
}
} else if (token.classList.contains('input-token')) {
const { isLastVisualTokenValid } =
gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
const inputValue = input && input.value;
......@@ -211,7 +214,7 @@ class DropdownUtils {
static getSearchInput(filteredSearchInput) {
const inputValue = filteredSearchInput.value;
const { right } = gl.DropdownUtils.getInputSelectionPosition(filteredSearchInput);
const { right } = DropdownUtils.getInputSelectionPosition(filteredSearchInput);
return inputValue.slice(0, right);
}
......@@ -252,6 +255,3 @@ class DropdownUtils {
};
}
}
window.gl = window.gl || {};
gl.DropdownUtils = DropdownUtils;
import DropdownUtils from './dropdown_utils';
import FilteredSearchDropdownManager from './filtered_search_dropdown_manager';
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
class FilteredSearchDropdown {
export default class FilteredSearchDropdown {
constructor({ droplab, dropdown, input, filter }) {
this.droplab = droplab;
this.hookId = input && input.id;
......@@ -30,11 +33,11 @@ class FilteredSearchDropdown {
const { selected } = e.detail;
if (selected.tagName === 'LI' && selected.innerHTML) {
const dataValueSet = gl.DropdownUtils.setDataValueIfSelected(this.filter, selected);
const dataValueSet = DropdownUtils.setDataValueIfSelected(this.filter, selected);
if (!dataValueSet) {
const value = getValueFunction(selected);
gl.FilteredSearchDropdownManager.addWordToInput(this.filter, value, true);
FilteredSearchDropdownManager.addWordToInput(this.filter, value, true);
}
this.resetFilters();
......@@ -108,6 +111,9 @@ class FilteredSearchDropdown {
if (hook) {
const data = hook.list.data || [];
if (!data) return;
const results = data.map((o) => {
const updated = o;
updated.droplab_hidden = false;
......@@ -117,6 +123,3 @@ class FilteredSearchDropdown {
}
}
}
window.gl = window.gl || {};
gl.FilteredSearchDropdown = FilteredSearchDropdown;
import _ from 'underscore';
import DropLab from '~/droplab/drop_lab';
import FilteredSearchContainer from './container';
class FilteredSearchDropdownManager {
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';
export default class FilteredSearchDropdownManager {
constructor(baseEndpoint = '', tokenizer, page, isGroup, filteredSearchTokenKeys) {
this.container = FilteredSearchContainer.container;
this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
this.tokenizer = tokenizer;
this.filteredSearchTokenKeys = filteredSearchTokenKeys;
this.filteredSearchTokenKeys = filteredSearchTokenKeys || FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search');
this.page = page;
......@@ -33,24 +40,24 @@ class FilteredSearchDropdownManager {
const allowedMappings = {
hint: {
reference: null,
gl: 'DropdownHint',
gl: DropdownHint,
element: this.container.querySelector('#js-dropdown-hint'),
},
};
const availableMappings = {
author: {
reference: null,
gl: 'DropdownUser',
gl: DropdownUser,
element: this.container.querySelector('#js-dropdown-author'),
},
assignee: {
reference: null,
gl: 'DropdownUser',
gl: DropdownUser,
element: this.container.querySelector('#js-dropdown-assignee'),
},
milestone: {
reference: null,
gl: 'DropdownNonUser',
gl: DropdownNonUser,
extraArguments: {
endpoint: `${this.baseEndpoint}/milestones.json`,
symbol: '%',
......@@ -59,17 +66,17 @@ class FilteredSearchDropdownManager {
},
label: {
reference: null,
gl: 'DropdownNonUser',
gl: DropdownNonUser,
extraArguments: {
endpoint: `${this.baseEndpoint}/labels.json`,
symbol: '~',
preprocessing: gl.DropdownUtils.duplicateLabelPreprocessing,
preprocessing: DropdownUtils.duplicateLabelPreprocessing,
},
element: this.container.querySelector('#js-dropdown-label'),
},
'my-reaction': {
reference: null,
gl: 'DropdownEmoji',
gl: DropdownEmoji,
element: this.container.querySelector('#js-dropdown-my-reaction'),
},
};
......@@ -86,11 +93,11 @@ class FilteredSearchDropdownManager {
static addWordToInput(tokenName, tokenValue = '', clicked = false) {
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
gl.FilteredSearchVisualTokens.addFilterVisualToken(tokenName, tokenValue);
FilteredSearchVisualTokens.addFilterVisualToken(tokenName, tokenValue);
input.value = '';
if (clicked) {
gl.FilteredSearchVisualTokens.moveInputToTheRight();
FilteredSearchVisualTokens.moveInputToTheRight();
}
}
......@@ -131,9 +138,9 @@ class FilteredSearchDropdownManager {
const extraArguments = mappingKey.extraArguments || {};
const glArguments = Object.assign({}, defaultArguments, extraArguments);
// Passing glArguments to `new gl[glClass](<arguments>)`
// Passing glArguments to `new glClass(<arguments>)`
mappingKey.reference =
new (Function.prototype.bind.apply(gl[glClass], [null, glArguments]))();
new (Function.prototype.bind.apply(glClass, [null, glArguments]))();
}
if (firstLoad) {
......@@ -171,7 +178,7 @@ class FilteredSearchDropdownManager {
}
setDropdown() {
const query = gl.DropdownUtils.getSearchQuery(true);
const query = DropdownUtils.getSearchQuery(true);
const { lastToken, searchToken } =
this.tokenizer.processTokens(query, this.filteredSearchTokenKeys.getKeys());
......@@ -216,6 +223,3 @@ class FilteredSearchDropdownManager {
this.droplab.destroy();
}
}
window.gl = window.gl || {};
gl.FilteredSearchDropdownManager = FilteredSearchDropdownManager;
import './filtered_search_token_keys';
class FilteredSearchTokenizer {
export default class FilteredSearchTokenizer {
static processTokens(input, allowedKeys) {
// Regex extracts `(token):(symbol)(value)`
// 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;
......@@ -3,8 +3,9 @@ import AjaxCache from '../lib/utils/ajax_cache';
import Flash from '../flash';
import FilteredSearchContainer from './container';
import UsersCache from '../lib/utils/users_cache';
import DropdownUtils from './dropdown_utils';
class FilteredSearchVisualTokens {
export default class FilteredSearchVisualTokens {
static getLastVisualTokenBeforeInput() {
const inputLi = FilteredSearchContainer.container.querySelector('.input-token');
const lastVisualToken = inputLi && inputLi.previousElementSibling;
......@@ -74,7 +75,7 @@ class FilteredSearchVisualTokens {
let processed = labels;
if (!labels.preprocessed) {
processed = gl.DropdownUtils.duplicateLabelPreprocessing(labels);
processed = DropdownUtils.duplicateLabelPreprocessing(labels);
AjaxCache.override(labelsEndpoint, processed);
processed.preprocessed = true;
}
......@@ -90,7 +91,7 @@ class FilteredSearchVisualTokens {
return AjaxCache.retrieve(labelsEndpoint)
.then(FilteredSearchVisualTokens.preprocessLabel.bind(null, labelsEndpoint))
.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) {
return;
......@@ -259,11 +260,11 @@ class FilteredSearchVisualTokens {
static tokenizeInput() {
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
const { isLastVisualTokenValid } =
gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (input.value) {
if (isLastVisualTokenValid) {
gl.FilteredSearchVisualTokens.addSearchVisualToken(input.value);
FilteredSearchVisualTokens.addSearchVisualToken(input.value);
} else {
FilteredSearchVisualTokens.addValueToPreviousVisualTokenElement(input.value);
}
......@@ -324,12 +325,12 @@ class FilteredSearchVisualTokens {
if (!tokenContainer.lastElementChild.isEqualNode(inputLi)) {
const { isLastVisualTokenValid } =
gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (!isLastVisualTokenValid) {
const lastPartial = gl.FilteredSearchVisualTokens.getLastTokenPartial();
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
gl.FilteredSearchVisualTokens.addSearchVisualToken(lastPartial);
const lastPartial = FilteredSearchVisualTokens.getLastTokenPartial();
FilteredSearchVisualTokens.removeLastTokenPartial();
FilteredSearchVisualTokens.addSearchVisualToken(lastPartial);
}
tokenContainer.removeChild(inputLi);
......@@ -337,6 +338,3 @@ class FilteredSearchVisualTokens {
}
}
}
window.gl = window.gl || {};
gl.FilteredSearchVisualTokens = FilteredSearchVisualTokens;
......@@ -485,7 +485,7 @@ GitLabDropdown = (function() {
$target = $(e.target);
if ($target && !$target.hasClass('dropdown-menu-close') &&
!$target.hasClass('dropdown-menu-close-icon') &&
!$target.data('is-link')) {
!$target.data('isLink')) {
e.stopPropagation();
return false;
} else {
......@@ -607,7 +607,20 @@ GitLabDropdown = (function() {
};
GitLabDropdown.prototype.renderItem = function(data, group, index) {
var field, fieldName, html, selected, text, url, value;
var field, fieldName, html, selected, text, url, value, rowHidden;
if (!this.options.renderRow) {
value = this.options.id ? this.options.id(data) : data.id;
if (value) {
value = value.toString().replace(/'/g, '\\\'');
}
}
// Hide element
if (this.options.hideRow && this.options.hideRow(value)) {
rowHidden = true;
}
if (group == null) {
group = false;
}
......@@ -616,6 +629,7 @@ GitLabDropdown = (function() {
index = false;
}
html = document.createElement('li');
if (data === 'divider' || data === 'separator') {
html.className = data;
return html;
......@@ -631,11 +645,9 @@ GitLabDropdown = (function() {
html = this.options.renderRow.call(this.options, data, this);
} else {
if (!selected) {
value = this.options.id ? this.options.id(data) : data.id;
fieldName = this.options.fieldName;
if (value) {
value = value.toString().replace(/'/g, '\\\'');
field = this.dropdown.parent().find(`input[name='${fieldName}'][value='${value}']`);
if (field.length) {
selected = true;
......
......@@ -12,7 +12,7 @@ export default class GLForm {
this.destroy();
// Setup the form
this.setupForm();
this.form.data('gl-form', this);
this.form.data('glForm', this);
}
destroy() {
......@@ -21,7 +21,7 @@ export default class GLForm {
if (this.autoComplete) {
this.autoComplete.destroy();
}
this.form.data('gl-form', null);
this.form.data('glForm', null);
}
setupForm() {
......
......@@ -11,7 +11,7 @@ export default class GpgBadges {
badges.html('<i class="fa fa-spinner fa-spin"></i>');
const params = parseQueryStringIntoObject(form.serialize());
return axios.get(form.data('signatures-path'), { params })
return axios.get(form.data('signaturesPath'), { params })
.then(({ data }) => {
data.signatures.forEach((signature) => {
badges.filter(`[data-commit-sha="${signature.commit_sha}"]`).replaceWith(signature.html);
......
import Chart from 'vendor/Chart';
// export to global scope
window.Chart = Chart;
......@@ -30,11 +30,11 @@
default: 'bottom',
},
/**
* value could either be number or string
* as `memberCount` is always passed as string
* while `subgroupCount` & `projectCount`
* are always number
*/
* value could either be number or string
* as `memberCount` is always passed as string
* while `subgroupCount` & `projectCount`
* are always number
*/
value: {
type: [Number, String],
required: false,
......
......@@ -7,8 +7,8 @@ export default function groupsSelect() {
window.GROUP_SELECT_PER_PAGE = 20;
$('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
const $select = $(this);
const allAvailable = $select.data('all-available');
const skipGroups = $select.data('skip-groups') || [];
const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skipGroups') || [];
$select.select2({
placeholder: 'Search for a group',
multiple: $select.hasClass('multiselect'),
......
// We will render the icons list here
if ($('#user-content-gitlab-icons').length > 0) {
const $iconsHeader = $('#user-content-gitlab-icons');
const $iconsList = $('<div id="iconsList">ICONS</div>');
$($iconsList).insertAfter($iconsHeader.parent());
}
export default () => {
if ($('#user-content-gitlab-icons').length > 0) {
const $iconsHeader = $('#user-content-gitlab-icons');
const $iconsList = $('<div id="iconsList">ICONS</div>');
$($iconsList).insertAfter($iconsHeader.parent());
}
};
document.addEventListener('DOMContentLoaded', () => {
const modal = $('#modal_merge_info').modal({
modal: true,
show: false,
});
$('.how_to_merge_link').on('click', () => {
modal.show();
});
$('.modal-header .close').on('click', () => {
modal.hide();
});
});
export default () => {
const modal = $('#modal_merge_info');
if (modal) {
modal.modal({
modal: true,
show: false,
});
$('.how_to_merge_link').on('click', modal.show);
$('.modal-header .close').on('click', modal.hide);
}
};
......@@ -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
window.__monaco_context__ = monacoContext;
export default monacoContext.require;
......@@ -6,8 +6,8 @@ export default class IntegrationSettingsForm {
this.$form = $(formSelector);
// Form Metadata
this.canTestService = this.$form.data('can-test');
this.testEndPoint = this.$form.data('test-url');
this.canTestService = this.$form.data('canTest');
this.testEndPoint = this.$form.data('testUrl');
// Form Child Elements
this.$serviceToggle = this.$form.find('#service_active');
......
......@@ -78,6 +78,7 @@
taskListUpdateSuccess(data) {
try {
this.checkForSpam(data);
this.closeRecaptcha();
} catch (error) {
if (error && error.name === 'SpamError') this.openRecaptcha();
}
......
export default function issueStatusSelect() {
$('.js-issue-status').each((i, el) => {
const fieldName = $(el).data('field-name');
const fieldName = $(el).data('fieldName');
return $(el).glDropdown({
selectable: true,
fieldName,
......
......@@ -3,7 +3,7 @@ import JobMediator from './job_details_mediator';
import jobHeader from './components/header.vue';
import detailsBlock from './components/sidebar_details_block.vue';
document.addEventListener('DOMContentLoaded', () => {
export default () => {
const dataset = document.getElementById('js-job-details-vue').dataset;
const mediator = new JobMediator({ endpoint: dataset.endpoint });
......@@ -55,4 +55,4 @@ document.addEventListener('DOMContentLoaded', () => {
});
},
});
});
};
......@@ -25,19 +25,19 @@ export default class LabelsSelect {
$dropdown = $(dropdown);
$dropdownContainer = $dropdown.closest('.labels-filter');
$toggleText = $dropdown.find('.dropdown-toggle-text');
namespacePath = $dropdown.data('namespace-path');
projectPath = $dropdown.data('project-path');
namespacePath = $dropdown.data('namespacePath');
projectPath = $dropdown.data('projectPath');
labelUrl = $dropdown.data('labels');
issueUpdateURL = $dropdown.data('issueUpdate');
selectedLabel = $dropdown.data('selected');
if ((selectedLabel != null) && !$dropdown.hasClass('js-multiselect')) {
selectedLabel = selectedLabel.split(',');
}
showNo = $dropdown.data('show-no');
showAny = $dropdown.data('show-any');
showNo = $dropdown.data('showNo');
showAny = $dropdown.data('showAny');
showMenuAbove = $dropdown.data('showMenuAbove');
defaultLabel = $dropdown.data('default-label');
abilityName = $dropdown.data('ability-name');
defaultLabel = $dropdown.data('defaultLabel');
abilityName = $dropdown.data('abilityName');
$selectbox = $dropdown.closest('.selectbox');
$block = $selectbox.closest('.block');
$form = $dropdown.closest('form, .js-issuable-update');
......@@ -45,11 +45,11 @@ export default class LabelsSelect {
$sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip');
$value = $block.find('.value');
$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');
propertyName = useId ? 'id' : 'title';
initialSelected = $selectbox
.find('input[name="' + $dropdown.data('field-name') + '"]')
.find('input[name="' + $dropdown.data('fieldName') + '"]')
.map(function () {
return this.value;
}).get();
......@@ -268,7 +268,7 @@ export default class LabelsSelect {
return defaultLabel;
}
},
fieldName: $dropdown.data('field-name'),
fieldName: $dropdown.data('fieldName'),
id: function(label) {
if (label.id <= 0) return label.title;
......@@ -316,9 +316,9 @@ export default class LabelsSelect {
},
multiSelect: $dropdown.hasClass('js-multiselect'),
vue: $dropdown.hasClass('js-issue-board-sidebar'),
clicked: function(options) {
const { $el, e, isMarking } = options;
const label = options.selectedObj;
clicked: function (clickEvent) {
const { $el, e, isMarking } = clickEvent;
const label = clickEvent.selectedObj;
var isIssueIndex, isMRIndex, page, boardsModel;
var fadeOutLoader = () => {
......
......@@ -4,7 +4,7 @@ import initFlyOutNav from './fly_out_nav';
function hideEndFade($scrollingTabs) {
$scrollingTabs.each(function scrollTabsLoop() {
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'));
});
}
......
......@@ -418,6 +418,16 @@ export const convertObjectPropsToCamelCase = (obj = {}) => {
export const imagePath = imgUrl => `${gon.asset_host || ''}${gon.relative_url_root || ''}/assets/${imgUrl}`;
export const addSelectOnFocusBehaviour = (selector = '.js-select-on-focus') => {
// Click a .js-select-on-focus field, select the contents
// Prevent a mouseup event from deselecting the input
$(selector).on('focusin', function selectOnFocusCallback() {
$(this).select().one('mouseup', (e) => {
e.preventDefault();
});
});
};
window.gl = window.gl || {};
window.gl.utils = {
...(window.gl.utils || {}),
......
......@@ -138,7 +138,7 @@ textUtils.init = function(form) {
return $('.js-md', form).off('click').on('click', function() {
var $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'));
});
};
......
......@@ -83,7 +83,7 @@ LineHighlighter.prototype.clickHandler = function(event) {
var current, lineNumber, range;
event.preventDefault();
this.clearHighlight();
lineNumber = $(event.target).closest('a').data('line-number');
lineNumber = $(event.target).closest('a').data('lineNumber');
current = this.hashToRange(this._hash);
if (!(current[0] && event.shiftKey)) {
// If there's no current selection, or there is but Shift wasn't held,
......
......@@ -10,7 +10,7 @@ window.jQuery = jQuery;
window.$ = jQuery;
// lib/utils
import { handleLocationHash } from './lib/utils/common_utils';
import { handleLocationHash, addSelectOnFocusBehaviour } from './lib/utils/common_utils';
import { localTimeAgo } from './lib/utils/datetime_utility';
import { getLocationHash, visitUrl } from './lib/utils/url_utility';
......@@ -61,7 +61,7 @@ gl.lazyLoader = new LazyLoader({
observerNode: '#content-body',
});
$(() => {
document.addEventListener('DOMContentLoaded', () => {
const $body = $('body');
const $document = $(document);
const $window = $(window);
......@@ -104,13 +104,7 @@ $(() => {
return true;
});
// Click a .js-select-on-focus field, select the contents
// Prevent a mouseup event from deselecting the input
$('.js-select-on-focus').on('focusin', function selectOnFocusCallback() {
$(this).select().one('mouseup', (e) => {
e.preventDefault();
});
});
addSelectOnFocusBehaviour('.js-select-on-focus');
$('.remove-row').on('ajax:success', function removeRowAjaxSuccessCallback() {
$(this).tooltip('destroy')
......@@ -220,7 +214,7 @@ $(() => {
$document.on('click', '.js-confirm-danger', (e) => {
const btn = $(e.target);
const form = btn.closest('form');
const text = btn.data('confirm-danger-message');
const text = btn.data('confirmDangerMessage');
e.preventDefault();
// eslint-disable-next-line no-new
......
......@@ -19,7 +19,7 @@ export default class Members {
isSelectable(selected, $el) {
return !$el.hasClass('is-active');
},
fieldName: $btn.data('field-name'),
fieldName: $btn.data('fieldName'),
id(selected, $el) {
return $el.data('id');
},
......@@ -51,7 +51,7 @@ export default class Members {
}
// eslint-disable-next-line class-methods-use-this
getMemberListItems($el) {
const $memberListItem = $el.is('.member') ? $el : $(`#${$el.data('el-id')}`);
const $memberListItem = $el.is('.member') ? $el : $(`#${$el.data('elId')}`);
return {
$memberListItem,
......
......@@ -361,7 +361,7 @@ export default class MergeRequestTabs {
}
diffViewType() {
return $('.inline-parallel-buttons a.active').data('view-type');
return $('.inline-parallel-buttons a.active').data('viewType');
}
isDiffAction(action) {
......
......@@ -24,19 +24,19 @@ export default class MilestoneSelect {
$els.each((i, dropdown) => {
let collapsedSidebarLabelTemplate, milestoneLinkNoneTemplate, milestoneLinkTemplate, selectedMilestone, selectedMilestoneDefault;
const $dropdown = $(dropdown);
const projectId = $dropdown.data('project-id');
const projectId = $dropdown.data('projectId');
const milestonesUrl = $dropdown.data('milestones');
const issueUpdateURL = $dropdown.data('issueUpdate');
const showNo = $dropdown.data('show-no');
const showAny = $dropdown.data('show-any');
const showNo = $dropdown.data('showNo');
const showAny = $dropdown.data('showAny');
const showMenuAbove = $dropdown.data('showMenuAbove');
const showUpcoming = $dropdown.data('show-upcoming');
const showStarted = $dropdown.data('show-started');
const useId = $dropdown.data('use-id');
const defaultLabel = $dropdown.data('default-label');
const defaultNo = $dropdown.data('default-no');
const issuableId = $dropdown.data('issuable-id');
const abilityName = $dropdown.data('ability-name');
const showUpcoming = $dropdown.data('showUpcoming');
const showStarted = $dropdown.data('showStarted');
const useId = $dropdown.data('useId');
const defaultLabel = $dropdown.data('defaultLabel');
const defaultNo = $dropdown.data('defaultNo');
const issuableId = $dropdown.data('issuableId');
const abilityName = $dropdown.data('abilityName');
const $selectBox = $dropdown.closest('.selectbox');
const $block = $selectBox.closest('.block');
const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
......@@ -114,7 +114,7 @@ export default class MilestoneSelect {
}
},
defaultLabel: defaultLabel,
fieldName: $dropdown.data('field-name'),
fieldName: $dropdown.data('fieldName'),
text: milestone => _.escape(milestone.title),
id: (milestone) => {
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
......@@ -166,7 +166,7 @@ export default class MilestoneSelect {
}
if (boardsStore) {
boardsStore[$dropdown.data('field-name')] = selected.name;
boardsStore[$dropdown.data('fieldName')] = selected.name;
e.preventDefault();
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
return Issuable.filterResults($dropdown.closest('form'));
......
......@@ -219,7 +219,7 @@ export default class Notes {
}
editNote = $textarea.closest('.note');
if (editNote.length) {
originalText = $textarea.closest('form').data('original-note');
originalText = $textarea.closest('form').data('originalNote');
newText = $textarea.val();
if (originalText !== newText) {
if (!confirm('Are you sure you want to cancel editing this comment?')) {
......@@ -609,9 +609,9 @@ export default class Notes {
*/
addDiscussionNote($form, note, isNewDiffComment) {
if ($form.attr('data-resolve-all') != null) {
var projectPath = $form.data('project-path');
var discussionId = $form.data('discussion-id');
var mergeRequestId = $form.data('noteable-iid');
var projectPath = $form.data('projectPath');
var discussionId = $form.data('discussionId');
var mergeRequestId = $form.data('noteableIid');
if (ResolveService != null) {
ResolveService.toggleResolveForDiscussion(mergeRequestId, discussionId);
......@@ -751,7 +751,7 @@ export default class Notes {
form.removeClass('current-note-edit-form');
form.find('.js-finish-edit-warning').hide();
// 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;
$note = $(el);
$notes = $note.closest('.discussion-notes');
const discussionId = $('.notes', $notes).data('discussion-id');
const discussionId = $('.notes', $notes).data('discussionId');
if (typeof gl.diffNotesCompileComponents !== 'undefined') {
if (gl.diffNoteApps[noteElId]) {
......@@ -897,7 +897,7 @@ export default class Notes {
// DiffNote
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-new-discussion').remove();
this.setupNoteForm(form);
......@@ -1037,7 +1037,7 @@ export default class Notes {
removeDiscussionNoteForm(form) {
var glForm, row;
row = form.closest('tr');
glForm = form.data('gl-form');
glForm = form.data('glForm');
glForm.destroy();
form.find('.js-note-text').data('autosave').reset();
// show the reply button (will only work for replies)
......@@ -1122,8 +1122,8 @@ export default class Notes {
return discardbtn.show();
}
} else {
reopentext = reopenbtn.data('original-text');
closetext = closebtn.data('original-text');
reopentext = reopenbtn.data('originalText');
closetext = closebtn.data('originalText');
if (reopenbtn.text() !== reopentext) {
reopenbtn.text(reopentext);
}
......@@ -1150,9 +1150,9 @@ export default class Notes {
var $originalContentEl = $note.find('.original-note-content');
var originalContent = $originalContentEl.text().trim();
var postUrl = $originalContentEl.data('post-url');
var targetId = $originalContentEl.data('target-id');
var targetType = $originalContentEl.data('target-type');
var postUrl = $originalContentEl.data('postUrl');
var targetId = $originalContentEl.data('targetId');
var targetType = $originalContentEl.data('targetType');
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 (isDiscussionResolve) {
$form
.attr('data-discussion-id', $submitBtn.data('discussion-id'))
.attr('data-discussion-id', $submitBtn.data('discussionId'))
.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
......@@ -1587,7 +1587,7 @@ export default class Notes {
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();
});
return $closeBtn.text($closeBtn.data('original-text'));
return $closeBtn.text($closeBtn.data('originalText'));
}
}
......
......@@ -3,11 +3,11 @@ import Flash from './flash';
export default function notificationsDropdown() {
$(document).on('click', '.update-notification', function updateNotificationCallback(e) {
e.preventDefault();
if ($(this).is('.is-active') && $(this).data('notification-level') === 'custom') {
if ($(this).is('.is-active') && $(this).data('notificationLevel') === 'custom') {
return;
}
const notificationLevel = $(this).data('notification-level');
const notificationLevel = $(this).data('notificationLevel');
const form = $(this).parents('.notification-form:first');
form.find('.js-notification-loading').toggleClass('fa-bell fa-spin fa-spinner');
......
......@@ -56,7 +56,7 @@ export default {
},
initLoadMore() {
$(document).unbind('scroll');
$(document).off('scroll');
$(document).endlessScroll({
bottomPixels: ENDLESS_SCROLL_BOTTOM_PX,
fireDelay: ENDLESS_SCROLL_FIRE_DELAY_MS,
......
......@@ -15,21 +15,21 @@ export default class AbuseReports {
const $messageCellElement = $(this);
const reportMessage = $messageCellElement.text();
if (reportMessage.length > MAX_MESSAGE_LENGTH) {
$messageCellElement.data('original-message', reportMessage);
$messageCellElement.data('message-truncated', 'true');
$messageCellElement.data('originalMessage', reportMessage);
$messageCellElement.data('messageTruncated', 'true');
$messageCellElement.text(truncate(reportMessage, MAX_MESSAGE_LENGTH));
}
}
toggleMessageTruncation() {
const $messageCellElement = $(this);
const originalMessage = $messageCellElement.data('original-message');
const originalMessage = $messageCellElement.data('originalMessage');
if (!originalMessage) return;
if ($messageCellElement.data('message-truncated') === 'true') {
$messageCellElement.data('message-truncated', 'false');
if ($messageCellElement.data('messageTruncated') === 'true') {
$messageCellElement.data('messageTruncated', 'false');
$messageCellElement.text(originalMessage);
} else {
$messageCellElement.data('message-truncated', 'true');
$messageCellElement.data('messageTruncated', 'true');
$messageCellElement.text(`${originalMessage.substr(0, (MAX_MESSAGE_LENGTH - 3))}...`);
}
}
......
......@@ -16,9 +16,9 @@ export default function adminInit() {
$('input#user_force_random_password').on('change', function randomPasswordClick() {
const $elems = $('#user_password, #user_password_confirmation');
if ($(this).attr('checked')) {
$elems.val('').attr('disabled', true);
$elems.val('').prop('disabled', true);
} else {
$elems.removeAttr('disabled');
$elems.prop('disabled', false);
}
});
......
......@@ -14,7 +14,7 @@ export default function initBroadcastMessagesForm() {
$('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() {
const message = $(this).val();
......
import UserCallout from '../../../../user_callout';
import UserCallout from '~/user_callout';
export default () => new UserCallout();
document.addEventListener('DOMContentLoaded', () => new UserCallout());
import groupAvatar from '../../../../group_avatar';
import groupAvatar from '~/group_avatar';
export default () => groupAvatar();
document.addEventListener('DOMContentLoaded', groupAvatar);
......@@ -2,8 +2,8 @@ import BindInOut from '../../../../behaviors/bind_in_out';
import Group from '../../../../group';
import groupAvatar from '../../../../group_avatar';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
BindInOut.initAll();
new Group(); // eslint-disable-line no-new
groupAvatar();
};
});
import DueDateSelectors from '../../../due_date_select';
import DueDateSelectors from '~/due_date_select';
export default () => new DueDateSelectors();
document.addEventListener('DOMContentLoaded', () => new DueDateSelectors());
import initAdmin from './admin';
export default () => initAdmin();
document.addEventListener('DOMContentLoaded', initAdmin);
import Vue from 'vue';
import Translate from '~/vue_shared/translate';
import stopJobsModal from './components/stop_jobs_modal.vue';
Vue.use(Translate);
export default () => {
document.addEventListener('DOMContentLoaded', () => {
const stopJobsButton = document.getElementById('stop-jobs-button');
if (stopJobsButton) {
// eslint-disable-next-line no-new
......@@ -27,4 +25,4 @@ export default () => {
},
});
}
};
});
......@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteProjectModal from './components/delete_project_modal.vue';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate);
const deleteProjectModalEl = document.getElementById('delete-project-modal');
......@@ -34,4 +34,4 @@ export default () => {
deleteModal.projectName = buttonProps.projectName;
}
});
};
});
......@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteUserModal from './components/delete_user_modal.vue';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate);
const deleteUserModalEl = document.getElementById('delete-user-modal');
......@@ -40,4 +40,4 @@ export default () => {
deleteModal.username = buttonProps.username;
}
});
};
});
import CILintEditor from '../ci_lint_editor';
document.addEventListener('DOMContentLoaded', () => new CILintEditor());
import CILintEditor from './ci_lint_editor';
export default () => new CILintEditor();
import CILintEditor from '../ci_lint_editor';
document.addEventListener('DOMContentLoaded', () => new CILintEditor());
import Activities from '~/activities';
export default () => new Activities();
document.addEventListener('DOMContentLoaded', () => new Activities());
import initGroupsList from '../../../../groups';
import initGroupsList from '~/groups';
export default () => {
initGroupsList();
};
document.addEventListener('DOMContentLoaded', initGroupsList);
import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
projectSelect();
initLegacyFilters();
};
});
import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
projectSelect();
initLegacyFilters();
};
});
import Milestone from '~/milestone';
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 Sidebar(); // eslint-disable-line no-new
};
new MountMilestoneSidebar(); // eslint-disable-line no-new
});
import ProjectsList from '~/projects_list';
export default () => new ProjectsList();
document.addEventListener('DOMContentLoaded', () => new ProjectsList());
import Todos from './todos';
export default () => new Todos();
document.addEventListener('DOMContentLoaded', () => new Todos());
......@@ -2,7 +2,7 @@ import GroupsList from '~/groups_list';
import Landing from '~/landing';
import initGroupsList from '../../../groups';
export default function () {
document.addEventListener('DOMContentLoaded', () => {
new GroupsList(); // eslint-disable-line no-new
initGroupsList();
const landingElement = document.querySelector('.js-explore-groups-landing');
......@@ -13,4 +13,4 @@ export default function () {
'explore_groups_landing_dismissed',
);
exploreGroupsLanding.toggle();
}
});
import ProjectsList from '~/projects_list';
export default () => new ProjectsList();
document.addEventListener('DOMContentLoaded', () => new ProjectsList());
import Activities from '~/activities';
export default () => new Activities();
document.addEventListener('DOMContentLoaded', () => new Activities());
import groupAvatar from '~/group_avatar';
import TransferDropdown from '~/groups/transfer_dropdown';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
groupAvatar();
new TransferDropdown(); // eslint-disable-line no-new
};
});
......@@ -4,8 +4,8 @@ import memberExpirationDate from '~/member_expiration_date';
import Members from '~/members';
import UsersSelect from '~/users_select';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
memberExpirationDate();
new Members();
new UsersSelect();
};
});
......@@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
});
projectSelect();
};
});
import Labels from '~/labels';
export default () => new Labels();
document.addEventListener('DOMContentLoaded', () => new Labels());
import initLabels from '~/init_labels';
export default initLabels;
document.addEventListener('DOMContentLoaded', initLabels);
import Labels from '~/labels';
export default () => new Labels();
document.addEventListener('DOMContentLoaded', () => new Labels());
......@@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
});
projectSelect();
};
});
import initForm from '../../../../shared/milestones/form';
export default () => initForm(false);
document.addEventListener('DOMContentLoaded', () => initForm(false));
import initForm from '../../../../shared/milestones/form';
export default () => initForm(false);
document.addEventListener('DOMContentLoaded', () => initForm(false));
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
export default initMilestonesShow;
document.addEventListener('DOMContentLoaded', initMilestonesShow);
......@@ -2,8 +2,8 @@ import BindInOut from '~/behaviors/bind_in_out';
import Group from '~/group';
import groupAvatar from '~/group_avatar';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
BindInOut.initAll();
new Group(); // eslint-disable-line no-new
groupAvatar();
};
});
import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
export default () => {
document.addEventListener('DOMContentLoaded', () => {
const variableListEl = document.querySelector('.js-ci-variable-list-section');
// eslint-disable-next-line no-new
new AjaxVariableList({
......@@ -9,4 +9,4 @@ export default () => {
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
saveEndpoint: variableListEl.dataset.saveEndpoint,
});
};
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment