diff options
author | Alfredo Sumaran <alfredo@gitlab.com> | 2016-11-29 02:47:02 -0500 |
---|---|---|
committer | Alfredo Sumaran <alfredo@gitlab.com> | 2016-12-14 10:05:00 -0500 |
commit | 262fc28a7d1015b0e1349d665d5527ccee29592f (patch) | |
tree | 497ff1b98a60f0cfa5e09499924d4f64ea84fb2b /app/assets/javascripts/labels_select.js | |
parent | 278baa5b618c5595045415a55d863daf9a15d792 (diff) | |
download | gitlab-ce-262fc28a7d1015b0e1349d665d5527ccee29592f.tar.gz |
Improve issuable's bulk assignment implementation
This fixes the case when the user wants to add a label. The user has to use the dropdown’s filter input to look for a label and click it in order to see the bug.
Step to reproduce
- Select at least two issues, one label should be present in all issues, other label should be present in at least one.
- On the label dropdown: Deselect label that is present in all issues, look for another issue using the filter input and click it.
- Click on `Update issues`
Before: Unmarked label were kept on selected issues.
Now: Unmarked label is removed from selected issues
Diffstat (limited to 'app/assets/javascripts/labels_select.js')
-rw-r--r-- | app/assets/javascripts/labels_select.js | 138 |
1 files changed, 76 insertions, 62 deletions
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index f334f35594d..1d79807785f 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -5,8 +5,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'); @@ -122,7 +123,7 @@ }); }); }; - return $dropdown.glDropdown({ + $dropdown.glDropdown({ showMenuAbove: showMenuAbove, data: function(term, callback) { return $.ajax({ @@ -169,33 +170,35 @@ }); }, 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; $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) && $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'); + } } if (label.duplicate) { spacing = 100 / label.color.length; @@ -231,7 +234,6 @@ // Return generated html return $li.html($a).prop('outerHTML'); }, - persistWhenHide: $dropdown.data('persistWhenHide'), search: { fields: ['title'] }, @@ -310,18 +312,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() @@ -330,12 +329,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'] = []; @@ -397,17 +395,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(); } @@ -420,34 +411,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) { @@ -456,8 +422,56 @@ } }; - return LabelsSelect; + LabelsSelect.prototype.setDropdownData = function($dropdown, isMarking, value) { + 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); |