summaryrefslogtreecommitdiff
path: root/app/assets
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/LabelManager.js115
-rw-r--r--app/assets/javascripts/LabelManager.js.es6106
-rw-r--r--app/assets/javascripts/activities.js12
-rw-r--r--app/assets/javascripts/api.js12
-rw-r--r--app/assets/javascripts/blob/blob_ci_yaml.js46
-rw-r--r--app/assets/javascripts/blob/blob_ci_yaml.js.es640
-rw-r--r--app/assets/javascripts/blob/blob_gitignore_selector.js2
-rw-r--r--app/assets/javascripts/blob/blob_license_selector.js2
-rw-r--r--app/assets/javascripts/blob/blob_license_selectors.js25
-rw-r--r--app/assets/javascripts/blob/blob_license_selectors.js.es621
-rw-r--r--app/assets/javascripts/blob/template_selector.js100
-rw-r--r--app/assets/javascripts/blob/template_selector.js.es6102
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js4
-rw-r--r--app/assets/javascripts/boards/components/board.js.es68
-rw-r--r--app/assets/javascripts/boards/components/board_blank_state.js.es66
-rw-r--r--app/assets/javascripts/boards/components/board_list.js.es69
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.js.es658
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js.es63
-rw-r--r--app/assets/javascripts/boards/mixins/sortable_default_options.js.es62
-rw-r--r--app/assets/javascripts/boards/models/list.js.es611
-rw-r--r--app/assets/javascripts/boards/services/board_service.js.es66
-rw-r--r--app/assets/javascripts/build.js2
-rw-r--r--app/assets/javascripts/copy_to_clipboard.js18
-rw-r--r--app/assets/javascripts/create_label.js.es69
-rw-r--r--app/assets/javascripts/diff.js7
-rw-r--r--app/assets/javascripts/dispatcher.js16
-rw-r--r--app/assets/javascripts/gl_dropdown.js13
-rw-r--r--app/assets/javascripts/groups_select.js5
-rw-r--r--app/assets/javascripts/issuable.js.es61
-rw-r--r--app/assets/javascripts/issues-bulk-assignment.js.es6 (renamed from app/assets/javascripts/issues-bulk-assignment.js)128
-rw-r--r--app/assets/javascripts/labels_select.js132
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js5
-rw-r--r--app/assets/javascripts/merge_conflict_data_provider.js.es616
-rw-r--r--app/assets/javascripts/merge_conflict_resolver.js.es65
-rw-r--r--app/assets/javascripts/merge_request.js9
-rw-r--r--app/assets/javascripts/merge_request_tabs.js55
-rw-r--r--app/assets/javascripts/milestone_select.js25
-rw-r--r--app/assets/javascripts/pipeline.js.es611
-rw-r--r--app/assets/javascripts/profile/gl_crop.js.es6 (renamed from app/assets/javascripts/profile/gl_crop.js)123
-rw-r--r--app/assets/javascripts/profile/profile.js106
-rw-r--r--app/assets/javascripts/profile/profile.js.es6100
-rw-r--r--app/assets/javascripts/project_select.js4
-rw-r--r--app/assets/javascripts/search.js2
-rw-r--r--app/assets/javascripts/search_autocomplete.js.es6 (renamed from app/assets/javascripts/search_autocomplete.js)158
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js.es622
-rw-r--r--app/assets/javascripts/templates/issuable_template_selectors.js.es612
-rw-r--r--app/assets/javascripts/todos.js.es6 (renamed from app/assets/javascripts/todos.js)143
-rw-r--r--app/assets/javascripts/user.js.es610
-rw-r--r--app/assets/javascripts/user_tabs.js188
-rw-r--r--app/assets/javascripts/user_tabs.js.es6157
-rw-r--r--app/assets/javascripts/users_select.js27
-rw-r--r--app/assets/stylesheets/framework/buttons.scss9
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss23
-rw-r--r--app/assets/stylesheets/framework/flash.scss9
-rw-r--r--app/assets/stylesheets/framework/forms.scss4
-rw-r--r--app/assets/stylesheets/framework/header.scss4
-rw-r--r--app/assets/stylesheets/framework/selects.scss9
-rw-r--r--app/assets/stylesheets/pages/boards.scss32
-rw-r--r--app/assets/stylesheets/pages/environments.scss33
-rw-r--r--app/assets/stylesheets/pages/labels.scss7
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss7
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss22
-rw-r--r--app/assets/stylesheets/pages/profile.scss25
-rw-r--r--app/assets/stylesheets/pages/projects.scss3
-rw-r--r--app/assets/stylesheets/pages/todos.scss19
65 files changed, 1315 insertions, 1090 deletions
diff --git a/app/assets/javascripts/LabelManager.js b/app/assets/javascripts/LabelManager.js
deleted file mode 100644
index d4a4c7abaa1..00000000000
--- a/app/assets/javascripts/LabelManager.js
+++ /dev/null
@@ -1,115 +0,0 @@
-(function() {
- this.LabelManager = (function() {
- LabelManager.prototype.errorMessage = 'Unable to update label prioritization at this time';
-
- function LabelManager(opts) {
- // Defaults
- var ref, ref1, ref2;
- if (opts == null) {
- opts = {};
- }
- this.togglePriorityButton = (ref = opts.togglePriorityButton) != null ? ref : $('.js-toggle-priority'), this.prioritizedLabels = (ref1 = opts.prioritizedLabels) != null ? ref1 : $('.js-prioritized-labels'), this.otherLabels = (ref2 = opts.otherLabels) != null ? ref2 : $('.js-other-labels');
- this.prioritizedLabels.sortable({
- items: 'li',
- placeholder: 'list-placeholder',
- axis: 'y',
- update: this.onPrioritySortUpdate.bind(this)
- });
- this.bindEvents();
- }
-
- LabelManager.prototype.bindEvents = function() {
- return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
- };
-
- LabelManager.prototype.onTogglePriorityClick = function(e) {
- var $btn, $label, $tooltip, _this, action;
- e.preventDefault();
- _this = e.data;
- $btn = $(e.currentTarget);
- $label = $("#" + ($btn.data('domId')));
- action = $btn.parents('.js-prioritized-labels').length ? 'remove' : 'add';
- // Make sure tooltip will hide
- $tooltip = $("#" + ($btn.find('.has-tooltip:visible').attr('aria-describedby')));
- $tooltip.tooltip('destroy');
- return _this.toggleLabelPriority($label, action);
- };
-
- LabelManager.prototype.toggleLabelPriority = function($label, action, persistState) {
- var $from, $target, _this, url, xhr;
- if (persistState == null) {
- persistState = true;
- }
- _this = this;
- url = $label.find('.js-toggle-priority').data('url');
- $target = this.prioritizedLabels;
- $from = this.otherLabels;
- // Optimistic update
- if (action === 'remove') {
- $target = this.otherLabels;
- $from = this.prioritizedLabels;
- }
- if ($from.find('li').length === 1) {
- $from.find('.empty-message').removeClass('hidden');
- }
- if (!$target.find('li').length) {
- $target.find('.empty-message').addClass('hidden');
- }
- $label.detach().appendTo($target);
- // Return if we are not persisting state
- if (!persistState) {
- return;
- }
- if (action === 'remove') {
- xhr = $.ajax({
- url: url,
- type: 'DELETE'
- });
- // Restore empty message
- if (!$from.find('li').length) {
- $from.find('.empty-message').removeClass('hidden');
- }
- } else {
- xhr = this.savePrioritySort($label, action);
- }
- return xhr.fail(this.rollbackLabelPosition.bind(this, $label, action));
- };
-
- LabelManager.prototype.onPrioritySortUpdate = function() {
- var xhr;
- xhr = this.savePrioritySort();
- return xhr.fail(function() {
- return new Flash(this.errorMessage, 'alert');
- });
- };
-
- LabelManager.prototype.savePrioritySort = function() {
- return $.post({
- url: this.prioritizedLabels.data('url'),
- data: {
- label_ids: this.getSortedLabelsIds()
- }
- });
- };
-
- LabelManager.prototype.rollbackLabelPosition = function($label, originalAction) {
- var action;
- action = originalAction === 'remove' ? 'add' : 'remove';
- this.toggleLabelPriority($label, action, false);
- return new Flash(this.errorMessage, 'alert');
- };
-
- LabelManager.prototype.getSortedLabelsIds = function() {
- var sortedIds;
- sortedIds = [];
- this.prioritizedLabels.find('li').each(function() {
- return sortedIds.push($(this).data('id'));
- });
- return sortedIds;
- };
-
- return LabelManager;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/LabelManager.js.es6 b/app/assets/javascripts/LabelManager.js.es6
new file mode 100644
index 00000000000..bc68e53504f
--- /dev/null
+++ b/app/assets/javascripts/LabelManager.js.es6
@@ -0,0 +1,106 @@
+((global) => {
+
+ class LabelManager {
+ constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
+ this.togglePriorityButton = togglePriorityButton || $('.js-toggle-priority');
+ this.prioritizedLabels = prioritizedLabels || $('.js-prioritized-labels');
+ this.otherLabels = otherLabels || $('.js-other-labels');
+ this.errorMessage = 'Unable to update label prioritization at this time';
+ this.prioritizedLabels.sortable({
+ items: 'li',
+ placeholder: 'list-placeholder',
+ axis: 'y',
+ update: this.onPrioritySortUpdate.bind(this)
+ });
+ this.bindEvents();
+ }
+
+ bindEvents() {
+ return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
+ }
+
+ onTogglePriorityClick(e) {
+ e.preventDefault();
+ const _this = e.data;
+ const $btn = $(e.currentTarget);
+ const $label = $(`#${$btn.data('domId')}`);
+ const action = $btn.parents('.js-prioritized-labels').length ? 'remove' : 'add';
+ const $tooltip = $(`#${$btn.find('.has-tooltip:visible').attr('aria-describedby')}`);
+ $tooltip.tooltip('destroy');
+ return _this.toggleLabelPriority($label, action);
+ }
+
+ toggleLabelPriority($label, action, persistState) {
+ if (persistState == null) {
+ persistState = true;
+ }
+ let xhr;
+ const _this = this;
+ const url = $label.find('.js-toggle-priority').data('url');
+ let $target = this.prioritizedLabels;
+ let $from = this.otherLabels;
+ if (action === 'remove') {
+ $target = this.otherLabels;
+ $from = this.prioritizedLabels;
+ }
+ if ($from.find('li').length === 1) {
+ $from.find('.empty-message').removeClass('hidden');
+ }
+ if (!$target.find('li').length) {
+ $target.find('.empty-message').addClass('hidden');
+ }
+ $label.detach().appendTo($target);
+ // Return if we are not persisting state
+ if (!persistState) {
+ return;
+ }
+ if (action === 'remove') {
+ xhr = $.ajax({
+ url,
+ type: 'DELETE'
+ });
+ // Restore empty message
+ if (!$from.find('li').length) {
+ $from.find('.empty-message').removeClass('hidden');
+ }
+ } else {
+ xhr = this.savePrioritySort($label, action);
+ }
+ return xhr.fail(this.rollbackLabelPosition.bind(this, $label, action));
+ }
+
+ onPrioritySortUpdate() {
+ const xhr = this.savePrioritySort();
+ return xhr.fail(function() {
+ return new Flash(this.errorMessage, 'alert');
+ });
+ }
+
+ savePrioritySort() {
+ return $.post({
+ url: this.prioritizedLabels.data('url'),
+ data: {
+ label_ids: this.getSortedLabelsIds()
+ }
+ });
+ }
+
+ rollbackLabelPosition($label, originalAction) {
+ const action = originalAction === 'remove' ? 'add' : 'remove';
+ this.toggleLabelPriority($label, action, false);
+ return new Flash(this.errorMessage, 'alert');
+ }
+
+ getSortedLabelsIds() {
+ const sortedIds = [];
+ this.prioritizedLabels.find('li').each(function() {
+ sortedIds.push($(this).data('id'));
+ });
+ return sortedIds;
+ }
+ }
+
+ gl.LabelManager = LabelManager;
+
+})(window.gl || (window.gl = {}));
+
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index d5e11e22be5..f4f8cf04184 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -21,16 +21,14 @@
};
Activities.prototype.toggleFilter = function(sender) {
- var event_filters, filter;
+ var filter = sender.attr("id").split("_")[0];
+
$('.event-filter .active').removeClass("active");
- event_filters = $.cookie("event_filter");
- filter = sender.attr("id").split("_")[0];
- $.cookie("event_filter", (event_filters !== filter ? filter : ""), {
+ $.cookie("event_filter", filter, {
path: gon.relative_url_root || '/'
});
- if (event_filters !== filter) {
- return sender.closest('li').toggleClass("active");
- }
+
+ sender.closest('li').toggleClass("active");
};
return Activities;
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 1cd2302111e..599331df3f5 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -5,7 +5,7 @@
namespacesPath: "/api/:version/namespaces.json",
groupProjectsPath: "/api/:version/groups/:id/projects.json",
projectsPath: "/api/:version/projects.json?simple=true",
- labelsPath: "/api/:version/projects/:id/labels",
+ labelsPath: "/:namespace_path/:project_path/labels",
licensePath: "/api/:version/licenses/:key",
gitignorePath: "/api/:version/gitignores/:key",
gitlabCiYmlPath: "/api/:version/gitlab_ci_ymls/:key",
@@ -23,12 +23,13 @@
},
// Return groups list. Filtered by query
// Only active groups retrieved
- groups: function(query, skip_ldap, callback) {
+ groups: function(query, skip_ldap, skip_groups, callback) {
var url = Api.buildUrl(Api.groupsPath);
return $.ajax({
url: url,
data: {
search: query,
+ skip_groups: skip_groups,
per_page: 20
},
dataType: "json"
@@ -65,13 +66,14 @@
return callback(projects);
});
},
- newLabel: function(project_id, data, callback) {
+ newLabel: function(namespace_path, project_path, data, callback) {
var url = Api.buildUrl(Api.labelsPath)
- .replace(':id', project_id);
+ .replace(':namespace_path', namespace_path)
+ .replace(':project_path', project_path);
return $.ajax({
url: url,
type: "POST",
- data: data,
+ data: {'label': data},
dataType: "json"
}).done(function(label) {
return callback(label);
diff --git a/app/assets/javascripts/blob/blob_ci_yaml.js b/app/assets/javascripts/blob/blob_ci_yaml.js
deleted file mode 100644
index 68758574967..00000000000
--- a/app/assets/javascripts/blob/blob_ci_yaml.js
+++ /dev/null
@@ -1,46 +0,0 @@
-
-/*= require blob/template_selector */
-
-(function() {
- var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
- hasProp = {}.hasOwnProperty;
-
- this.BlobCiYamlSelector = (function(superClass) {
- extend(BlobCiYamlSelector, superClass);
-
- function BlobCiYamlSelector() {
- return BlobCiYamlSelector.__super__.constructor.apply(this, arguments);
- }
-
- BlobCiYamlSelector.prototype.requestFile = function(query) {
- return Api.gitlabCiYml(query.name, this.requestFileSuccess.bind(this));
- };
-
- return BlobCiYamlSelector;
-
- })(TemplateSelector);
-
- this.BlobCiYamlSelectors = (function() {
- function BlobCiYamlSelectors(opts) {
- var ref;
- this.$dropdowns = (ref = opts.$dropdowns) != null ? ref : $('.js-gitlab-ci-yml-selector'), this.editor = opts.editor;
- this.$dropdowns.each((function(_this) {
- return function(i, dropdown) {
- var $dropdown;
- $dropdown = $(dropdown);
- return new BlobCiYamlSelector({
- pattern: /(.gitlab-ci.yml)/,
- data: $dropdown.data('data'),
- wrapper: $dropdown.closest('.js-gitlab-ci-yml-selector-wrap'),
- dropdown: $dropdown,
- editor: _this.editor
- });
- };
- })(this));
- }
-
- return BlobCiYamlSelectors;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/blob/blob_ci_yaml.js.es6 b/app/assets/javascripts/blob/blob_ci_yaml.js.es6
new file mode 100644
index 00000000000..d6ea4f84f57
--- /dev/null
+++ b/app/assets/javascripts/blob/blob_ci_yaml.js.es6
@@ -0,0 +1,40 @@
+/*= require blob/template_selector */
+((global) => {
+
+ class BlobCiYamlSelector extends gl.TemplateSelector {
+ requestFile(query) {
+ return Api.gitlabCiYml(query.name, this.requestFileSuccess.bind(this));
+ }
+
+ requestFileSuccess(file) {
+ return super.requestFileSuccess(file);
+ }
+ }
+
+ global.BlobCiYamlSelector = BlobCiYamlSelector;
+
+ class BlobCiYamlSelectors {
+ constructor({ editor, $dropdowns } = {}) {
+ this.editor = editor;
+ this.$dropdowns = $dropdowns || $('.js-gitlab-ci-yml-selector');
+ this.initSelectors();
+ }
+
+ initSelectors() {
+ const editor = this.editor;
+ this.$dropdowns.each((i, dropdown) => {
+ const $dropdown = $(dropdown);
+ return new BlobCiYamlSelector({
+ editor,
+ pattern: /(.gitlab-ci.yml)/,
+ data: $dropdown.data('data'),
+ wrapper: $dropdown.closest('.js-gitlab-ci-yml-selector-wrap'),
+ dropdown: $dropdown
+ });
+ });
+ }
+ }
+
+ global.BlobCiYamlSelectors = BlobCiYamlSelectors;
+
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/blob/blob_gitignore_selector.js b/app/assets/javascripts/blob/blob_gitignore_selector.js
index 54a09e919f8..cd746b05cf6 100644
--- a/app/assets/javascripts/blob/blob_gitignore_selector.js
+++ b/app/assets/javascripts/blob/blob_gitignore_selector.js
@@ -18,6 +18,6 @@
return BlobGitignoreSelector;
- })(TemplateSelector);
+ })(gl.TemplateSelector);
}).call(this);
diff --git a/app/assets/javascripts/blob/blob_license_selector.js b/app/assets/javascripts/blob/blob_license_selector.js
index 9a8ef08f4e5..2701df3e6de 100644
--- a/app/assets/javascripts/blob/blob_license_selector.js
+++ b/app/assets/javascripts/blob/blob_license_selector.js
@@ -23,6 +23,6 @@
return BlobLicenseSelector;
- })(TemplateSelector);
+ })(gl.TemplateSelector);
}).call(this);
diff --git a/app/assets/javascripts/blob/blob_license_selectors.js b/app/assets/javascripts/blob/blob_license_selectors.js
deleted file mode 100644
index 39237705e8d..00000000000
--- a/app/assets/javascripts/blob/blob_license_selectors.js
+++ /dev/null
@@ -1,25 +0,0 @@
-(function() {
- this.BlobLicenseSelectors = (function() {
- function BlobLicenseSelectors(opts) {
- var ref;
- this.$dropdowns = (ref = opts.$dropdowns) != null ? ref : $('.js-license-selector'), this.editor = opts.editor;
- this.$dropdowns.each((function(_this) {
- return function(i, dropdown) {
- var $dropdown;
- $dropdown = $(dropdown);
- return new BlobLicenseSelector({
- pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i,
- data: $dropdown.data('data'),
- wrapper: $dropdown.closest('.js-license-selector-wrap'),
- dropdown: $dropdown,
- editor: _this.editor
- });
- };
- })(this));
- }
-
- return BlobLicenseSelectors;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/blob/blob_license_selectors.js.es6 b/app/assets/javascripts/blob/blob_license_selectors.js.es6
new file mode 100644
index 00000000000..153ed457559
--- /dev/null
+++ b/app/assets/javascripts/blob/blob_license_selectors.js.es6
@@ -0,0 +1,21 @@
+((global) => {
+ class BlobLicenseSelectors {
+ constructor({ $dropdowns, editor }) {
+ this.$dropdowns = $('.js-license-selector');
+ this.editor = editor;
+ this.$dropdowns.each((i, dropdown) => {
+ const $dropdown = $(dropdown);
+ return new BlobLicenseSelector({
+ editor,
+ pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i,
+ data: $dropdown.data('data'),
+ wrapper: $dropdown.closest('.js-license-selector-wrap'),
+ dropdown: $dropdown,
+ });
+ });
+ }
+ }
+
+ global.BlobLicenseSelectors = BlobLicenseSelectors;
+
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/blob/template_selector.js b/app/assets/javascripts/blob/template_selector.js
deleted file mode 100644
index 95352164d76..00000000000
--- a/app/assets/javascripts/blob/template_selector.js
+++ /dev/null
@@ -1,100 +0,0 @@
-(function() {
- var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
-
- this.TemplateSelector = (function() {
- function TemplateSelector(opts) {
- var ref;
- if (opts == null) {
- opts = {};
- }
- this.onClick = bind(this.onClick, this);
- this.dropdown = opts.dropdown, this.data = opts.data, this.pattern = opts.pattern, this.wrapper = opts.wrapper, this.editor = opts.editor, this.fileEndpoint = opts.fileEndpoint, this.$input = (ref = opts.$input) != null ? ref : $('#file_name');
- this.dropdownIcon = $('.fa-chevron-down', this.dropdown);
- this.buildDropdown();
- this.bindEvents();
- this.onFilenameUpdate();
-
- this.autosizeUpdateEvent = document.createEvent('Event');
- this.autosizeUpdateEvent.initEvent('autosize:update', true, false);
- }
-
- TemplateSelector.prototype.buildDropdown = function() {
- return this.dropdown.glDropdown({
- data: this.data,
- filterable: true,
- selectable: true,
- toggleLabel: this.toggleLabel,
- search: {
- fields: ['name']
- },
- clicked: this.onClick,
- text: function(item) {
- return item.name;
- }
- });
- };
-
- TemplateSelector.prototype.bindEvents = function() {
- return this.$input.on('keyup blur', (function(_this) {
- return function(e) {
- return _this.onFilenameUpdate();
- };
- })(this));
- };
-
- TemplateSelector.prototype.toggleLabel = function(item) {
- return item.name;
- };
-
- TemplateSelector.prototype.onFilenameUpdate = function() {
- var filenameMatches;
- if (!this.$input.length) {
- return;
- }
- filenameMatches = this.pattern.test(this.$input.val().trim());
- if (!filenameMatches) {
- this.wrapper.addClass('hidden');
- return;
- }
- return this.wrapper.removeClass('hidden');
- };
-
- TemplateSelector.prototype.onClick = function(item, el, e) {
- e.preventDefault();
- return this.requestFile(item);
- };
-
- TemplateSelector.prototype.requestFile = function(item) {
- // This `requestFile` method is an abstract method that should
- // be added by all subclasses.
- };
-
- // To be implemented on the extending class
- // e.g.
- // Api.gitignoreText item.name, @requestFileSuccess.bind(@)
- TemplateSelector.prototype.requestFileSuccess = function(file, skipFocus) {
- this.editor.setValue(file.content, 1);
- if (!skipFocus) this.editor.focus();
-
- if (this.editor instanceof jQuery) {
- this.editor.get(0).dispatchEvent(this.autosizeUpdateEvent);
- }
- };
-
- TemplateSelector.prototype.startLoadingSpinner = function() {
- this.dropdownIcon
- .addClass('fa-spinner fa-spin')
- .removeClass('fa-chevron-down');
- };
-
- TemplateSelector.prototype.stopLoadingSpinner = function() {
- this.dropdownIcon
- .addClass('fa-chevron-down')
- .removeClass('fa-spinner fa-spin');
- };
-
- return TemplateSelector;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/blob/template_selector.js.es6 b/app/assets/javascripts/blob/template_selector.js.es6
new file mode 100644
index 00000000000..4e309e480b0
--- /dev/null
+++ b/app/assets/javascripts/blob/template_selector.js.es6
@@ -0,0 +1,102 @@
+((global) => {
+ class TemplateSelector {
+ constructor({ dropdown, data, pattern, wrapper, editor, fileEndpoint, $input } = {}) {
+ this.onClick = this.onClick.bind(this);
+ this.dropdown = dropdown;
+ this.data = data;
+ this.pattern = pattern;
+ this.wrapper = wrapper;
+ this.editor = editor;
+ this.fileEndpoint = fileEndpoint;
+ this.$input = $input || $('#file_name');
+ this.dropdownIcon = $('.fa-chevron-down', this.dropdown);
+ this.buildDropdown();
+ this.bindEvents();
+ this.onFilenameUpdate();
+
+ this.autosizeUpdateEvent = document.createEvent('Event');
+ this.autosizeUpdateEvent.initEvent('autosize:update', true, false);
+ }
+
+ buildDropdown() {
+ return this.dropdown.glDropdown({
+ data: this.data,
+ filterable: true,
+ selectable: true,
+ toggleLabel: this.toggleLabel,
+ search: {
+ fields: ['name']
+ },
+ clicked: this.onClick,
+ text: function(item) {
+ return item.name;
+ }
+ });
+ }
+
+ bindEvents() {
+ return this.$input.on('keyup blur', (e) => this.onFilenameUpdate());
+ }
+
+ toggleLabel(item) {
+ return item.name;
+ }
+
+ onFilenameUpdate() {
+ var filenameMatches;
+ if (!this.$input.length) {
+ return;
+ }
+ filenameMatches = this.pattern.test(this.$input.val().trim());
+ if (!filenameMatches) {
+ this.wrapper.addClass('hidden');
+ return;
+ }
+ return this.wrapper.removeClass('hidden');
+ }
+
+ onClick(item, el, e) {
+ e.preventDefault();
+ return this.requestFile(item);
+ }
+
+ requestFile(item) {
+ // This `requestFile` method is an abstract method that should
+ // be added by all subclasses.
+ }
+
+ // To be implemented on the extending class
+ // e.g.
+ // Api.gitignoreText item.name, @requestFileSuccess.bind(@)
+ requestFileSuccess(file, { skipFocus, append } = {}) {
+ const oldValue = this.editor.getValue();
+ let newValue = file.content;
+
+ if (append && oldValue.length && oldValue !== newValue) {
+ newValue = oldValue + '\n\n' + newValue;
+ }
+
+ this.editor.setValue(newValue, 1);
+ if (!skipFocus) this.editor.focus();
+
+ if (this.editor instanceof jQuery) {
+ this.editor.get(0).dispatchEvent(this.autosizeUpdateEvent);
+ }
+ }
+
+ startLoadingSpinner() {
+ this.dropdownIcon
+ .addClass('fa-spinner fa-spin')
+ .removeClass('fa-chevron-down');
+ }
+
+ stopLoadingSpinner() {
+ this.dropdownIcon
+ .addClass('fa-chevron-down')
+ .removeClass('fa-spinner fa-spin');
+ }
+ }
+
+ global.TemplateSelector = TemplateSelector;
+ })(window.gl || ( window.gl = {}));
+
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index de6cdd851be..8db4f6a3b28 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -23,13 +23,13 @@
})(this));
this.initModePanesAndLinks();
this.initSoftWrap();
- new BlobLicenseSelectors({
+ new gl.BlobLicenseSelectors({
editor: this.editor
});
new BlobGitignoreSelectors({
editor: this.editor
});
- new BlobCiYamlSelectors({
+ new gl.BlobCiYamlSelectors({
editor: this.editor
});
}
diff --git a/app/assets/javascripts/boards/components/board.js.es6 b/app/assets/javascripts/boards/components/board.js.es6
index 7e86f001f44..cacb36a897f 100644
--- a/app/assets/javascripts/boards/components/board.js.es6
+++ b/app/assets/javascripts/boards/components/board.js.es6
@@ -21,7 +21,8 @@
},
data () {
return {
- filters: Store.state.filters
+ filters: Store.state.filters,
+ showIssueForm: false
};
},
watch: {
@@ -33,6 +34,11 @@
deep: true
}
},
+ methods: {
+ showNewIssueForm() {
+ this.showIssueForm = !this.showIssueForm;
+ }
+ },
ready () {
const options = gl.issueBoards.getBoardSortableDefaultOptions({
disabled: this.disabled,
diff --git a/app/assets/javascripts/boards/components/board_blank_state.js.es6 b/app/assets/javascripts/boards/components/board_blank_state.js.es6
index 63d72d857d9..ff90f2d6d75 100644
--- a/app/assets/javascripts/boards/components/board_blank_state.js.es6
+++ b/app/assets/javascripts/boards/components/board_blank_state.js.es6
@@ -8,10 +8,8 @@
data () {
return {
predefinedLabels: [
- new ListLabel({ title: 'Development', color: '#5CB85C' }),
- new ListLabel({ title: 'Testing', color: '#F0AD4E' }),
- new ListLabel({ title: 'Production', color: '#FF5F00' }),
- new ListLabel({ title: 'Ready', color: '#FF0000' })
+ new ListLabel({ title: 'To Do', color: '#F0AD4E' }),
+ new ListLabel({ title: 'Doing', color: '#5CB85C' })
]
}
},
diff --git a/app/assets/javascripts/boards/components/board_list.js.es6 b/app/assets/javascripts/boards/components/board_list.js.es6
index 474805c1437..7022a29e818 100644
--- a/app/assets/javascripts/boards/components/board_list.js.es6
+++ b/app/assets/javascripts/boards/components/board_list.js.es6
@@ -1,4 +1,5 @@
//= require ./board_card
+//= require ./board_new_issue
(() => {
const Store = gl.issueBoards.BoardsStore;
@@ -8,14 +9,16 @@
gl.issueBoards.BoardList = Vue.extend({
components: {
- 'board-card': gl.issueBoards.BoardCard
+ 'board-card': gl.issueBoards.BoardCard,
+ 'board-new-issue': gl.issueBoards.BoardNewIssue
},
props: {
disabled: Boolean,
list: Object,
issues: Array,
loading: Boolean,
- issueLinkBase: String
+ issueLinkBase: String,
+ showIssueForm: Boolean
},
data () {
return {
@@ -73,7 +76,7 @@
group: 'issues',
sort: false,
disabled: this.disabled,
- filter: '.board-list-count',
+ filter: '.board-list-count, .is-disabled',
onStart: (e) => {
const card = this.$refs.issue[e.oldIndex];
diff --git a/app/assets/javascripts/boards/components/board_new_issue.js.es6 b/app/assets/javascripts/boards/components/board_new_issue.js.es6
new file mode 100644
index 00000000000..a4fad422eca
--- /dev/null
+++ b/app/assets/javascripts/boards/components/board_new_issue.js.es6
@@ -0,0 +1,58 @@
+(() => {
+ window.gl = window.gl || {};
+
+ gl.issueBoards.BoardNewIssue = Vue.extend({
+ props: {
+ list: Object,
+ showIssueForm: Boolean
+ },
+ data() {
+ return {
+ title: '',
+ error: false
+ };
+ },
+ watch: {
+ showIssueForm () {
+ this.$els.input.focus();
+ }
+ },
+ methods: {
+ submit(e) {
+ e.preventDefault();
+ if (this.title.trim() === '') return;
+
+ this.error = false;
+
+ const labels = this.list.label ? [this.list.label] : [];
+ const issue = new ListIssue({
+ title: this.title,
+ labels
+ });
+
+ this.list.newIssue(issue)
+ .then((data) => {
+ // Need this because our jQuery very kindly disables buttons on ALL form submissions
+ $(this.$els.submitButton).enable();
+ })
+ .catch(() => {
+ // Need this because our jQuery very kindly disables buttons on ALL form submissions
+ $(this.$els.submitButton).enable();
+
+ // Remove the issue
+ this.list.removeIssue(issue);
+
+ // Show error message
+ this.error = true;
+ this.showIssueForm = true;
+ });
+
+ this.cancel();
+ },
+ cancel() {
+ this.showIssueForm = false;
+ this.title = '';
+ }
+ }
+ });
+})();
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6 b/app/assets/javascripts/boards/components/new_list_dropdown.js.es6
index 1a4d8157970..6ccd83e2d84 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js.es6
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js.es6
@@ -3,8 +3,7 @@ $(() => {
$('.js-new-board-list').each(function () {
const $this = $(this);
-
- new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('project-id'));
+ new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespace-path'), $this.data('project-path'));
$this.glDropdown({
data(term, callback) {
diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6 b/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6
index 44addb3ea98..f629d45c587 100644
--- a/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6
+++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js.es6
@@ -21,7 +21,7 @@
fallbackClass: 'is-dragging',
fallbackOnBody: true,
ghostClass: 'is-ghost',
- filter: '.has-tooltip',
+ filter: '.has-tooltip, .btn',
delay: gl.issueBoards.touchEnabled ? 100 : 0,
scrollSensitivity: gl.issueBoards.touchEnabled ? 60 : 100,
scrollSpeed: 20,
diff --git a/app/assets/javascripts/boards/models/list.js.es6 b/app/assets/javascripts/boards/models/list.js.es6
index 91fd620fdb3..5d0a561cdba 100644
--- a/app/assets/javascripts/boards/models/list.js.es6
+++ b/app/assets/javascripts/boards/models/list.js.es6
@@ -87,6 +87,17 @@ class List {
});
}
+ newIssue (issue) {
+ this.addIssue(issue);
+ this.issuesSize++;
+
+ return gl.boardService.newIssue(this.id, issue)
+ .then((resp) => {
+ const data = resp.json();
+ issue.id = data.iid;
+ });
+ }
+
createIssues (data) {
data.forEach((issueObj) => {
this.addIssue(new ListIssue(issueObj));
diff --git a/app/assets/javascripts/boards/services/board_service.js.es6 b/app/assets/javascripts/boards/services/board_service.js.es6
index 9b80fb2e99f..2b825c3949f 100644
--- a/app/assets/javascripts/boards/services/board_service.js.es6
+++ b/app/assets/javascripts/boards/services/board_service.js.es6
@@ -58,4 +58,10 @@ class BoardService {
to_list_id
});
}
+
+ newIssue (id, issue) {
+ return this.issues.save({ id }, {
+ issue
+ });
+ }
};
diff --git a/app/assets/javascripts/build.js b/app/assets/javascripts/build.js
index 78d21c0552a..f336bfc36d6 100644
--- a/app/assets/javascripts/build.js
+++ b/app/assets/javascripts/build.js
@@ -146,7 +146,7 @@
$date = $('.js-artifacts-remove');
if ($date.length) {
date = $date.text();
- return $date.text($.timefor(new Date(date.replace(/-/g, '/')), ' '));
+ return $date.text($.timefor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3')), ' '));
}
};
diff --git a/app/assets/javascripts/copy_to_clipboard.js b/app/assets/javascripts/copy_to_clipboard.js
index 3e20db7e308..e23bda2fa4e 100644
--- a/app/assets/javascripts/copy_to_clipboard.js
+++ b/app/assets/javascripts/copy_to_clipboard.js
@@ -26,15 +26,15 @@
};
showTooltip = function(target, title) {
- return $(target).tooltip({
- container: 'body',
- html: 'true',
- placement: 'auto bottom',
- title: title,
- trigger: 'manual'
- }).tooltip('show').one('mouseleave', function() {
- return $(this).tooltip('hide');
- });
+ var $target = $(target);
+ var originalTitle = $target.data('original-title');
+
+ $target
+ .attr('title', 'Copied!')
+ .tooltip('fixTitle')
+ .tooltip('show')
+ .attr('title', originalTitle)
+ .tooltip('fixTitle');
};
$(function() {
diff --git a/app/assets/javascripts/create_label.js.es6 b/app/assets/javascripts/create_label.js.es6
index 46d1c3f00c1..c5f8c29242d 100644
--- a/app/assets/javascripts/create_label.js.es6
+++ b/app/assets/javascripts/create_label.js.es6
@@ -1,8 +1,9 @@
(function (w) {
class CreateLabelDropdown {
- constructor ($el, projectId) {
+ constructor ($el, namespacePath, projectPath) {
this.$el = $el;
- this.projectId = projectId;
+ this.namespacePath = namespacePath;
+ this.projectPath = projectPath;
this.$dropdownBack = $('.dropdown-menu-back', this.$el.closest('.dropdown'));
this.$cancelButton = $('.js-cancel-label-btn', this.$el);
this.$newLabelField = $('#new_label_name', this.$el);
@@ -91,8 +92,8 @@
e.preventDefault();
e.stopPropagation();
- Api.newLabel(this.projectId, {
- name: this.$newLabelField.val(),
+ Api.newLabel(this.namespacePath, this.projectPath, {
+ title: this.$newLabelField.val(),
color: this.$newColorField.val()
}, (label) => {
this.$newLabelCreateButton.enable();
diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js
index c8634b78f2b..8086c10ad6b 100644
--- a/app/assets/javascripts/diff.js
+++ b/app/assets/javascripts/diff.js
@@ -7,6 +7,9 @@
function Diff() {
$('.files .diff-file').singleFileDiff();
this.filesCommentButton = $('.files .diff-file').filesCommentButton();
+ if (this.diffViewType() === 'parallel') {
+ $('.content-wrapper .container-fluid').removeClass('container-limited');
+ }
$(document).off('click', '.js-unfold');
$(document).on('click', '.js-unfold', (function(_this) {
return function(event) {
@@ -52,6 +55,10 @@
})(this));
}
+ Diff.prototype.diffViewType = function() {
+ return $('.inline-parallel-buttons a.active').data('view-type');
+ }
+
Diff.prototype.lineNumbers = function(line) {
if (!line.children().length) {
return [0, 0];
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index ddf11ecf34c..8d99b12102d 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -26,7 +26,7 @@
case 'projects:merge_requests:index':
case 'projects:issues:index':
Issuable.init();
- new IssuableBulkActions();
+ new gl.IssuableBulkActions();
shortcut_handler = new ShortcutsNavigation();
break;
case 'projects:issues:show':
@@ -40,7 +40,7 @@
new Milestone();
break;
case 'dashboard:todos:index':
- new Todos();
+ new gl.Todos();
break;
case 'projects:milestones:new':
case 'projects:milestones:edit':
@@ -59,7 +59,9 @@
shortcut_handler = new ShortcutsNavigation();
new GLForm($('.issue-form'));
new IssuableForm($('.issue-form'));
- new IssuableTemplateSelectors();
+ new LabelsSelect();
+ new MilestoneSelect();
+ new gl.IssuableTemplateSelectors();
break;
case 'projects:merge_requests:new':
case 'projects:merge_requests:edit':
@@ -67,7 +69,9 @@
shortcut_handler = new ShortcutsNavigation();
new GLForm($('.merge-request-form'));
new IssuableForm($('.merge-request-form'));
- new IssuableTemplateSelectors();
+ new LabelsSelect();
+ new MilestoneSelect();
+ new gl.IssuableTemplateSelectors();
break;
case 'projects:tags:new':
new ZenMode();
@@ -165,7 +169,7 @@
break;
case 'projects:labels:index':
if ($('.prioritized-labels').length) {
- new LabelManager();
+ new gl.LabelManager();
}
break;
case 'projects:network:show':
@@ -279,7 +283,7 @@
Dispatcher.prototype.initSearch = function() {
// Only when search form is present
if ($('.search').length) {
- return new SearchAutocomplete();
+ return new gl.SearchAutocomplete();
}
};
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index 1b6db641200..d4403375643 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -443,6 +443,7 @@
var contentHtml;
this.resetRows();
this.addArrowKeyEvent();
+
if (this.options.setIndeterminateIds) {
this.options.setIndeterminateIds.call(this);
}
@@ -460,9 +461,21 @@
if (this.options.filterable) {
this.filterInput.focus();
}
+
+ if (this.options.showMenuAbove) {
+ this.positionMenuAbove();
+ }
+
return this.dropdown.trigger('shown.gl.dropdown');
};
+ GitLabDropdown.prototype.positionMenuAbove = function() {
+ var $button = $(this.el);
+ var $menu = this.dropdown.find('.dropdown-menu');
+
+ $menu.css('top', ($button.height() + $menu.height()) * -1);
+ };
+
GitLabDropdown.prototype.hidden = function(e) {
var $input;
this.resetRows();
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index 7c2eebcdd44..5f06186504b 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -5,14 +5,15 @@
function GroupsSelect() {
$('.ajax-groups-select').each((function(_this) {
return function(i, select) {
- var skip_ldap;
+ var skip_ldap, skip_groups;
skip_ldap = $(select).hasClass('skip_ldap');
+ skip_groups = $(select).data('skip-groups') || [];
return $(select).select2({
placeholder: "Search for a group",
multiple: $(select).hasClass('multiselect'),
minimumInputLength: 0,
query: function(query) {
- return Api.groups(query.term, skip_ldap, function(groups) {
+ return Api.groups(query.term, skip_ldap, skip_groups, function(groups) {
var data;
data = {
results: groups
diff --git a/app/assets/javascripts/issuable.js.es6 b/app/assets/javascripts/issuable.js.es6
index 73e2664e9c0..57f7e4ef230 100644
--- a/app/assets/javascripts/issuable.js.es6
+++ b/app/assets/javascripts/issuable.js.es6
@@ -51,7 +51,6 @@
}).remove();
// Submit the form to get new data
Issuable.filterResults($('.filter-form'));
- return $('.js-label-select').trigger('update.label');
});
},
filterResults: (function(_this) {
diff --git a/app/assets/javascripts/issues-bulk-assignment.js b/app/assets/javascripts/issues-bulk-assignment.js.es6
index 62a7fc9a06c..0808f538f01 100644
--- a/app/assets/javascripts/issues-bulk-assignment.js
+++ b/app/assets/javascripts/issues-bulk-assignment.js.es6
@@ -1,13 +1,10 @@
-(function() {
- this.IssuableBulkActions = (function() {
- function IssuableBulkActions(opts) {
- // Set defaults
- var ref, ref1, ref2;
- if (opts == null) {
- opts = {};
- }
- this.container = (ref = opts.container) != null ? ref : $('.content'), this.form = (ref1 = opts.form) != null ? ref1 : this.getElement('.bulk-update'), this.issues = (ref2 = opts.issues) != null ? ref2 : this.getElement('.issuable-list > li');
- // Save instance
+((global) => {
+
+ class IssuableBulkActions {
+ constructor({ container, form, issues } = {}) {
+ this.container = container || $('.content'),
+ this.form = form || this.getElement('.bulk-update');
+ this.issues = issues || this.getElement('.issues-list .issue');
this.form.data('bulkActions', this);
this.willUpdateLabels = false;
this.bindEvents();
@@ -15,53 +12,46 @@
Issuable.initChecks();
}
- IssuableBulkActions.prototype.getElement = function(selector) {
+ getElement(selector) {
return this.container.find(selector);
- };
+ }
- IssuableBulkActions.prototype.bindEvents = function() {
+ bindEvents() {
return this.form.off('submit').on('submit', this.onFormSubmit.bind(this));
- };
+ }
- IssuableBulkActions.prototype.onFormSubmit = function(e) {
+ onFormSubmit(e) {
e.preventDefault();
return this.submit();
- };
+ }
- IssuableBulkActions.prototype.submit = function() {
- var _this, xhr;
- _this = this;
- xhr = $.ajax({
+ submit() {
+ const _this = this;
+ const xhr = $.ajax({
url: this.form.attr('action'),
method: this.form.attr('method'),
dataType: 'JSON',
data: this.getFormDataAsObject()
});
- xhr.done(function(response, status, xhr) {
- return location.reload();
- });
- xhr.fail(function() {
- return new Flash("Issue update failed");
- });
+ xhr.done(() => window.location.reload());
+ xhr.fail(() => new Flash("Issue update failed"));
return xhr.always(this.onFormSubmitAlways.bind(this));
- };
+ }
- IssuableBulkActions.prototype.onFormSubmitAlways = function() {
+ onFormSubmitAlways() {
return this.form.find('[type="submit"]').enable();
- };
+ }
- IssuableBulkActions.prototype.getSelectedIssues = function() {
+ getSelectedIssues() {
return this.issues.has('.selected_issue:checked');
- };
+ }
- IssuableBulkActions.prototype.getLabelsFromSelection = function() {
- var labels;
- labels = [];
+ getLabelsFromSelection() {
+ const labels = [];
this.getSelectedIssues().map(function() {
- var _labels;
- _labels = $(this).data('labels');
- if (_labels) {
- return _labels.map(function(labelId) {
+ const labelsData = $(this).data('labels');
+ if (labelsData) {
+ return labelsData.map(function(labelId) {
if (labels.indexOf(labelId) === -1) {
return labels.push(labelId);
}
@@ -69,7 +59,7 @@
}
});
return labels;
- };
+ }
/**
@@ -77,25 +67,21 @@
* @return {Array} Label IDs
*/
- IssuableBulkActions.prototype.getUnmarkedIndeterminedLabels = function() {
- var el, i, id, j, labelsToKeep, len, len1, ref, ref1, result;
- result = [];
- labelsToKeep = [];
- ref = this.getElement('.labels-filter .is-indeterminate');
- for (i = 0, len = ref.length; i < len; i++) {
- el = ref[i];
- labelsToKeep.push($(el).data('labelId'));
- }
- ref1 = this.getLabelsFromSelection();
- for (j = 0, len1 = ref1.length; j < len1; j++) {
- id = ref1[j];
- // Only the ones that we are not going to keep
+ getUnmarkedIndeterminedLabels() {
+ const result = [];
+ const labelsToKeep = [];
+
+ this.getElement('.labels-filter .is-indeterminate')
+ .each((i, el) => labelsToKeep.push($(el).data('labelId')));
+
+ this.getLabelsFromSelection().forEach((id) => {
if (labelsToKeep.indexOf(id) === -1) {
result.push(id);
}
- }
+ });
+
return result;
- };
+ }
/**
@@ -103,9 +89,8 @@
* Returns key/value pairs from form data
*/
- IssuableBulkActions.prototype.getFormDataAsObject = function() {
- var formData;
- formData = {
+ getFormDataAsObject() {
+ const formData = {
update: {
state_event: this.form.find('input[name="update[state_event]"]').val(),
assignee_id: this.form.find('input[name="update[assignee_id]"]').val(),
@@ -125,19 +110,18 @@
});
}
return formData;
- };
+ }
- IssuableBulkActions.prototype.getLabelsToApply = function() {
- var $labels, labelIds;
- labelIds = [];
- $labels = this.form.find('.labels-filter input[name="update[label_ids][]"]');
+ getLabelsToApply() {
+ const labelIds = [];
+ const $labels = this.form.find('.labels-filter input[name="update[label_ids][]"]');
$labels.each(function(k, label) {
if (label) {
return labelIds.push(parseInt($(label).val()));
}
});
return labelIds;
- };
+ }
/**
@@ -145,11 +129,10 @@
* @return {Array} Array of labels IDs
*/
- IssuableBulkActions.prototype.getLabelsToRemove = function() {
- var indeterminatedLabels, labelsToApply, result;
- result = [];
- indeterminatedLabels = this.getUnmarkedIndeterminedLabels();
- labelsToApply = this.getLabelsToApply();
+ getLabelsToRemove() {
+ const result = [];
+ const indeterminatedLabels = this.getUnmarkedIndeterminedLabels();
+ const labelsToApply = this.getLabelsToApply();
indeterminatedLabels.map(function(id) {
// We need to exclude label IDs that will be applied
// By not doing this will cause issues from selection to not add labels at all
@@ -158,10 +141,9 @@
}
});
return result;
- };
-
- return IssuableBulkActions;
+ }
+ }
- })();
+ global.IssuableBulkActions = IssuableBulkActions;
-}).call(this);
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index ce79e2e348a..e356872624a 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -4,9 +4,11 @@
var _this;
_this = this;
$('.js-label-select').each(function(i, dropdown) {
- var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, projectId, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected;
+ var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelHTMLTemplate, labelNoneHTMLTemplate, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove;
$dropdown = $(dropdown);
- projectId = $dropdown.data('project-id');
+ $toggleText = $dropdown.find('.dropdown-toggle-text');
+ namespacePath = $dropdown.data('namespace-path');
+ projectPath = $dropdown.data('project-path');
labelUrl = $dropdown.data('labels');
issueUpdateURL = $dropdown.data('issueUpdate');
selectedLabel = $dropdown.data('selected');
@@ -15,6 +17,7 @@
}
showNo = $dropdown.data('show-no');
showAny = $dropdown.data('show-any');
+ showMenuAbove = $dropdown.data('showMenuAbove');
defaultLabel = $dropdown.data('default-label');
abilityName = $dropdown.data('ability-name');
$selectbox = $dropdown.closest('.selectbox');
@@ -24,6 +27,9 @@
$sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip');
$value = $block.find('.value');
$loading = $block.find('.block-loading').fadeOut();
+ fieldName = $dropdown.data('field-name');
+ 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') + '"]')
.map(function () {
@@ -40,12 +46,12 @@
$sidebarLabelTooltip.tooltip();
if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) {
- new gl.CreateLabelDropdown($dropdown.closest('.dropdown').find('.dropdown-new-label'), projectId);
+ new gl.CreateLabelDropdown($dropdown.closest('.dropdown').find('.dropdown-new-label'), namespacePath, projectPath);
}
saveLabelData = function() {
var data, selected;
- selected = $dropdown.closest('.selectbox').find("input[name='" + ($dropdown.data('field-name')) + "']").map(function() {
+ selected = $dropdown.closest('.selectbox').find("input[name='" + fieldName + "']").map(function() {
return this.value;
}).get();
@@ -75,7 +81,8 @@
if (data.labels.length) {
template = labelHTMLTemplate(data);
labelCount = data.labels.length;
- } else {
+ }
+ else {
template = labelNoneHTMLTemplate;
}
$value.removeAttr('style').html(template);
@@ -92,7 +99,8 @@
}
labelTooltipTitle = labelTitles.join(', ');
- } else {
+ }
+ else {
labelTooltipTitle = '';
$sidebarLabelTooltip.tooltip('destroy');
}
@@ -114,6 +122,7 @@
});
};
return $dropdown.glDropdown({
+ showMenuAbove: showMenuAbove,
data: function(term, callback) {
return $.ajax({
url: labelUrl
@@ -133,23 +142,29 @@
};
}).value();
if ($dropdown.hasClass('js-extra-options')) {
+ var extraData = [];
if (showNo) {
- data.unshift({
+ extraData.unshift({
id: 0,
title: 'No Label'
});
}
if (showAny) {
- data.unshift({
+ extraData.unshift({
isAny: true,
title: 'Any Label'
});
}
- if (data.length > 2) {
- data.splice(2, 0, 'divider');
+ if (extraData.length) {
+ extraData.push('divider');
+ data = extraData.concat(data);
}
}
- return callback(data);
+
+ callback(data);
+ if (showMenuAbove) {
+ $dropdown.data('glDropdown').positionMenuAbove();
+ }
});
},
renderRow: function(label, instance) {
@@ -157,7 +172,7 @@
$li = $('<li>');
$a = $('<a href="#">');
selectedClass = [];
- removesAll = label.id === 0 || (label.id == null);
+ removesAll = label.id <= 0 || (label.id == null);
if ($dropdown.hasClass('js-filter-bulk-update')) {
indeterminate = instance.indeterminateIds;
active = instance.activeIds;
@@ -194,14 +209,16 @@
return color + " " + percentFirst + "%," + color + " " + percentSecond + "% ";
}).join(',');
color = "linear-gradient(" + color + ")";
- } else {
+ }
+ else {
if (label.color != null) {
color = label.color[0];
}
}
if (color) {
colorEl = "<span class='dropdown-label-box' style='background: " + color + "'></span>";
- } else {
+ }
+ else {
colorEl = '';
}
// We need to identify which items are actually labels
@@ -219,30 +236,46 @@
},
selectable: true,
filterable: true,
+ selected: $dropdown.data('selected') || [],
toggleLabel: function(selected, el) {
- var selected_labels;
- selected_labels = $('.js-label-select').siblings('.dropdown-menu-labels').find('.is-active');
- if (selected && (selected.title != null)) {
- if (selected_labels.length > 1) {
- return selected.title + " +" + (selected_labels.length - 1) + " more";
- } else {
- return selected.title;
- }
- } else if (!selected && selected_labels.length !== 0) {
- if (selected_labels.length > 1) {
- return ($(selected_labels[0]).text()) + " +" + (selected_labels.length - 1) + " more";
- } else if (selected_labels.length === 1) {
- return $(selected_labels).text();
- }
- } else {
+ var isSelected = el !== null ? el.hasClass('is-active') : false;
+ var title = selected.title;
+ var selectedLabels = this.selected;
+
+ if (selected.id === 0) {
+ this.selected = [];
+ return 'No Label';
+ }
+ else if (isSelected) {
+ this.selected.push(title);
+ }
+ else {
+ var index = this.selected.indexOf(title);
+ this.selected.splice(index, 1);
+ }
+
+ if (selectedLabels.length === 1) {
+ return selectedLabels;
+ }
+ else if (selectedLabels.length) {
+ return selectedLabels[0] + " +" + (selectedLabels.length - 1) + " more";
+ }
+ else {
return defaultLabel;
}
},
fieldName: $dropdown.data('field-name'),
id: function(label) {
+ if (label.id <= 0) return;
+
+ if ($dropdown.hasClass('js-issuable-form-dropdown')) {
+ return label.id;
+ }
+
if ($dropdown.hasClass("js-filter-submit") && (label.isAny == null)) {
return label.title;
- } else {
+ }
+ else {
return label.id;
}
},
@@ -254,6 +287,11 @@
$selectbox.hide();
// display:block overrides the hide-collapse rule
$value.removeAttr('style');
+
+ if ($dropdown.hasClass('js-issuable-form-dropdown')) {
+ return;
+ }
+
if (page === 'projects:boards:show') {
return;
}
@@ -261,9 +299,11 @@
if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
selectedLabels = $dropdown.closest('form').find("input:hidden[name='" + ($dropdown.data('fieldName')) + "']");
Issuable.filterResults($dropdown.closest('form'));
- } else if ($dropdown.hasClass('js-filter-submit')) {
+ }
+ else if ($dropdown.hasClass('js-filter-submit')) {
$dropdown.closest('form').submit();
- } else {
+ }
+ else {
if (!$dropdown.hasClass('js-filter-bulk-update')) {
saveLabelData();
}
@@ -280,18 +320,28 @@
clicked: function(label, $el, e) {
var isIssueIndex, isMRIndex, page;
_this.enableBulkLabelDropdown();
- if ($dropdown.hasClass('js-filter-bulk-update')) {
+
+ if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) {
+ $dropdown.parent()
+ .find('.dropdown-clear-active')
+ .removeClass('is-active')
+ }
+
+ if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
return;
}
+
page = $('body').data('page');
isIssueIndex = page === 'projects:issues:index';
isMRIndex = page === 'projects:merge_requests:index';
if (page === 'projects:boards:show') {
if (label.isAny) {
gl.issueBoards.BoardsStore.state.filters['label_name'] = [];
- } else if ($el.hasClass('is-active')) {
+ }
+ else if ($el.hasClass('is-active')) {
gl.issueBoards.BoardsStore.state.filters['label_name'].push(label.title);
- } else {
+ }
+ else {
var filters = gl.issueBoards.BoardsStore.state.filters['label_name'];
filters = filters.filter(function (filteredLabel) {
return filteredLabel !== label.title;
@@ -302,17 +352,21 @@
gl.issueBoards.BoardsStore.updateFiltersUrl();
e.preventDefault();
return;
- } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ }
+ else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
if (!$dropdown.hasClass('js-multiselect')) {
selectedLabel = label.title;
return Issuable.filterResults($dropdown.closest('form'));
}
- } else if ($dropdown.hasClass('js-filter-submit')) {
+ }
+ else if ($dropdown.hasClass('js-filter-submit')) {
return $dropdown.closest('form').submit();
- } else {
+ }
+ else {
if ($dropdown.hasClass('js-multiselect')) {
- } else {
+ }
+ else {
return saveLabelData();
}
}
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 9299d0eabd2..b170e26eebf 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -38,6 +38,11 @@
gl.utils.getPagePath = function() {
return $('body').data('page').split(':')[0];
};
+ gl.utils.parseUrl = function (url) {
+ var parser = document.createElement('a');
+ parser.href = url;
+ return parser;
+ };
return jQuery.timefor = function(time, suffix, expiredLabel) {
var suffixFromNow, timefor;
if (!time) {
diff --git a/app/assets/javascripts/merge_conflict_data_provider.js.es6 b/app/assets/javascripts/merge_conflict_data_provider.js.es6
index cd92df8ddc5..13ee794ba38 100644
--- a/app/assets/javascripts/merge_conflict_data_provider.js.es6
+++ b/app/assets/javascripts/merge_conflict_data_provider.js.es6
@@ -7,13 +7,16 @@ const ORIGIN_BUTTON_TITLE = 'Use theirs';
class MergeConflictDataProvider {
getInitialData() {
+ // TODO: remove reliance on jQuery and DOM state introspection
const diffViewType = $.cookie('diff_view');
+ const fixedLayout = $('.content-wrapper .container-fluid').hasClass('container-limited');
return {
isLoading : true,
hasError : false,
isParallel : diffViewType === 'parallel',
diffViewType : diffViewType,
+ fixedLayout : fixedLayout,
isSubmitting : false,
conflictsData : {},
resolutionData : {}
@@ -192,14 +195,17 @@ class MergeConflictDataProvider {
updateViewType(newType) {
const vi = this.vueInstance;
- if (newType === vi.diffView || !(newType === 'parallel' || newType === 'inline')) {
+ if (newType === vi.diffViewType || !(newType === 'parallel' || newType === 'inline')) {
return;
}
- vi.diffView = newType;
- vi.isParallel = newType === 'parallel';
- $.cookie('diff_view', newType); // TODO: Make sure that cookie path added.
- $('.content-wrapper .container-fluid').toggleClass('container-limited');
+ vi.diffViewType = newType;
+ vi.isParallel = newType === 'parallel';
+ $.cookie('diff_view', newType, {
+ path: (gon && gon.relative_url_root) || '/'
+ });
+ $('.content-wrapper .container-fluid')
+ .toggleClass('container-limited', !vi.isParallel && vi.fixedLayout);
}
diff --git a/app/assets/javascripts/merge_conflict_resolver.js.es6 b/app/assets/javascripts/merge_conflict_resolver.js.es6
index b56fd5aa658..7e756433bf5 100644
--- a/app/assets/javascripts/merge_conflict_resolver.js.es6
+++ b/app/assets/javascripts/merge_conflict_resolver.js.es6
@@ -60,9 +60,8 @@ class MergeConflictResolver {
$('#conflicts .js-syntax-highlight').syntaxHighlight();
});
- if (this.vue.diffViewType === 'parallel') {
- $('.content-wrapper .container-fluid').removeClass('container-limited');
- }
+ $('.content-wrapper .container-fluid')
+ .toggleClass('container-limited', !this.vue.isParallel && this.vue.fixedLayout);
})
}
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 05644b3d03c..02ff5a382e2 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -36,13 +36,10 @@
};
MergeRequest.prototype.initTabs = function() {
- if (this.opts.action !== 'new') {
- // `MergeRequests#new` has no tab-persisting or lazy-loading behavior
- window.mrTabs = new MergeRequestTabs(this.opts);
- } else {
- // Show the first tab (Commits)
- return $('.merge-request-tabs a[data-toggle="tab"]:first').tab('show');
+ if (window.mrTabs) {
+ window.mrTabs.unbindEvents();
}
+ window.mrTabs = new MergeRequestTabs(this.opts);
};
MergeRequest.prototype.showAllCommits = function() {
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 18bbfa7a459..8045d24a1bb 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -56,9 +56,14 @@
MergeRequestTabs.prototype.commitsLoaded = false;
+ MergeRequestTabs.prototype.fixedLayoutPref = null;
+
function MergeRequestTabs(opts) {
this.opts = opts != null ? opts : {};
this.opts.setUrl = this.opts.setUrl !== undefined ? this.opts.setUrl : true;
+
+ this.buildsLoaded = this.opts.buildsLoaded || false;
+
this.setCurrentAction = bind(this.setCurrentAction, this);
this.tabShown = bind(this.tabShown, this);
this.showTab = bind(this.showTab, this);
@@ -70,7 +75,12 @@
MergeRequestTabs.prototype.bindEvents = function() {
$(document).on('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown);
- return $(document).on('click', '.js-show-tab', this.showTab);
+ $(document).on('click', '.js-show-tab', this.showTab);
+ };
+
+ MergeRequestTabs.prototype.unbindEvents = function() {
+ $(document).off('shown.bs.tab', '.merge-request-tabs a[data-toggle="tab"]', this.tabShown);
+ $(document).off('click', '.js-show-tab', this.showTab);
};
MergeRequestTabs.prototype.showTab = function(event) {
@@ -85,11 +95,15 @@
if (action === 'commits') {
this.loadCommits($target.attr('href'));
this.expandView();
- } else if (action === 'diffs') {
+ this.resetViewContainer();
+ } else if (this.isDiffAction(action)) {
this.loadDiff($target.attr('href'));
if ((typeof bp !== "undefined" && bp !== null) && bp.getBreakpointSize() !== 'lg') {
this.shrinkView();
}
+ if (this.diffViewType() === 'parallel') {
+ this.expandViewContainer();
+ }
navBarHeight = $('.navbar-gitlab').outerHeight();
$.scrollTo(".merge-request-details .merge-request-tabs", {
offset: -navBarHeight
@@ -97,11 +111,14 @@
} else if (action === 'builds') {
this.loadBuilds($target.attr('href'));
this.expandView();
+ this.resetViewContainer();
} else if (action === 'pipelines') {
this.loadPipelines($target.attr('href'));
this.expandView();
+ this.resetViewContainer();
} else {
this.expandView();
+ this.resetViewContainer();
}
if (this.opts.setUrl) {
this.setCurrentAction(action);
@@ -126,7 +143,7 @@
if (action === 'show') {
action = 'notes';
}
- return $(".merge-request-tabs a[data-action='" + action + "']").tab('show');
+ $(".merge-request-tabs a[data-action='" + action + "']").tab('show').trigger('shown.bs.tab');
};
// Replaces the current Merge Request-specific action in the URL with a new one
@@ -156,8 +173,9 @@
action = 'notes';
}
this.currentAction = action;
- // Remove a trailing '/commits' or '/diffs'
- new_state = this._location.pathname.replace(/\/(commits|diffs|builds|pipelines)(\.html)?\/?$/, '');
+ // Remove a trailing '/commits' '/diffs' '/builds' '/pipelines' '/new' '/new/diffs'
+ new_state = this._location.pathname.replace(/\/(commits|diffs|builds|pipelines|new|new\/diffs)(\.html)?\/?$/, '');
+
// Append the new action if we're on a tab other than 'notes'
if (action !== 'notes') {
new_state += "/" + action;
@@ -196,8 +214,13 @@
if (this.diffsLoaded) {
return;
}
+
+ // We extract pathname for the current Changes tab anchor href
+ // some pages like MergeRequestsController#new has query parameters on that anchor
+ var url = gl.utils.parseUrl(source);
+
return this._get({
- url: (source + ".json") + this._location.search,
+ url: (url.pathname + ".json") + this._location.search,
success: (function(_this) {
return function(data) {
$('#diffs').html(data.html);
@@ -209,7 +232,7 @@
gl.utils.localTimeAgo($('.js-timeago', 'div#diffs'));
$('#diffs .js-syntax-highlight').syntaxHighlight();
$('#diffs .diff-file').singleFileDiff();
- if (_this.diffViewType() === 'parallel') {
+ if (_this.diffViewType() === 'parallel' && (_this.isDiffAction(_this.currentAction)) ) {
_this.expandViewContainer();
}
_this.diffsLoaded = true;
@@ -308,11 +331,25 @@
MergeRequestTabs.prototype.diffViewType = function() {
return $('.inline-parallel-buttons a.active').data('view-type');
- // Returns diff view type
+ };
+
+ MergeRequestTabs.prototype.isDiffAction = function(action) {
+ return action === 'diffs' || action === 'new/diffs'
};
MergeRequestTabs.prototype.expandViewContainer = function() {
- return $('.container-fluid').removeClass('container-limited');
+ var $wrapper = $('.content-wrapper .container-fluid');
+ if (this.fixedLayoutPref === null) {
+ this.fixedLayoutPref = $wrapper.hasClass('container-limited');
+ }
+ $wrapper.removeClass('container-limited');
+ };
+
+ MergeRequestTabs.prototype.resetViewContainer = function() {
+ if (this.fixedLayoutPref !== null) {
+ $('.content-wrapper .container-fluid')
+ .toggleClass('container-limited', this.fixedLayoutPref);
+ }
};
MergeRequestTabs.prototype.shrinkView = function() {
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index c8031174dd2..26cc6eb0e96 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -7,7 +7,7 @@
this.currentProject = JSON.parse(currentProject);
}
$('.js-milestone-select').each(function(i, dropdown) {
- var $block, $dropdown, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, collapsedSidebarLabelTemplate, defaultLabel, issuableId, issueUpdateURL, milestoneLinkNoneTemplate, milestoneLinkTemplate, milestonesUrl, projectId, selectedMilestone, showAny, showNo, showUpcoming, useId;
+ var $block, $dropdown, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, collapsedSidebarLabelTemplate, defaultLabel, issuableId, issueUpdateURL, milestoneLinkNoneTemplate, milestoneLinkTemplate, milestonesUrl, projectId, selectedMilestone, showAny, showNo, showUpcoming, useId, showMenuAbove;
$dropdown = $(dropdown);
projectId = $dropdown.data('project-id');
milestonesUrl = $dropdown.data('milestones');
@@ -15,6 +15,7 @@
selectedMilestone = $dropdown.data('selected');
showNo = $dropdown.data('show-no');
showAny = $dropdown.data('show-any');
+ showMenuAbove = $dropdown.data('showMenuAbove');
showUpcoming = $dropdown.data('show-upcoming');
useId = $dropdown.data('use-id');
defaultLabel = $dropdown.data('default-label');
@@ -31,12 +32,12 @@
collapsedSidebarLabelTemplate = _.template('<span class="has-tooltip" data-container="body" title="<%- remaining %>" data-placement="left"> <%- title %> </span>');
}
return $dropdown.glDropdown({
+ showMenuAbove: showMenuAbove,
data: function(term, callback) {
return $.ajax({
url: milestonesUrl
}).done(function(data) {
- var extraOptions;
- extraOptions = [];
+ var extraOptions = [];
if (showAny) {
extraOptions.push({
id: 0,
@@ -58,10 +59,14 @@
title: 'Upcoming'
});
}
- if (extraOptions.length > 2) {
+ if (extraOptions.length) {
extraOptions.push('divider');
}
- return callback(extraOptions.concat(data));
+
+ callback(extraOptions.concat(data));
+ if (showMenuAbove) {
+ $dropdown.data('glDropdown').positionMenuAbove();
+ }
});
},
filterable: true,
@@ -69,19 +74,20 @@
fields: ['title']
},
selectable: true,
- toggleLabel: function(selected) {
- if (selected && 'id' in selected) {
+ toggleLabel: function(selected, el, e) {
+ if (selected && 'id' in selected && $(el).hasClass('is-active')) {
return selected.title;
} else {
return defaultLabel;
}
},
+ defaultLabel: defaultLabel,
fieldName: $dropdown.data('field-name'),
text: function(milestone) {
return _.escape(milestone.title);
},
id: function(milestone) {
- if (!useId) {
+ if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
return milestone.name;
} else {
return milestone.id;
@@ -100,7 +106,8 @@
page = $('body').data('page');
isIssueIndex = page === 'projects:issues:index';
isMRIndex = (page === page && page === 'projects:merge_requests:index');
- if ($dropdown.hasClass('js-filter-bulk-update')) {
+ if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
+ e.preventDefault();
return;
}
if (page === 'projects:boards:show') {
diff --git a/app/assets/javascripts/pipeline.js.es6 b/app/assets/javascripts/pipeline.js.es6
index bf33eb10100..8813bb5dfef 100644
--- a/app/assets/javascripts/pipeline.js.es6
+++ b/app/assets/javascripts/pipeline.js.es6
@@ -3,12 +3,21 @@
const $pipelineBtn = $(this).closest('.toggle-pipeline-btn');
const $pipelineGraph = $(this).closest('.row-content-block').next('.pipeline-graph');
const $btnText = $(this).find('.toggle-btn-text');
+ const $icon = $(this).find('.fa');
$($pipelineBtn).add($pipelineGraph).toggleClass('graph-collapsed');
const graphCollapsed = $pipelineGraph.hasClass('graph-collapsed');
+ const expandIcon = 'fa-caret-down';
+ const hideIcon = 'fa-caret-up';
- graphCollapsed ? $btnText.text('Expand') : $btnText.text('Hide')
+ if(graphCollapsed) {
+ $btnText.text('Expand');
+ $icon.removeClass(hideIcon).addClass(expandIcon);
+ } else {
+ $btnText.text('Hide');
+ $icon.removeClass(expandIcon).addClass(hideIcon);
+ }
}
$(document).on('click', '.toggle-pipeline-btn', toggleGraph);
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js.es6
index 30cd6f6e470..a1b0126e857 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js.es6
@@ -1,47 +1,45 @@
-(function() {
- var GitLabCrop,
- bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
+((global) => {
- GitLabCrop = (function() {
- var FILENAMEREGEX;
+ // Matches everything but the file name
+ const FILENAMEREGEX = /^.*[\\\/]/;
- // Matches everything but the file name
- FILENAMEREGEX = /^.*[\\\/]/;
+ class GitLabCrop {
+ constructor(input, { filename, previewImage, modalCrop, pickImageEl, uploadImageBtn, modalCropImg,
+ exportWidth = 200, exportHeight = 200, cropBoxWidth = 200, cropBoxHeight = 200 } = {}) {
- function GitLabCrop(input, opts) {
- var ref, ref1, ref2, ref3, ref4;
- if (opts == null) {
- opts = {};
- }
- this.onUploadImageBtnClick = bind(this.onUploadImageBtnClick, this);
- this.onModalHide = bind(this.onModalHide, this);
- this.onModalShow = bind(this.onModalShow, this);
- this.onPickImageClick = bind(this.onPickImageClick, this);
+ this.onUploadImageBtnClick = this.onUploadImageBtnClick.bind(this);
+ this.onModalHide = this.onModalHide.bind(this);
+ this.onModalShow = this.onModalShow.bind(this);
+ this.onPickImageClick = this.onPickImageClick.bind(this);
this.fileInput = $(input);
- // We should rename to avoid spec to fail
- // Form will submit the proper input filed with a file using FormData
- this.fileInput.attr('name', (this.fileInput.attr('name')) + "-trigger").attr('id', (this.fileInput.attr('id')) + "-trigger");
- // Set defaults
- this.exportWidth = (ref = opts.exportWidth) != null ? ref : 200, this.exportHeight = (ref1 = opts.exportHeight) != null ? ref1 : 200, this.cropBoxWidth = (ref2 = opts.cropBoxWidth) != null ? ref2 : 200, this.cropBoxHeight = (ref3 = opts.cropBoxHeight) != null ? ref3 : 200, this.form = (ref4 = opts.form) != null ? ref4 : this.fileInput.parents('form'), this.filename = opts.filename, this.previewImage = opts.previewImage, this.modalCrop = opts.modalCrop, this.pickImageEl = opts.pickImageEl, this.uploadImageBtn = opts.uploadImageBtn, this.modalCropImg = opts.modalCropImg;
- // Required params
- // Ensure needed elements are jquery objects
- // If selector is provided we will convert them to a jQuery Object
- this.filename = this.getElement(this.filename);
- this.previewImage = this.getElement(this.previewImage);
- this.pickImageEl = this.getElement(this.pickImageEl);
- // Modal elements usually are outside the @form element
- this.modalCrop = _.isString(this.modalCrop) ? $(this.modalCrop) : this.modalCrop;
- this.uploadImageBtn = _.isString(this.uploadImageBtn) ? $(this.uploadImageBtn) : this.uploadImageBtn;
this.modalCropImg = _.isString(this.modalCropImg) ? $(this.modalCropImg) : this.modalCropImg;
+ this.fileInput.attr('name', `${this.fileInput.attr('name')}-trigger`).attr('id', `this.fileInput.attr('id')-trigger`);
+ this.exportWidth = exportWidth;
+ this.exportHeight = exportHeight;
+ this.cropBoxWidth = cropBoxWidth;
+ this.cropBoxHeight = cropBoxHeight;
+ this.form = this.fileInput.parents('form');
+ this.filename = filename;
+ this.previewImage = previewImage;
+ this.modalCrop = modalCrop;
+ this.pickImageEl = pickImageEl;
+ this.uploadImageBtn = uploadImageBtn;
+ this.modalCropImg = modalCropImg;
+ this.filename = this.getElement(filename);
+ this.previewImage = this.getElement(previewImage);
+ this.pickImageEl = this.getElement(pickImageEl);
+ this.modalCrop = _.isString(modalCrop) ? $(modalCrop) : modalCrop;
+ this.uploadImageBtn = _.isString(uploadImageBtn) ? $(uploadImageBtn) : uploadImageBtn;
+ this.modalCropImg = _.isString(modalCropImg) ? $(modalCropImg) : modalCropImg;
this.cropActionsBtn = this.modalCrop.find('[data-method]');
this.bindEvents();
}
- GitLabCrop.prototype.getElement = function(selector) {
+ getElement(selector) {
return $(selector, this.form);
- };
+ }
- GitLabCrop.prototype.bindEvents = function() {
+ bindEvents() {
var _this;
_this = this;
this.fileInput.on('change', function(e) {
@@ -57,13 +55,13 @@
return _this.onActionBtnClick(btn);
});
return this.croppedImageBlob = null;
- };
+ }
- GitLabCrop.prototype.onPickImageClick = function() {
+ onPickImageClick() {
return this.fileInput.trigger('click');
- };
+ }
- GitLabCrop.prototype.onModalShow = function() {
+ onModalShow() {
var _this;
_this = this;
return this.modalCropImg.cropper({
@@ -95,44 +93,44 @@
});
}
});
- };
+ }
- GitLabCrop.prototype.onModalHide = function() {
+ onModalHide() {
return this.modalCropImg.attr('src', '').cropper('destroy');
- };
+ }
- GitLabCrop.prototype.onUploadImageBtnClick = function(e) { // Remove attached image
- e.preventDefault(); // Destroy cropper instance
+ onUploadImageBtnClick(e) {
+ e.preventDefault();
this.setBlob();
this.setPreview();
this.modalCrop.modal('hide');
return this.fileInput.val('');
- };
+ }
- GitLabCrop.prototype.onActionBtnClick = function(btn) {
+ onActionBtnClick(btn) {
var data, result;
data = $(btn).data();
if (this.modalCropImg.data('cropper') && data.method) {
return result = this.modalCropImg.cropper(data.method, data.option);
}
- };
+ }
- GitLabCrop.prototype.onFileInputChange = function(e, input) {
+ onFileInputChange(e, input) {
return this.readFile(input);
- };
+ }
- GitLabCrop.prototype.readFile = function(input) {
+ readFile(input) {
var _this, reader;
_this = this;
reader = new FileReader;
- reader.onload = function() {
+ reader.onload = () => {
_this.modalCropImg.attr('src', reader.result);
return _this.modalCrop.modal('show');
};
return reader.readAsDataURL(input.files[0]);
- };
+ }
- GitLabCrop.prototype.dataURLtoBlob = function(dataURL) {
+ dataURLtoBlob(dataURL) {
var array, binary, i, k, len, v;
binary = atob(dataURL.split(',')[1]);
array = [];
@@ -143,35 +141,32 @@
return new Blob([new Uint8Array(array)], {
type: 'image/png'
});
- };
+ }
- GitLabCrop.prototype.setPreview = function() {
+ setPreview() {
var filename;
this.previewImage.attr('src', this.dataURL);
filename = this.fileInput.val().replace(FILENAMEREGEX, '');
return this.filename.text(filename);
- };
+ }
- GitLabCrop.prototype.setBlob = function() {
+ setBlob() {
this.dataURL = this.modalCropImg.cropper('getCroppedCanvas', {
width: 200,
height: 200
}).toDataURL('image/png');
return this.croppedImageBlob = this.dataURLtoBlob(this.dataURL);
- };
+ }
- GitLabCrop.prototype.getBlob = function() {
+ getBlob() {
return this.croppedImageBlob;
- };
-
- return GitLabCrop;
-
- })();
+ }
+ }
$.fn.glCrop = function(opts) {
return this.each(function() {
return $(this).data('glcrop', new GitLabCrop(this, opts));
});
- };
+ }
-}).call(this);
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
deleted file mode 100644
index 60f9fba5777..00000000000
--- a/app/assets/javascripts/profile/profile.js
+++ /dev/null
@@ -1,106 +0,0 @@
-(function() {
- var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
-
- this.Profile = (function() {
- function Profile(opts) {
- var cropOpts, ref;
- if (opts == null) {
- opts = {};
- }
- this.onSubmitForm = bind(this.onSubmitForm, this);
- this.form = (ref = opts.form) != null ? ref : $('.edit-user');
- $('.js-preferences-form').on('change.preference', 'input[type=radio]', function() {
- return $(this).parents('form').submit();
- // Automatically submit the Preferences form when any of its radio buttons change
- });
- $('#user_notification_email').on('change', function() {
- return $(this).parents('form').submit();
- // Automatically submit email form when it changes
- });
- $('.update-username').on('ajax:before', function() {
- $('.loading-username').show();
- $(this).find('.update-success').hide();
- return $(this).find('.update-failed').hide();
- });
- $('.update-username').on('ajax:complete', function() {
- $('.loading-username').hide();
- $(this).find('.btn-save').enable();
- return $(this).find('.loading-gif').hide();
- });
- $('.update-notifications').on('ajax:success', function(e, data) {
- if (data.saved) {
- return new Flash("Notification settings saved", "notice");
- } else {
- return new Flash("Failed to save new settings", "alert");
- }
- });
- this.bindEvents();
- cropOpts = {
- filename: '.js-avatar-filename',
- previewImage: '.avatar-image .avatar',
- modalCrop: '.modal-profile-crop',
- pickImageEl: '.js-choose-user-avatar-button',
- uploadImageBtn: '.js-upload-user-avatar',
- modalCropImg: '.modal-profile-crop-image'
- };
- this.avatarGlCrop = $('.js-user-avatar-input').glCrop(cropOpts).data('glcrop');
- }
-
- Profile.prototype.bindEvents = function() {
- return this.form.on('submit', this.onSubmitForm);
- };
-
- Profile.prototype.onSubmitForm = function(e) {
- e.preventDefault();
- return this.saveForm();
- };
-
- Profile.prototype.saveForm = function() {
- var avatarBlob, formData, self;
- self = this;
- formData = new FormData(this.form[0]);
- avatarBlob = this.avatarGlCrop.getBlob();
- if (avatarBlob != null) {
- formData.append('user[avatar]', avatarBlob, 'avatar.png');
- }
- return $.ajax({
- url: this.form.attr('action'),
- type: this.form.attr('method'),
- data: formData,
- dataType: "json",
- processData: false,
- contentType: false,
- success: function(response) {
- return new Flash(response.message, 'notice');
- },
- error: function(jqXHR) {
- return new Flash(jqXHR.responseJSON.message, 'alert');
- },
- complete: function() {
- window.scrollTo(0, 0);
- // Enable submit button after requests ends
- return self.form.find(':input[disabled]').enable();
- }
- });
- };
-
- return Profile;
-
- })();
-
- $(function() {
- $(document).on('focusout.ssh_key', '#key_key', function() {
- var $title, comment;
- $title = $('#key_title');
- comment = $(this).val().match(/^\S+ \S+ (.+)\n?$/);
- if (comment && comment.length > 1 && $title.val() === '') {
- return $title.val(comment[1]).change();
- }
- // Extract the SSH Key title from its comment
- });
- if (gl.utils.getPagePath() === 'profiles') {
- return new Profile();
- }
- });
-
-}).call(this);
diff --git a/app/assets/javascripts/profile/profile.js.es6 b/app/assets/javascripts/profile/profile.js.es6
new file mode 100644
index 00000000000..b2307be73ad
--- /dev/null
+++ b/app/assets/javascripts/profile/profile.js.es6
@@ -0,0 +1,100 @@
+((global) => {
+
+ class Profile {
+ constructor({ form } = {}) {
+ this.onSubmitForm = this.onSubmitForm.bind(this);
+ this.form = form || $('.edit-user');
+ this.bindEvents();
+ this.initAvatarGlCrop();
+ }
+
+ initAvatarGlCrop() {
+ const cropOpts = {
+ filename: '.js-avatar-filename',
+ previewImage: '.avatar-image .avatar',
+ modalCrop: '.modal-profile-crop',
+ pickImageEl: '.js-choose-user-avatar-button',
+ uploadImageBtn: '.js-upload-user-avatar',
+ modalCropImg: '.modal-profile-crop-image'
+ };
+ this.avatarGlCrop = $('.js-user-avatar-input').glCrop(cropOpts).data('glcrop');
+ }
+
+ bindEvents() {
+ $('.js-preferences-form').on('change.preference', 'input[type=radio]', this.submitForm);
+ $('#user_notification_email').on('change', this.submitForm);
+ $('.update-username').on('ajax:before', this.beforeUpdateUsername);
+ $('.update-username').on('ajax:complete', this.afterUpdateUsername);
+ $('.update-notifications').on('ajax:success', this.onUpdateNotifs);
+ this.form.on('submit', this.onSubmitForm);
+ }
+
+ submitForm() {
+ return $(this).parents('form').submit();
+ }
+
+ onSubmitForm(e) {
+ e.preventDefault();
+ return this.saveForm();
+ }
+
+ beforeUpdateUsername() {
+ $('.loading-username').show();
+ $(this).find('.update-success').hide();
+ return $(this).find('.update-failed').hide();
+ }
+
+ afterUpdateUsername() {
+ $('.loading-username').hide();
+ $(this).find('.btn-save').enable();
+ return $(this).find('.loading-gif').hide();
+ }
+
+ onUpdateNotifs(e, data) {
+ return data.saved ?
+ new Flash("Notification settings saved", "notice") :
+ new Flash("Failed to save new settings", "alert");
+ }
+
+ saveForm() {
+ const self = this;
+ const formData = new FormData(this.form[0]);
+ const avatarBlob = this.avatarGlCrop.getBlob();
+
+ if (avatarBlob != null) {
+ formData.append('user[avatar]', avatarBlob, 'avatar.png');
+ }
+
+ return $.ajax({
+ url: this.form.attr('action'),
+ type: this.form.attr('method'),
+ data: formData,
+ dataType: "json",
+ processData: false,
+ contentType: false,
+ success: response => new Flash(response.message, 'notice'),
+ error: jqXHR => new Flash(jqXHR.responseJSON.message, 'alert'),
+ complete: () => {
+ window.scrollTo(0, 0);
+ // Enable submit button after requests ends
+ return self.form.find(':input[disabled]').enable();
+ }
+ });
+ }
+ }
+
+ $(function() {
+ $(document).on('focusout.ssh_key', '#key_key', function() {
+ const $title = $('#key_title');
+ const comment = $(this).val().match(/^\S+ \S+ (.+)\n?$/);
+ if (comment && comment.length > 1 && $title.val() === '') {
+ return $title.val(comment[1]).change();
+ }
+ // Extract the SSH Key title from its comment
+ });
+ if (global.utils.getPagePath() === 'profiles') {
+ return new Profile();
+ }
+ });
+
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index 20b147500cf..4239ed2f889 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -23,7 +23,7 @@
data = groups.concat(projects);
return finalCallback(data);
};
- return Api.groups(term, false, groupsCallback);
+ return Api.groups(term, false, false, groupsCallback);
};
} else {
projectsCallback = finalCallback;
@@ -72,7 +72,7 @@
data = groups.concat(projects);
return finalCallback(data);
};
- return Api.groups(query.term, false, groupsCallback);
+ return Api.groups(query.term, false, false, groupsCallback);
};
} else {
projectsCallback = finalCallback;
diff --git a/app/assets/javascripts/search.js b/app/assets/javascripts/search.js
index d34346f862b..8074a94f33e 100644
--- a/app/assets/javascripts/search.js
+++ b/app/assets/javascripts/search.js
@@ -10,7 +10,7 @@
filterable: true,
fieldName: 'group_id',
data: function(term, callback) {
- return Api.groups(term, null, function(data) {
+ return Api.groups(term, false, false, function(data) {
data.unshift({
name: 'Any'
});
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js.es6
index 678d836f56f..b4c6226dc68 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js.es6
@@ -1,30 +1,21 @@
-(function() {
- var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
-
- this.SearchAutocomplete = (function() {
- var KEYCODE;
-
- KEYCODE = {
- ESCAPE: 27,
- BACKSPACE: 8,
- ENTER: 13,
- UP: 38,
- DOWN: 40
- };
-
- function SearchAutocomplete(opts) {
- var ref, ref1, ref2, ref3, ref4;
- if (opts == null) {
- opts = {};
- }
- this.onSearchInputBlur = bind(this.onSearchInputBlur, this);
- this.onClearInputClick = bind(this.onClearInputClick, this);
- this.onSearchInputFocus = bind(this.onSearchInputFocus, this);
- this.onSearchInputClick = bind(this.onSearchInputClick, this);
- this.onSearchInputKeyUp = bind(this.onSearchInputKeyUp, this);
- this.onSearchInputKeyDown = bind(this.onSearchInputKeyDown, this);
- this.wrap = (ref = opts.wrap) != null ? ref : $('.search'), this.optsEl = (ref1 = opts.optsEl) != null ? ref1 : this.wrap.find('.search-autocomplete-opts'), this.autocompletePath = (ref2 = opts.autocompletePath) != null ? ref2 : this.optsEl.data('autocomplete-path'), this.projectId = (ref3 = opts.projectId) != null ? ref3 : this.optsEl.data('autocomplete-project-id') || '', this.projectRef = (ref4 = opts.projectRef) != null ? ref4 : this.optsEl.data('autocomplete-project-ref') || '';
- // Dropdown Element
+((global) => {
+
+ const KEYCODE = {
+ ESCAPE: 27,
+ BACKSPACE: 8,
+ ENTER: 13,
+ UP: 38,
+ DOWN: 40
+ };
+
+ class SearchAutocomplete {
+ constructor({ wrap, optsEl, autocompletePath, projectId, projectRef } = {}) {
+ this.bindEventContext();
+ this.wrap = wrap || $('.search');
+ this.optsEl = optsEl || this.wrap.find('.search-autocomplete-opts');
+ this.autocompletePath = autocompletePath || this.optsEl.data('autocomplete-path');
+ this.projectId = projectId || (this.optsEl.data('autocomplete-project-id') || '');
+ this.projectRef = projectRef || (this.optsEl.data('autocomplete-project-ref') || '');
this.dropdown = this.wrap.find('.dropdown');
this.dropdownContent = this.dropdown.find('.dropdown-content');
this.locationBadgeEl = this.getElement('.location-badge');
@@ -46,19 +37,27 @@
}
// Finds an element inside wrapper element
- SearchAutocomplete.prototype.getElement = function(selector) {
+ bindEventContext() {
+ this.onSearchInputBlur = this.onSearchInputBlur.bind(this);
+ this.onClearInputClick = this.onClearInputClick.bind(this);
+ this.onSearchInputFocus = this.onSearchInputFocus.bind(this);
+ this.onSearchInputClick = this.onSearchInputClick.bind(this);
+ this.onSearchInputKeyUp = this.onSearchInputKeyUp.bind(this);
+ this.onSearchInputKeyDown = this.onSearchInputKeyDown.bind(this);
+ }
+ getElement(selector) {
return this.wrap.find(selector);
- };
+ }
- SearchAutocomplete.prototype.saveOriginalState = function() {
+ saveOriginalState() {
return this.originalState = this.serializeState();
- };
+ }
- SearchAutocomplete.prototype.saveTextLength = function() {
+ saveTextLength() {
return this.lastTextLength = this.searchInput.val().length;
- };
+ }
- SearchAutocomplete.prototype.createAutocomplete = function() {
+ createAutocomplete() {
return this.searchInput.glDropdown({
filterInputBlur: false,
filterable: true,
@@ -73,9 +72,9 @@
selectable: true,
clicked: this.onClick.bind(this)
});
- };
+ }
- SearchAutocomplete.prototype.getData = function(term, callback) {
+ getData(term, callback) {
var _this, contents, jqXHR;
_this = this;
if (!term) {
@@ -138,9 +137,9 @@
}).always(function() {
return _this.loadingSuggestions = false;
});
- };
+ }
- SearchAutocomplete.prototype.getCategoryContents = function() {
+ getCategoryContents() {
var dashboardOptions, groupOptions, issuesPath, items, mrPath, name, options, projectOptions, userId, utils;
userId = gon.current_user_id;
utils = gl.utils, projectOptions = gl.projectOptions, groupOptions = gl.groupOptions, dashboardOptions = gl.dashboardOptions;
@@ -173,9 +172,9 @@
items.splice(0, 1);
}
return items;
- };
+ }
- SearchAutocomplete.prototype.serializeState = function() {
+ serializeState() {
return {
// Search Criteria
search_project_id: this.projectInputEl.val(),
@@ -186,9 +185,9 @@
// Location badge
_location: this.locationBadgeEl.text()
};
- };
+ }
- SearchAutocomplete.prototype.bindEvents = function() {
+ bindEvents() {
this.searchInput.on('keydown', this.onSearchInputKeyDown);
this.searchInput.on('keyup', this.onSearchInputKeyUp);
this.searchInput.on('click', this.onSearchInputClick);
@@ -200,9 +199,9 @@
return _this.searchInput.focus();
};
})(this));
- };
+ }
- SearchAutocomplete.prototype.enableAutocomplete = function() {
+ enableAutocomplete() {
var _this;
// No need to enable anything if user is not logged in
if (!gon.current_user_id) {
@@ -216,12 +215,12 @@
}
};
- SearchAutocomplete.prototype.onSearchInputKeyDown = function() {
// Saves last length of the entered text
+ onSearchInputKeyDown() {
return this.saveTextLength();
- };
+ }
- SearchAutocomplete.prototype.onSearchInputKeyUp = function(e) {
+ onSearchInputKeyUp(e) {
switch (e.keyCode) {
case KEYCODE.BACKSPACE:
// when trying to remove the location badge
@@ -259,54 +258,53 @@
}
}
this.wrap.toggleClass('has-value', !!e.target.value);
- };
+ }
// Avoid falsy value to be returned
- SearchAutocomplete.prototype.onSearchInputClick = function(e) {
- // Prevents closing the dropdown menu
+ onSearchInputClick(e) {
return e.stopImmediatePropagation();
- };
+ }
- SearchAutocomplete.prototype.onSearchInputFocus = function() {
+ onSearchInputFocus() {
this.isFocused = true;
this.wrap.addClass('search-active');
if (this.getValue() === '') {
return this.getData();
}
- };
+ }
- SearchAutocomplete.prototype.getValue = function() {
+ getValue() {
return this.searchInput.val();
- };
+ }
- SearchAutocomplete.prototype.onClearInputClick = function(e) {
+ onClearInputClick(e) {
e.preventDefault();
return this.searchInput.val('').focus();
- };
+ }
- SearchAutocomplete.prototype.onSearchInputBlur = function(e) {
+ onSearchInputBlur(e) {
this.isFocused = false;
this.wrap.removeClass('search-active');
// If input is blank then restore state
if (this.searchInput.val() === '') {
return this.restoreOriginalState();
}
- };
+ }
- SearchAutocomplete.prototype.addLocationBadge = function(item) {
+ addLocationBadge(item) {
var badgeText, category, value;
category = item.category != null ? item.category + ": " : '';
value = item.value != null ? item.value : '';
badgeText = "" + category + value;
this.locationBadgeEl.text(badgeText).show();
return this.wrap.addClass('has-location-badge');
- };
+ }
- SearchAutocomplete.prototype.hasLocationBadge = function() {
+ hasLocationBadge() {
return this.wrap.is('.has-location-badge');
};
- SearchAutocomplete.prototype.restoreOriginalState = function() {
+ restoreOriginalState() {
var i, input, inputs, len;
inputs = Object.keys(this.originalState);
for (i = 0, len = inputs.length; i < len; i++) {
@@ -320,13 +318,13 @@
value: this.originalState._location
});
}
- };
+ }
- SearchAutocomplete.prototype.badgePresent = function() {
+ badgePresent() {
return this.locationBadgeEl.length;
- };
+ }
- SearchAutocomplete.prototype.resetSearchState = function() {
+ resetSearchState() {
var i, input, inputs, len, results;
inputs = Object.keys(this.originalState);
results = [];
@@ -339,30 +337,30 @@
results.push(this.getElement("#" + input).val(''));
}
return results;
- };
+ }
- SearchAutocomplete.prototype.removeLocationBadge = function() {
+ removeLocationBadge() {
this.locationBadgeEl.hide();
this.resetSearchState();
this.wrap.removeClass('has-location-badge');
return this.disableAutocomplete();
- };
+ }
- SearchAutocomplete.prototype.disableAutocomplete = function() {
+ disableAutocomplete() {
if (!this.searchInput.hasClass('disabled') && this.dropdown.hasClass('open')) {
this.searchInput.addClass('disabled');
this.dropdown.removeClass('open').trigger('hidden.bs.dropdown');
this.restoreMenu();
}
- };
+ }
- SearchAutocomplete.prototype.restoreMenu = function() {
+ restoreMenu() {
var html;
html = "<ul> <li><a class='dropdown-menu-empty-link is-focused'>Loading...</a></li> </ul>";
return this.dropdownContent.html(html);
};
- SearchAutocomplete.prototype.onClick = function(item, $el, e) {
+ onClick(item, $el, e) {
if (location.pathname.indexOf(item.url) !== -1) {
e.preventDefault();
if (!this.badgePresent) {
@@ -385,9 +383,9 @@
}
};
- return SearchAutocomplete;
+ }
- })();
+ global.SearchAutocomplete = SearchAutocomplete;
$(function() {
var $projectOptionsDataEl = $('.js-search-project-options');
@@ -408,16 +406,16 @@
if ($groupOptionsDataEl.length) {
gl.groupOptions = gl.groupOptions || {};
-
+
var groupPath = $groupOptionsDataEl.data('group-path');
-
+
gl.groupOptions[groupPath] = {
name: $groupOptionsDataEl.data('name'),
issuesPath: $groupOptionsDataEl.data('issues-path'),
mrPath: $groupOptionsDataEl.data('mr-path')
};
}
-
+
if ($dashboardOptionsDataEl.length) {
gl.dashboardOptions = {
issuesPath: $dashboardOptionsDataEl.data('issues-path'),
@@ -426,4 +424,4 @@
}
});
-}).call(this);
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js.es6 b/app/assets/javascripts/templates/issuable_template_selector.js.es6
index c32ddf80219..2ecf3b18975 100644
--- a/app/assets/javascripts/templates/issuable_template_selector.js.es6
+++ b/app/assets/javascripts/templates/issuable_template_selector.js.es6
@@ -1,7 +1,7 @@
/*= require ../blob/template_selector */
((global) => {
- class IssuableTemplateSelector extends TemplateSelector {
+ class IssuableTemplateSelector extends gl.TemplateSelector {
constructor(...args) {
super(...args);
this.projectPath = this.dropdown.data('project-path');
@@ -16,7 +16,7 @@
if (initialQuery.name) this.requestFile(initialQuery);
$('.reset-template', this.dropdown.parent()).on('click', () => {
- if (this.currentTemplate) this.setInputValueToTemplateContent();
+ if (this.currentTemplate) this.setInputValueToTemplateContent(false);
});
}
@@ -26,26 +26,28 @@
this.currentTemplate = currentTemplate;
if (err) return; // Error handled by global AJAX error handler
this.stopLoadingSpinner();
- this.setInputValueToTemplateContent();
+ this.setInputValueToTemplateContent(true);
});
return;
}
- setInputValueToTemplateContent() {
+ setInputValueToTemplateContent(append) {
// `this.requestFileSuccess` sets the value of the description input field
- // to the content of the template selected.
+ // to the content of the template selected. If `append` is true, the
+ // template content will be appended to the previous value of the field,
+ // separated by a blank line if the previous value is non-empty.
if (this.titleInput.val() === '') {
// If the title has not yet been set, focus the title input and
- // skip focusing the description input by setting `true` as the 2nd
- // argument to `requestFileSuccess`.
- this.requestFileSuccess(this.currentTemplate, true);
+ // skip focusing the description input by setting `true` as the
+ // `skipFocus` option to `requestFileSuccess`.
+ this.requestFileSuccess(this.currentTemplate, {skipFocus: true, append});
this.titleInput.focus();
} else {
- this.requestFileSuccess(this.currentTemplate);
+ this.requestFileSuccess(this.currentTemplate, {skipFocus: false, append});
}
return;
}
}
global.IssuableTemplateSelector = IssuableTemplateSelector;
-})(window);
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/templates/issuable_template_selectors.js.es6 b/app/assets/javascripts/templates/issuable_template_selectors.js.es6
index bd8cdde033e..4e8247b89e1 100644
--- a/app/assets/javascripts/templates/issuable_template_selectors.js.es6
+++ b/app/assets/javascripts/templates/issuable_template_selectors.js.es6
@@ -1,12 +1,12 @@
((global) => {
class IssuableTemplateSelectors {
- constructor(opts = {}) {
- this.$dropdowns = opts.$dropdowns || $('.js-issuable-selector');
- this.editor = opts.editor || this.initEditor();
+ constructor({ $dropdowns, editor } = {}) {
+ this.$dropdowns = $dropdowns || $('.js-issuable-selector');
+ this.editor = editor || this.initEditor();
this.$dropdowns.each((i, dropdown) => {
- let $dropdown = $(dropdown);
- new IssuableTemplateSelector({
+ const $dropdown = $(dropdown);
+ new gl.IssuableTemplateSelector({
pattern: /(\.md)/,
data: $dropdown.data('data'),
wrapper: $dropdown.closest('.js-issuable-selector-wrap'),
@@ -26,4 +26,4 @@
}
global.IssuableTemplateSelectors = IssuableTemplateSelectors;
-})(window);
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/todos.js b/app/assets/javascripts/todos.js.es6
index 93421649ac7..055228c5df8 100644
--- a/app/assets/javascripts/todos.js
+++ b/app/assets/javascripts/todos.js.es6
@@ -1,34 +1,29 @@
-(function() {
- var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
-
- this.Todos = (function() {
- function Todos(opts) {
- var ref;
- if (opts == null) {
- opts = {};
- }
- this.allDoneClicked = bind(this.allDoneClicked, this);
- this.doneClicked = bind(this.doneClicked, this);
- this.el = (ref = opts.el) != null ? ref : $('.js-todos-options');
+((global) => {
+
+ class Todos {
+ constructor({ el } = {}) {
+ this.allDoneClicked = this.allDoneClicked.bind(this);
+ this.doneClicked = this.doneClicked.bind(this);
+ this.el = el || $('.js-todos-options');
this.perPage = this.el.data('perPage');
this.clearListeners();
this.initBtnListeners();
this.initFilters();
}
- Todos.prototype.clearListeners = function() {
+ clearListeners() {
$('.done-todo').off('click');
$('.js-todos-mark-all').off('click');
return $('.todo').off('click');
- };
+ }
- Todos.prototype.initBtnListeners = function() {
+ initBtnListeners() {
$('.done-todo').on('click', this.doneClicked);
$('.js-todos-mark-all').on('click', this.allDoneClicked);
return $('.todo').on('click', this.goToTodoUrl);
- };
+ }
- Todos.prototype.initFilters = function() {
+ initFilters() {
new UsersSelect();
this.initFilterDropdown($('.js-project-search'), 'project_id', ['text']);
this.initFilterDropdown($('.js-type-search'), 'type');
@@ -38,125 +33,117 @@
event.preventDefault();
Turbolinks.visit(this.action + '&' + $(this).serialize());
});
- };
+ }
- Todos.prototype.initFilterDropdown = function($dropdown, fieldName, searchFields) {
+ initFilterDropdown($dropdown, fieldName, searchFields) {
$dropdown.glDropdown({
+ fieldName,
selectable: true,
filterable: searchFields ? true : false,
- fieldName: fieldName,
search: { fields: searchFields },
data: $dropdown.data('data'),
clicked: function() {
return $dropdown.closest('form.filter-form').submit();
}
})
- };
+ }
- Todos.prototype.doneClicked = function(e) {
- var $this;
+ doneClicked(e) {
e.preventDefault();
e.stopImmediatePropagation();
- $this = $(e.currentTarget);
- $this.disable();
+ const $target = $(e.currentTarget);
+ $target.disable();
return $.ajax({
type: 'POST',
- url: $this.attr('href'),
+ url: $target.attr('href'),
dataType: 'json',
data: {
'_method': 'delete'
},
- success: (function(_this) {
- return function(data) {
- _this.redirectIfNeeded(data.count);
- _this.clearDone($this.closest('li'));
- return _this.updateBadges(data);
- };
- })(this)
+ success: (data) => {
+ this.redirectIfNeeded(data.count);
+ this.clearDone($target.closest('li'));
+ return this.updateBadges(data);
+ }
});
- };
+ }
- Todos.prototype.allDoneClicked = function(e) {
- var $this;
+ allDoneClicked(e) {
e.preventDefault();
e.stopImmediatePropagation();
- $this = $(e.currentTarget);
- $this.disable();
+ $target = $(e.currentTarget);
+ $target.disable();
return $.ajax({
type: 'POST',
- url: $this.attr('href'),
+ url: $target.attr('href'),
dataType: 'json',
data: {
'_method': 'delete'
},
- success: (function(_this) {
- return function(data) {
- $this.remove();
- $('.prepend-top-default').html('<div class="nothing-here-block">You\'re all done!</div>');
- return _this.updateBadges(data);
- };
- })(this)
+ success: (data) => {
+ $target.remove();
+ $('.prepend-top-default').html('<div class="nothing-here-block">You\'re all done!</div>');
+ return this.updateBadges(data);
+ }
});
- };
+ }
- Todos.prototype.clearDone = function($row) {
- var $ul;
- $ul = $row.closest('ul');
+ clearDone($row) {
+ const $ul = $row.closest('ul');
$row.remove();
if (!$ul.find('li').length) {
return $ul.parents('.panel').remove();
}
- };
+ }
- Todos.prototype.updateBadges = function(data) {
+ updateBadges(data) {
$('.todos-pending .badge, .todos-pending-count').text(data.count);
return $('.todos-done .badge').text(data.done_count);
- };
+ }
- Todos.prototype.getTotalPages = function() {
+ getTotalPages() {
return this.el.data('totalPages');
- };
+ }
- Todos.prototype.getCurrentPage = function() {
+ getCurrentPage() {
return this.el.data('currentPage');
- };
+ }
- Todos.prototype.getTodosPerPage = function() {
+ getTodosPerPage() {
return this.el.data('perPage');
- };
+ }
+
+ redirectIfNeeded(total) {
+ const currPages = this.getTotalPages();
+ const currPage = this.getCurrentPage();
- Todos.prototype.redirectIfNeeded = function(total) {
- var currPage, currPages, newPages, pageParams, url;
- currPages = this.getTotalPages();
- currPage = this.getCurrentPage();
// Refresh if no remaining Todos
if (!total) {
- location.reload();
+ window.location.reload();
return;
}
// Do nothing if no pagination
if (!currPages) {
return;
}
- newPages = Math.ceil(total / this.getTodosPerPage());
- // Includes query strings
- url = location.href;
- // If new total of pages is different than we have now
+
+ const newPages = Math.ceil(total / this.getTodosPerPage());
+ let url = location.href;
+
if (newPages !== currPages) {
// Redirect to previous page if there's one available
if (currPages > 1 && currPage === currPages) {
- pageParams = {
+ const pageParams = {
page: currPages - 1
};
url = gl.utils.mergeUrlParams(pageParams, url);
}
return Turbolinks.visit(url);
}
- };
+ }
- Todos.prototype.goToTodoUrl = function(e) {
- var todoLink;
- todoLink = $(this).data('url');
+ goToTodoUrl(e) {
+ const todoLink = $(this).data('url');
if (!todoLink) {
return;
}
@@ -167,10 +154,8 @@
} else {
return Turbolinks.visit(todoLink);
}
- };
-
- return Todos;
-
- })();
+ }
+ }
-}).call(this);
+ global.Todos = Todos;
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/user.js.es6 b/app/assets/javascripts/user.js.es6
index 6889d3a7491..0f97924d94e 100644
--- a/app/assets/javascripts/user.js.es6
+++ b/app/assets/javascripts/user.js.es6
@@ -1,7 +1,7 @@
-(global => {
+((global) => {
global.User = class {
- constructor(opts) {
- this.opts = opts;
+ constructor({ action }) {
+ this.action = action;
this.placeProfileAvatarsToTop();
this.initTabs();
this.hideProjectLimitMessage();
@@ -14,9 +14,9 @@
}
initTabs() {
- return new UserTabs({
+ return new global.UserTabs({
parentEl: '.user-profile',
- action: this.opts.action
+ action: this.action
});
}
diff --git a/app/assets/javascripts/user_tabs.js b/app/assets/javascripts/user_tabs.js
deleted file mode 100644
index 8a657780eb6..00000000000
--- a/app/assets/javascripts/user_tabs.js
+++ /dev/null
@@ -1,188 +0,0 @@
-// UserTabs
-//
-// Handles persisting and restoring the current tab selection and lazily-loading
-// content on the Users#show page.
-//
-// ### Example Markup
-//
-// <ul class="nav-links">
-// <li class="activity-tab active">
-// <a data-action="activity" data-target="#activity" data-toggle="tab" href="/u/username">
-// Activity
-// </a>
-// </li>
-// <li class="groups-tab">
-// <a data-action="groups" data-target="#groups" data-toggle="tab" href="/u/username/groups">
-// Groups
-// </a>
-// </li>
-// <li class="contributed-tab">
-// <a data-action="contributed" data-target="#contributed" data-toggle="tab" href="/u/username/contributed">
-// Contributed projects
-// </a>
-// </li>
-// <li class="projects-tab">
-// <a data-action="projects" data-target="#projects" data-toggle="tab" href="/u/username/projects">
-// Personal projects
-// </a>
-// </li>
-// <li class="snippets-tab">
-// <a data-action="snippets" data-target="#snippets" data-toggle="tab" href="/u/username/snippets">
-// </a>
-// </li>
-// </ul>
-//
-// <div class="tab-content">
-// <div class="tab-pane" id="activity">
-// Activity Content
-// </div>
-// <div class="tab-pane" id="groups">
-// Groups Content
-// </div>
-// <div class="tab-pane" id="contributed">
-// Contributed projects content
-// </div>
-// <div class="tab-pane" id="projects">
-// Projects content
-// </div>
-// <div class="tab-pane" id="snippets">
-// Snippets content
-// </div>
-// </div>
-//
-// <div class="loading-status">
-// <div class="loading">
-// Loading Animation
-// </div>
-// </div>
-//
-(function() {
- var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
-
- this.UserTabs = (function() {
- function UserTabs(opts) {
- this.tabShown = bind(this.tabShown, this);
- var i, item, len, ref, ref1, ref2, ref3;
- this.action = (ref = opts.action) != null ? ref : 'activity', this.defaultAction = (ref1 = opts.defaultAction) != null ? ref1 : 'activity', this.parentEl = (ref2 = opts.parentEl) != null ? ref2 : $(document);
- // Make jQuery object if selector is provided
- if (typeof this.parentEl === 'string') {
- this.parentEl = $(this.parentEl);
- }
- // Store the `location` object, allowing for easier stubbing in tests
- this._location = location;
- // Set tab states
- this.loaded = {};
- ref3 = this.parentEl.find('.nav-links a');
- for (i = 0, len = ref3.length; i < len; i++) {
- item = ref3[i];
- this.loaded[$(item).attr('data-action')] = false;
- }
- // Actions
- this.actions = Object.keys(this.loaded);
- this.bindEvents();
- // Set active tab
- if (this.action === 'show') {
- this.action = this.defaultAction;
- }
- this.activateTab(this.action);
- }
-
- UserTabs.prototype.bindEvents = function() {
- // Toggle event listeners
- return this.parentEl.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]').on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', this.tabShown);
- };
-
- UserTabs.prototype.tabShown = function(event) {
- var $target, action, source;
- $target = $(event.target);
- action = $target.data('action');
- source = $target.attr('href');
- this.setTab(source, action);
- return this.setCurrentAction(action);
- };
-
- UserTabs.prototype.activateTab = function(action) {
- return this.parentEl.find(".nav-links .js-" + action + "-tab a").tab('show');
- };
-
- UserTabs.prototype.setTab = function(source, action) {
- if (this.loaded[action] === true) {
- return;
- }
- if (action === 'activity') {
- this.loadActivities(source);
- }
- if (action === 'groups' || action === 'contributed' || action === 'projects' || action === 'snippets') {
- return this.loadTab(source, action);
- }
- };
-
- UserTabs.prototype.loadTab = function(source, action) {
- return $.ajax({
- beforeSend: (function(_this) {
- return function() {
- return _this.toggleLoading(true);
- };
- })(this),
- complete: (function(_this) {
- return function() {
- return _this.toggleLoading(false);
- };
- })(this),
- dataType: 'json',
- type: 'GET',
- url: source + ".json",
- success: (function(_this) {
- return function(data) {
- var tabSelector;
- tabSelector = 'div#' + action;
- _this.parentEl.find(tabSelector).html(data.html);
- _this.loaded[action] = true;
- // Fix tooltips
- return gl.utils.localTimeAgo($('.js-timeago', tabSelector));
- };
- })(this)
- });
- };
-
- UserTabs.prototype.loadActivities = function(source) {
- var $calendarWrap;
- if (this.loaded['activity'] === true) {
- return;
- }
- $calendarWrap = this.parentEl.find('.user-calendar');
- $calendarWrap.load($calendarWrap.data('href'));
- new Activities();
- return this.loaded['activity'] = true;
- };
-
- UserTabs.prototype.toggleLoading = function(status) {
- return this.parentEl.find('.loading-status .loading').toggle(status);
- };
-
- UserTabs.prototype.setCurrentAction = function(action) {
- var new_state, regExp;
- // Remove possible actions from URL
- regExp = new RegExp('\/(' + this.actions.join('|') + ')(\.html)?\/?$');
- new_state = this._location.pathname;
- // remove trailing slashes
- new_state = new_state.replace(/\/+$/, "");
- new_state = new_state.replace(regExp, '');
- // Append the new action if we're on a tab other than 'activity'
- if (action !== this.defaultAction) {
- new_state += "/" + action;
- }
- // Ensure parameters and hash come along for the ride
- new_state += this._location.search + this._location.hash;
- history.replaceState({
- turbolinks: true,
- url: new_state
- }, document.title, new_state);
- return new_state;
- };
-
- return UserTabs;
-
- })();
-
-}).call(this);
diff --git a/app/assets/javascripts/user_tabs.js.es6 b/app/assets/javascripts/user_tabs.js.es6
new file mode 100644
index 00000000000..dfdfa1e7f75
--- /dev/null
+++ b/app/assets/javascripts/user_tabs.js.es6
@@ -0,0 +1,157 @@
+/*
+UserTabs
+
+Handles persisting and restoring the current tab selection and lazily-loading
+content on the Users#show page.
+
+### Example Markup
+
+ <ul class="nav-links">
+ <li class="activity-tab active">
+ <a data-action="activity" data-target="#activity" data-toggle="tab" href="/u/username">
+ Activity
+ </a>
+ </li>
+ <li class="groups-tab">
+ <a data-action="groups" data-target="#groups" data-toggle="tab" href="/u/username/groups">
+ Groups
+ </a>
+ </li>
+ <li class="contributed-tab">
+ <a data-action="contributed" data-target="#contributed" data-toggle="tab" href="/u/username/contributed">
+ Contributed projects
+ </a>
+ </li>
+ <li class="projects-tab">
+ <a data-action="projects" data-target="#projects" data-toggle="tab" href="/u/username/projects">
+ Personal projects
+ </a>
+ </li>
+ <li class="snippets-tab">
+ <a data-action="snippets" data-target="#snippets" data-toggle="tab" href="/u/username/snippets">
+ </a>
+ </li>
+ </ul>
+
+ <div class="tab-content">
+ <div class="tab-pane" id="activity">
+ Activity Content
+ </div>
+ <div class="tab-pane" id="groups">
+ Groups Content
+ </div>
+ <div class="tab-pane" id="contributed">
+ Contributed projects content
+ </div>
+ <div class="tab-pane" id="projects">
+ Projects content
+ </div>
+ <div class="tab-pane" id="snippets">
+ Snippets content
+ </div>
+ </div>
+
+ <div class="loading-status">
+ <div class="loading">
+ Loading Animation
+ </div>
+ </div>
+*/
+((global) => {
+ class UserTabs {
+ constructor ({ defaultAction, action, parentEl }) {
+ this.loaded = {};
+ this.defaultAction = defaultAction || 'activity';
+ this.action = action || this.defaultAction;
+ this.$parentEl = $(parentEl) || $(document);
+ this._location = window.location;
+ this.$parentEl.find('.nav-links a')
+ .each((i, navLink) => {
+ this.loaded[$(navLink).attr('data-action')] = false;
+ });
+ this.actions = Object.keys(this.loaded);
+ this.bindEvents();
+
+ if (this.action === 'show') {
+ this.action = this.defaultAction;
+ }
+
+ this.activateTab(this.action);
+ }
+
+ bindEvents() {
+ return this.$parentEl.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
+ .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event));
+ }
+
+ tabShown(event) {
+ const $target = $(event.target);
+ const action = $target.data('action');
+ const source = $target.attr('href');
+ this.setTab(source, action);
+ return this.setCurrentAction(source, action);
+ }
+
+ activateTab(action) {
+ return this.$parentEl.find(`.nav-links .js-${action}-tab a`)
+ .tab('show');
+ }
+
+ setTab(source, action) {
+ if (this.loaded[action]) {
+ return;
+ }
+ if (action === 'activity') {
+ this.loadActivities(source);
+ }
+
+ const loadableActions = [ 'groups', 'contributed', 'projects', 'snippets' ];
+ if (loadableActions.indexOf(action) > -1) {
+ return this.loadTab(source, action);
+ }
+ }
+
+ loadTab(source, action) {
+ return $.ajax({
+ beforeSend: () => this.toggleLoading(true),
+ complete: () => this.toggleLoading(false),
+ dataType: 'json',
+ type: 'GET',
+ url: `${source}.json`,
+ success: (data) => {
+ const tabSelector = `div#${action}`;
+ this.$parentEl.find(tabSelector).html(data.html);
+ this.loaded[action] = true;
+ return gl.utils.localTimeAgo($('.js-timeago', tabSelector));
+ }
+ });
+ }
+
+ loadActivities(source) {
+ if (this.loaded['activity']) {
+ return;
+ }
+ const $calendarWrap = this.$parentEl.find('.user-calendar');
+ $calendarWrap.load($calendarWrap.data('href'));
+ new Activities();
+ return this.loaded['activity'] = true;
+ }
+
+ toggleLoading(status) {
+ return this.$parentEl.find('.loading-status .loading')
+ .toggle(status);
+ }
+
+ setCurrentAction(source, action) {
+ let new_state = source
+ new_state = new_state.replace(/\/+$/, '');
+ new_state += this._location.search + this._location.hash;
+ history.replaceState({
+ turbolinks: true,
+ url: new_state
+ }, document.title, new_state);
+ return new_state;
+ }
+ }
+ global.UserTabs = UserTabs;
+})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index 9c277998db4..bcabda3ceb2 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -14,11 +14,12 @@
$('.js-user-search').each((function(_this) {
return function(i, dropdown) {
var options = {};
- var $block, $collapsedSidebar, $dropdown, $loading, $selectbox, $value, abilityName, assignTo, assigneeTemplate, collapsedAssigneeTemplate, defaultLabel, firstUser, issueURL, selectedId, showAnyUser, showNullUser;
+ var $block, $collapsedSidebar, $dropdown, $loading, $selectbox, $value, abilityName, assignTo, assigneeTemplate, collapsedAssigneeTemplate, defaultLabel, firstUser, issueURL, selectedId, showAnyUser, showNullUser, showMenuAbove;
$dropdown = $(dropdown);
options.projectId = $dropdown.data('project-id');
options.showCurrentUser = $dropdown.data('current-user');
showNullUser = $dropdown.data('null-user');
+ showMenuAbove = $dropdown.data('showMenuAbove');
showAnyUser = $dropdown.data('any-user');
firstUser = $dropdown.data('first-user');
options.authorId = $dropdown.data('author-id');
@@ -70,9 +71,10 @@
return $collapsedSidebar.html(collapsedAssigneeTemplate(user));
});
};
- collapsedAssigneeTemplate = _.template('<% if( avatar ) { %> <a class="author_link" href="/u/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>');
- assigneeTemplate = _.template('<% if (username) { %> <a class="author_link bold" href="/u/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself"> No assignee - <a href="#" class="js-assign-yourself"> assign yourself </a> </span> <% } %>');
+ collapsedAssigneeTemplate = _.template('<% if( avatar ) { %> <a class="author_link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>');
+ assigneeTemplate = _.template('<% if (username) { %> <a class="author_link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself"> No assignee - <a href="#" class="js-assign-yourself"> assign yourself </a> </span> <% } %>');
return $dropdown.glDropdown({
+ showMenuAbove: showMenuAbove,
data: function(term, callback) {
var isAuthorFilter;
isAuthorFilter = $('.js-author-search');
@@ -116,8 +118,11 @@
if (showDivider) {
users.splice(showDivider, 0, "divider");
}
- // Send the data back
- return callback(users);
+
+ callback(users);
+ if (showMenuAbove) {
+ $dropdown.data('glDropdown').positionMenuAbove();
+ }
});
},
filterable: true,
@@ -127,8 +132,8 @@
},
selectable: true,
fieldName: $dropdown.data('field-name'),
- toggleLabel: function(selected) {
- if (selected && 'id' in selected) {
+ toggleLabel: function(selected, el) {
+ if (selected && 'id' in selected && $(el).hasClass('is-active')) {
if (selected.text) {
return selected.text;
} else {
@@ -138,6 +143,7 @@
return defaultLabel;
}
},
+ defaultLabel: defaultLabel,
inputId: 'issue_assignee_id',
hidden: function(e) {
$selectbox.hide();
@@ -149,7 +155,9 @@
page = $('body').data('page');
isIssueIndex = page === 'projects:issues:index';
isMRIndex = (page === page && page === 'projects:merge_requests:index');
- if ($dropdown.hasClass('js-filter-bulk-update')) {
+ if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
+ e.preventDefault();
+ selectedId = user.id;
return;
}
if (page === 'projects:boards:show') {
@@ -167,6 +175,9 @@
return assignTo(selected);
}
},
+ id: function (user) {
+ return user.id;
+ },
renderRow: function(user) {
var avatar, img, listClosingTags, listWithName, listWithUserName, selected, username;
username = user.username ? "@" + user.username : "";
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index ce489f7c3de..d11b2fe7ec2 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -194,10 +194,17 @@
pointer-events: none !important;
}
- .caret {
+ .fa-caret-down,
+ .fa-caret-up {
margin-left: 5px;
}
+ &.dropdown-toggle {
+ .fa-caret-down {
+ margin-left: 3px;
+ }
+ }
+
svg {
height: 15px;
width: 15px;
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index b0ba112476b..baa95711329 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -1,20 +1,3 @@
-.caret {
- display: inline-block;
- width: 0;
- height: 0;
- margin-left: 2px;
- vertical-align: middle;
- border-top: $caret-width-base dashed;
- border-right: $caret-width-base solid transparent;
- border-left: $caret-width-base solid transparent;
-}
-
-.btn-group {
- .caret {
- margin-left: 0;
- }
-}
-
.dropdown {
position: relative;
@@ -604,3 +587,9 @@
display: block;
color: $gl-placeholder-color;
}
+
+.dropdown-toggle-text {
+ &.is-default {
+ color: $gl-placeholder-color;
+ }
+}
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index 3ac1678dd05..a55dcf4a699 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -21,7 +21,8 @@
.flash-notice, .flash-alert {
border-radius: $border-radius-default;
- .container-fluid.container-limited.flash-text {
+ .container-fluid,
+ .container-fluid.container-limited {
background: transparent;
}
}
@@ -35,12 +36,6 @@
}
}
-.content-wrapper {
- .flash-notice .container-fluid {
- background-color: transparent;
- }
-}
-
@media (max-width: $screen-md-min) {
ul.notes {
.flash-container.timeline-content {
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index 37ff7e22ed1..a67d31de2f7 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -81,10 +81,10 @@ label {
.select-wrapper {
position: relative;
- .caret {
+ .fa-caret-down {
position: absolute;
right: 10px;
- top: $gl-padding;
+ top: 10px;
color: $gray-darkest;
pointer-events: none;
}
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index c748f856501..9823abdde1f 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -57,6 +57,10 @@ header {
&:hover, &:focus, &:active {
background-color: $background-color;
}
+
+ .fa-caret-down {
+ font-size: 15px;
+ }
}
.navbar-toggle {
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index c75dacf95d9..bcd60391543 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -21,7 +21,14 @@
padding-right: 10px;
b {
- @extend .caret;
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 2px;
+ vertical-align: middle;
+ border-top: $caret-width-base dashed;
+ border-right: $caret-width-base solid transparent;
+ border-left: $caret-width-base solid transparent;
color: $gray-darkest;
}
}
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index ecc5b24e360..6e81c12aa55 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -162,6 +162,10 @@ lex
list-style: none;
overflow-y: scroll;
overflow-x: hidden;
+
+ &.is-smaller {
+ height: calc(100% - 185px);
+ }
}
.board-list-loading {
@@ -233,3 +237,31 @@ lex
margin-right: 5px;
}
}
+
+.board-new-issue-form {
+ margin: 5px;
+}
+
+.board-issue-count-holder {
+ margin-top: -3px;
+
+ .btn {
+ line-height: 12px;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+}
+
+.board-issue-count {
+ padding-right: 10px;
+ padding-left: 10px;
+ line-height: 21px;
+ border-radius: $border-radius-base;
+ border: 1px solid $border-color;
+
+ &.has-btn {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-width: 1px 0 1px 1px;
+ }
+}
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index d01c60ee6ab..3f19e920166 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -1,4 +1,15 @@
+.environments-container,
+.deployments-container {
+ width: 100%;
+ overflow: auto;
+}
+
.environments {
+ .deployment-column {
+ .avatar {
+ float: none;
+ }
+ }
.commit-title {
margin: 0;
@@ -9,6 +20,7 @@
width: 12px;
}
+ .external-url,
.dropdown-new {
color: $table-text-gray;
}
@@ -21,16 +33,35 @@
}
}
+ .build-link,
.branch-name {
color: $gl-dark-link-color;
}
+
+ .deployment {
+ .build-column {
+
+ .build-link {
+ color: $gl-dark-link-color;
+ }
+
+ .avatar {
+ float: none;
+ }
+ }
+ }
}
.table.builds.environments {
- min-width: 500px;
.icon-container {
width: 20px;
text-align: center;
}
+
+ .branch-commit {
+ .commit-id {
+ margin-right: 0;
+ }
+ }
}
diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss
index 38c7cd98e41..822830706a5 100644
--- a/app/assets/stylesheets/pages/labels.scss
+++ b/app/assets/stylesheets/pages/labels.scss
@@ -59,6 +59,13 @@
width: 200px;
margin-bottom: 0;
}
+
+ .label {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ max-width: 100%;
+ }
}
.label-description {
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 926247e5e87..bc8693ae467 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -70,7 +70,8 @@
&.ci-success {
color: $gl-success;
- a.environment {
+ a.environment,
+ a.pipeline {
color: inherit;
}
}
@@ -349,6 +350,10 @@
.issuable-form-select-holder {
display: inline-block;
width: 250px;
+
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
}
.table-holder {
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index b035bfc9f3c..a2779704eff 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -22,6 +22,11 @@
.table.builds {
min-width: 1200px;
+
+ .branch-commit {
+ width: 33%;
+ }
+
}
}
@@ -224,9 +229,12 @@
.fa {
color: $table-text-gray;
- margin-right: 6px;
font-size: 14px;
}
+
+ svg, .fa {
+ margin-right: 0;
+ }
}
.btn-remove {
@@ -267,18 +275,8 @@
.toggle-pipeline-btn {
background-color: $gray-dark;
- .caret {
- border-top: none;
- border-bottom: 4px solid;
- }
-
&.graph-collapsed {
background-color: $white-light;
-
- .caret {
- border-bottom: none;
- border-top: 4px solid;
- }
}
}
@@ -385,6 +383,8 @@
left: auto;
right: -214px;
top: -9px;
+ max-height: 245px;
+ overflow-y: scroll;
a:hover {
.ci-status-text {
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 0fcdaf94a21..c7eac5cf4b9 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -94,7 +94,7 @@
.profile-user-bio {
// Limits the width of the user bio for readability.
max-width: 600px;
- margin: 15px auto 0;
+ margin: 10px auto;
padding: 0 16px;
}
@@ -213,29 +213,22 @@
}
.user-profile {
+
.cover-controls a {
margin-left: 5px;
}
+
.profile-header {
margin: 0 auto;
+
.avatar-holder {
width: 90px;
- display: inline-block;
- }
- .user-info {
- display: inline-block;
- text-align: left;
- vertical-align: middle;
- margin-left: 15px;
- .handle {
- color: $gl-gray-light;
- }
- .member-date {
- margin-bottom: 4px;
- }
+ margin: 0 auto 10px;
}
}
+
@media (max-width: $screen-xs-max) {
+
.cover-block {
padding-top: 20px;
}
@@ -258,10 +251,6 @@
}
}
-.user-profile-nav {
- margin-top: 15px;
-}
-
table.u2f-registrations {
th:not(:last-child), td:not(:last-child) {
border-right: solid 1px transparent;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 78bc4b79e86..87548dcb590 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -146,7 +146,8 @@
}
.project-repo-btn-group,
- .notification-dropdown {
+ .notification-dropdown,
+ .project-dropdown {
margin-left: 10px;
}
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 68a5d1ae06c..ea76fe18876 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -51,6 +51,7 @@
-webkit-flex-direction: column;
flex-direction: column;
margin-left: 10px;
+ min-width: 55px;
}
.todo-item {
@@ -120,6 +121,14 @@
}
}
+@media (max-width: $screen-sm-max) {
+ .todos-filters {
+ .dropdown-menu-toggle {
+ width: 135px;
+ }
+ }
+}
+
@media (max-width: $screen-xs-max) {
.todo {
.avatar {
@@ -141,4 +150,14 @@
padding-left: 10px;
}
}
+
+ .todos-filters {
+ .row-content-block {
+ padding-bottom: 50px;
+ }
+
+ .dropdown-menu-toggle {
+ width: 100%;
+ }
+ }
}