summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/labels_select.js
diff options
context:
space:
mode:
authorFatih Acet <acetfatih@gmail.com>2016-12-15 21:03:33 +0000
committerFatih Acet <acetfatih@gmail.com>2016-12-15 21:03:33 +0000
commitb01a830afedeacfa099be5c3332f012c3d3db02c (patch)
treefc701c5261a5dd0c9b3f061187c333d6e14ad1eb /app/assets/javascripts/labels_select.js
parent07c7976d16d5561613ee70022fa3d1086ba0bd92 (diff)
parent51b2ffaf7ecbfbc7604a38b66576af008aa8599f (diff)
downloadgitlab-ce-b01a830afedeacfa099be5c3332f012c3d3db02c.tar.gz
Merge branch '24877-bulk-edit-only-keeps-common-labels-when-searching' into 'master'
Improve bulk assignment This MR improves current implementation of Label dropdown when used for bulk assignment on issuable pages (/:namespace/:project/issues, /:namespace/:project/merge_requests) Previously this dropdown relied on `<input>` tags to get its active items and also to calculate items with indeterminate state. Relying on `<input>` tags is not enough when we want to set/get multiple states on a dropdown. For this case we want to get/set: - Marked items - Unmarked items that were initially marked - Unmarked items that were initially indeterminate - Items with indeterminate state. This MR makes the Label dropdown to save its own state as `data` so it will be easy to get and set whatever state we want no matter if the dropdown is filtering which is the issue that I initially wanted to solve as you can see in the following gif. **Before** ![2016-12-07_11.44.48](/uploads/cb697161b8b39cdee72fdbb95a531100/2016-12-07_11.44.48.gif) **After** ![2016-12-07_11.32.43](/uploads/338255a302de0dd1367474f33232d2a3/2016-12-07_11.32.43.gif) As you can see in the first gif the `bug` label is removed from the selected issues but the `enhancement` label should set but the `critical` should be kept. This is fixed on the next gif. Fixes #24877 See merge request !7765
Diffstat (limited to 'app/assets/javascripts/labels_select.js')
-rw-r--r--app/assets/javascripts/labels_select.js146
1 files changed, 84 insertions, 62 deletions
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index d29a5edb9ad..6853d6b9db2 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -8,8 +8,9 @@
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, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove;
+ 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, $container;
$dropdown = $(dropdown);
+ $dropdownContainer = $dropdown.closest('.labels-filter');
$toggleText = $dropdown.find('.dropdown-toggle-text');
namespacePath = $dropdown.data('namespace-path');
projectPath = $dropdown.data('project-path');
@@ -125,7 +126,7 @@
});
});
};
- return $dropdown.glDropdown({
+ $dropdown.glDropdown({
showMenuAbove: showMenuAbove,
data: function(term, callback) {
return $.ajax({
@@ -172,33 +173,40 @@
});
},
renderRow: function(label, instance) {
- var $a, $li, active, color, colorEl, indeterminate, removesAll, selectedClass, spacing;
+ var $a, $li, color, colorEl, indeterminate, removesAll, selectedClass, spacing, i, marked, dropdownName, dropdownValue;
$li = $('<li>');
$a = $('<a href="#">');
selectedClass = [];
removesAll = label.id <= 0 || (label.id == null);
if ($dropdown.hasClass('js-filter-bulk-update')) {
- indeterminate = instance.indeterminateIds;
- active = instance.activeIds;
+ indeterminate = $dropdown.data('indeterminate') || [];
+ marked = $dropdown.data('marked') || [];
+
if (indeterminate.indexOf(label.id) !== -1) {
selectedClass.push('is-indeterminate');
}
- if (active.indexOf(label.id) !== -1) {
+
+ if (marked.indexOf(label.id) !== -1) {
// Remove is-indeterminate class if the item will be marked as active
i = selectedClass.indexOf('is-indeterminate');
if (i !== -1) {
selectedClass.splice(i, 1);
}
selectedClass.push('is-active');
- // Add input manually
- instance.addInput(this.fieldName, label.id);
}
- }
- if (this.id(label) && $form.find("input[type='hidden'][name='" + ($dropdown.data('fieldName')) + "'][value='" + this.id(label).toString().replace(/'/g, '\\\'') + "']").length) {
- selectedClass.push('is-active');
- }
- if ($dropdown.hasClass('js-multiselect') && removesAll) {
- selectedClass.push('dropdown-clear-active');
+ } else {
+ if (this.id(label)) {
+ dropdownName = $dropdown.data('fieldName');
+ dropdownValue = this.id(label).toString().replace(/'/g, '\\\'');
+
+ if ($form.find("input[type='hidden'][name='" + dropdownName + "'][value='" + dropdownValue + "']").length) {
+ selectedClass.push('is-active');
+ }
+ }
+
+ if ($dropdown.hasClass('js-multiselect') && removesAll) {
+ selectedClass.push('dropdown-clear-active');
+ }
}
if (label.duplicate) {
spacing = 100 / label.color.length;
@@ -234,7 +242,6 @@
// Return generated html
return $li.html($a).prop('outerHTML');
},
- persistWhenHide: $dropdown.data('persistWhenHide'),
search: {
fields: ['title']
},
@@ -313,18 +320,15 @@
}
}
}
- if ($dropdown.hasClass('js-filter-bulk-update')) {
- // If we are persisting state we need the classes
- if (!this.options.persistWhenHide) {
- return $dropdown.parent().find('.is-active, .is-indeterminate').removeClass();
- }
- }
},
multiSelect: $dropdown.hasClass('js-multiselect'),
vue: $dropdown.hasClass('js-issue-board-sidebar'),
- clicked: function(label, $el, e) {
+ clicked: function(label, $el, e, isMarking) {
var isIssueIndex, isMRIndex, page;
- _this.enableBulkLabelDropdown();
+
+ page = $('body').data('page');
+ isIssueIndex = page === 'projects:issues:index';
+ isMRIndex = page === 'projects:merge_requests:index';
if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) {
$dropdown.parent()
@@ -333,12 +337,11 @@
}
if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
+ _this.enableBulkLabelDropdown();
+ _this.setDropdownData($dropdown, isMarking, this.id(label));
return;
}
- page = $('body').data('page');
- isIssueIndex = page === 'projects:issues:index';
- isMRIndex = page === 'projects:merge_requests:index';
if ($('html').hasClass('issue-boards-page') && !$dropdown.hasClass('js-issue-board-sidebar')) {
if (label.isAny) {
gl.issueBoards.BoardsStore.state.filters['label_name'] = [];
@@ -400,17 +403,10 @@
}
}
},
- setIndeterminateIds: function() {
- if (this.dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')) {
- return this.indeterminateIds = _this.getIndeterminateIds();
- }
- },
- setActiveIds: function() {
- if (this.dropdown.find('.dropdown-menu-toggle').hasClass('js-filter-bulk-update')) {
- return this.activeIds = _this.getActiveIds();
- }
- }
});
+
+ // Set dropdown data
+ _this.setOriginalDropdownData($dropdownContainer, $dropdown);
});
this.bindEvents();
}
@@ -423,34 +419,9 @@
if ($('.selected_issue:checked').length) {
return;
}
- // Remove inputs
- $('.issues_bulk_update .labels-filter input[type="hidden"]').remove();
- // Also restore button text
return $('.issues_bulk_update .labels-filter .dropdown-toggle-text').text('Label');
};
- LabelsSelect.prototype.getIndeterminateIds = function() {
- var label_ids;
- label_ids = [];
- $('.selected_issue:checked').each(function(i, el) {
- var issue_id;
- issue_id = $(el).data('id');
- return label_ids.push($("#issue_" + issue_id).data('labels'));
- });
- return _.flatten(label_ids);
- };
-
- LabelsSelect.prototype.getActiveIds = function() {
- var label_ids;
- label_ids = [];
- $('.selected_issue:checked').each(function(i, el) {
- var issue_id;
- issue_id = $(el).data('id');
- return label_ids.push($("#issue_" + issue_id).data('labels'));
- });
- return _.intersection.apply(_, label_ids);
- };
-
LabelsSelect.prototype.enableBulkLabelDropdown = function() {
var issuableBulkActions;
if ($('.selected_issue:checked').length) {
@@ -459,8 +430,59 @@
}
};
- return LabelsSelect;
+ LabelsSelect.prototype.setDropdownData = function($dropdown, isMarking, value) {
+ var i, markedIds, unmarkedIds, indeterminateIds;
+ var issuableBulkActions = $('.bulk-update').data('bulkActions');
+
+ markedIds = $dropdown.data('marked') || [];
+ unmarkedIds = $dropdown.data('unmarked') || [];
+ indeterminateIds = $dropdown.data('indeterminate') || [];
+
+ if (isMarking) {
+ markedIds.push(value);
+
+ i = indeterminateIds.indexOf(value);
+ if (i > -1) {
+ indeterminateIds.splice(i, 1);
+ }
+
+ i = unmarkedIds.indexOf(value);
+ if (i > -1) {
+ unmarkedIds.splice(i, 1);
+ }
+ } else {
+ // If marked item (not common) is unmarked
+ i = markedIds.indexOf(value);
+ if (i > -1) {
+ markedIds.splice(i, 1);
+ }
+
+ // If an indeterminate item is being unmarked
+ if (issuableBulkActions.getOriginalIndeterminateIds().indexOf(value) > -1) {
+ unmarkedIds.push(value);
+ }
+
+ // If a marked item is being unmarked
+ // (a marked item could also be a label that is present in all selection)
+ if (issuableBulkActions.getOriginalCommonIds().indexOf(value) > -1) {
+ unmarkedIds.push(value);
+ }
+ }
+ $dropdown.data('marked', markedIds);
+ $dropdown.data('unmarked', unmarkedIds);
+ $dropdown.data('indeterminate', indeterminateIds);
+ };
+
+ LabelsSelect.prototype.setOriginalDropdownData = function($container, $dropdown) {
+ var labels = [];
+ $container.find('[name="label_name[]"]').map(function() {
+ return labels.push(this.value);
+ });
+ $dropdown.data('marked', labels);
+ };
+
+ return LabelsSelect;
})();
}).call(this);