debian-mirror-gitlab/app/assets/javascripts/labels_select.js

642 lines
22 KiB
JavaScript
Raw Normal View History

2018-12-13 13:39:08 +05:30
/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, prefer-arrow-callback, one-var, no-unused-vars, prefer-template, no-new, consistent-return, object-shorthand, no-shadow, no-param-reassign, vars-on-top, no-lonely-if, no-else-return, dot-notation, no-empty */
2017-08-17 22:00:37 +05:30
/* global Issuable */
/* global ListLabel */
2018-05-09 12:01:36 +05:30
import $ from 'jquery';
2017-09-10 17:25:29 +05:30
import _ from 'underscore';
2019-09-04 21:01:54 +05:30
import { sprintf, s__, __ } from './locale';
2018-03-17 18:26:18 +05:30
import axios from './lib/utils/axios_utils';
2017-09-10 17:25:29 +05:30
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
2018-03-17 18:26:18 +05:30
import CreateLabelDropdown from './create_label';
import flash from './flash';
2018-10-15 14:42:47 +05:30
import ModalStore from './boards/stores/modal_store';
2018-12-13 13:39:08 +05:30
import boardsStore from './boards/stores/boards_store';
2019-07-31 22:56:46 +05:30
import { isEE, isScopedLabel } from '~/lib/utils/common_utils';
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
export default class LabelsSelect {
constructor(els, options = {}) {
var _this, $els;
_this = this;
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
$els = $(els);
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
if (!els) {
$els = $('.js-label-select');
}
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
$els.each(function(i, dropdown) {
2018-12-13 13:39:08 +05:30
var $block,
$colorPreview,
$dropdown,
$form,
$loading,
$selectbox,
$sidebarCollapsedValue,
$value,
abilityName,
defaultLabel,
enableLabelCreateButton,
issueURLSplit,
issueUpdateURL,
labelUrl,
namespacePath,
projectPath,
saveLabelData,
selectedLabel,
showAny,
showNo,
$sidebarLabelTooltip,
initialSelected,
$toggleText,
fieldName,
useId,
propertyName,
showMenuAbove,
$container,
$dropdownContainer;
2018-03-17 18:26:18 +05:30
$dropdown = $(dropdown);
$dropdownContainer = $dropdown.closest('.labels-filter');
$toggleText = $dropdown.find('.dropdown-toggle-text');
2018-03-27 19:54:05 +05:30
namespacePath = $dropdown.data('namespacePath');
projectPath = $dropdown.data('projectPath');
2018-03-17 18:26:18 +05:30
issueUpdateURL = $dropdown.data('issueUpdate');
selectedLabel = $dropdown.data('selected');
2018-12-13 13:39:08 +05:30
if (selectedLabel != null && !$dropdown.hasClass('js-multiselect')) {
2018-03-17 18:26:18 +05:30
selectedLabel = selectedLabel.split(',');
}
2018-03-27 19:54:05 +05:30
showNo = $dropdown.data('showNo');
showAny = $dropdown.data('showAny');
2018-03-17 18:26:18 +05:30
showMenuAbove = $dropdown.data('showMenuAbove');
2018-11-20 20:47:30 +05:30
defaultLabel = $dropdown.data('defaultLabel') || __('Label');
2018-03-27 19:54:05 +05:30
abilityName = $dropdown.data('abilityName');
2018-03-17 18:26:18 +05:30
$selectbox = $dropdown.closest('.selectbox');
$block = $selectbox.closest('.block');
$form = $dropdown.closest('form, .js-issuable-update');
$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span');
$sidebarLabelTooltip = $block.find('.js-sidebar-labels-tooltip');
$value = $block.find('.value');
$loading = $block.find('.block-loading').fadeOut();
2018-03-27 19:54:05 +05:30
fieldName = $dropdown.data('fieldName');
2018-12-13 13:39:08 +05:30
useId = $dropdown.is(
'.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown',
);
2018-03-17 18:26:18 +05:30
propertyName = useId ? 'id' : 'title';
initialSelected = $selectbox
2018-03-27 19:54:05 +05:30
.find('input[name="' + $dropdown.data('fieldName') + '"]')
2018-12-13 13:39:08 +05:30
.map(function() {
2018-03-17 18:26:18 +05:30
return this.value;
2018-12-13 13:39:08 +05:30
})
.get();
2019-07-07 11:18:12 +05:30
const scopedLabels = $dropdown.data('scopedLabels');
const scopedLabelsDocumentationLink = $dropdown.data('scopedLabelsDocumentationLink');
2018-11-08 19:23:39 +05:30
const { handleClick } = options;
2018-03-17 18:26:18 +05:30
$sidebarLabelTooltip.tooltip();
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) {
2018-12-13 13:39:08 +05:30
new CreateLabelDropdown(
$dropdown.closest('.dropdown').find('.dropdown-new-label'),
namespacePath,
projectPath,
);
2018-03-17 18:26:18 +05:30
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
saveLabelData = function() {
var data, selected;
2018-12-13 13:39:08 +05:30
selected = $dropdown
.closest('.selectbox')
.find("input[name='" + fieldName + "']")
.map(function() {
return this.value;
})
.get();
2016-10-01 15:18:49 +05:30
2018-03-17 18:26:18 +05:30
if (_.isEqual(initialSelected, selected)) return;
initialSelected = selected;
2016-10-01 15:18:49 +05:30
2018-03-17 18:26:18 +05:30
data = {};
data[abilityName] = {};
data[abilityName].label_ids = selected;
if (!selected.length) {
data[abilityName].label_ids = [''];
}
$loading.removeClass('hidden').fadeIn();
$dropdown.trigger('loading.gl.dropdown');
2018-12-13 13:39:08 +05:30
axios
.put(issueUpdateURL, data)
2018-03-17 18:26:18 +05:30
.then(({ data }) => {
2018-10-15 14:42:47 +05:30
var labelCount, template, labelTooltipTitle, labelTitles, formattedLabels;
2016-09-13 17:45:13 +05:30
$loading.fadeOut();
$dropdown.trigger('loaded.gl.dropdown');
$selectbox.hide();
2018-03-27 19:54:05 +05:30
data.issueUpdateURL = issueUpdateURL;
2016-09-13 17:45:13 +05:30
labelCount = 0;
2018-03-27 19:54:05 +05:30
if (data.labels.length && issueUpdateURL) {
template = LabelsSelect.getLabelTemplate({
labels: data.labels,
issueUpdateURL,
2019-07-07 11:18:12 +05:30
enableScopedLabels: scopedLabels,
scopedLabelsDocumentationLink,
2018-03-27 19:54:05 +05:30
});
2016-09-13 17:45:13 +05:30
labelCount = data.labels.length;
2019-07-07 11:18:12 +05:30
// EE Specific
if (isEE) {
/**
* For Scoped labels, the last label selected with the
* same key will be applied to the current issueable.
*
* If these are the labels - priority::1, priority::2; and if
* we apply them in the same order, only priority::2 will stick
* with the issuable.
*
* In the current dropdown implementation, we keep track of all
* the labels selected via a hidden DOM element. Since a User
* can select priority::1 and priority::2 at the same time, the
* DOM will have 2 hidden input and the dropdown will show both
* the items selected but in reality server only applied
* priority::2.
*
* We find all the labels then find all the labels server accepted
* and then remove the excess ones.
*/
const toRemoveIds = Array.from(
$form.find(`input[type="hidden"][name="${fieldName}"]`),
)
.map(el => el.value)
.map(Number);
data.labels.forEach(label => {
const index = toRemoveIds.indexOf(label.id);
toRemoveIds.splice(index, 1);
});
toRemoveIds.forEach(id => {
$form
.find(`input[type="hidden"][name="${fieldName}"][value="${id}"]`)
.last()
.remove();
});
}
2018-12-13 13:39:08 +05:30
} else {
2019-09-04 21:01:54 +05:30
template = `<span class="no-value">${__('None')}</span>`;
2016-09-13 17:45:13 +05:30
}
$value.removeAttr('style').html(template);
$sidebarCollapsedValue.text(labelCount);
if (data.labels.length) {
labelTitles = data.labels.map(function(label) {
return label.title;
});
if (labelTitles.length > 5) {
labelTitles = labelTitles.slice(0, 5);
2019-09-04 21:01:54 +05:30
labelTitles.push(
sprintf(s__('Labels|and %{count} more'), { count: data.labels.length - 5 }),
);
2016-09-13 17:45:13 +05:30
}
labelTooltipTitle = labelTitles.join(', ');
2018-12-13 13:39:08 +05:30
} else {
2018-10-15 14:42:47 +05:30
labelTooltipTitle = __('Labels');
2016-09-13 17:45:13 +05:30
}
2018-12-13 13:39:08 +05:30
$sidebarLabelTooltip.attr('title', labelTooltipTitle).tooltip('_fixTitle');
2016-09-13 17:45:13 +05:30
$('.has-tooltip', $value).tooltip({
2018-12-13 13:39:08 +05:30
container: 'body',
2016-09-13 17:45:13 +05:30
});
2018-03-17 18:26:18 +05:30
})
.catch(() => flash(__('Error saving label update.')));
};
$dropdown.glDropdown({
showMenuAbove: showMenuAbove,
data: function(term, callback) {
2018-12-13 13:39:08 +05:30
labelUrl = $dropdown.attr('data-labels');
axios
.get(labelUrl)
.then(res => {
2019-02-15 15:39:39 +05:30
let { data } = res;
2016-09-13 17:45:13 +05:30
if ($dropdown.hasClass('js-extra-options')) {
2016-11-03 12:29:30 +05:30
var extraData = [];
2016-09-13 17:45:13 +05:30
if (showNo) {
2016-11-03 12:29:30 +05:30
extraData.unshift({
2016-09-13 17:45:13 +05:30
id: 0,
2019-09-04 21:01:54 +05:30
title: __('No Label'),
2016-09-13 17:45:13 +05:30
});
}
if (showAny) {
2016-11-03 12:29:30 +05:30
extraData.unshift({
2016-09-13 17:45:13 +05:30
isAny: true,
2019-09-04 21:01:54 +05:30
title: __('Any Label'),
2016-09-13 17:45:13 +05:30
});
}
2016-11-03 12:29:30 +05:30
if (extraData.length) {
extraData.push('divider');
data = extraData.concat(data);
2016-09-13 17:45:13 +05:30
}
}
2016-11-03 12:29:30 +05:30
callback(data);
if (showMenuAbove) {
$dropdown.data('glDropdown').positionMenuAbove();
}
2018-03-17 18:26:18 +05:30
})
.catch(() => flash(__('Error fetching labels.')));
},
renderRow: function(label, instance) {
2019-07-07 11:18:12 +05:30
var linkEl,
listItemEl,
2018-12-13 13:39:08 +05:30
color,
colorEl,
indeterminate,
removesAll,
selectedClass,
spacing,
i,
marked,
dropdownValue;
2019-07-07 11:18:12 +05:30
2018-03-17 18:26:18 +05:30
selectedClass = [];
2018-12-13 13:39:08 +05:30
removesAll = label.id <= 0 || label.id == null;
2019-07-07 11:18:12 +05:30
2018-03-17 18:26:18 +05:30
if ($dropdown.hasClass('js-filter-bulk-update')) {
indeterminate = $dropdown.data('indeterminate') || [];
marked = $dropdown.data('marked') || [];
if (indeterminate.indexOf(label.id) !== -1) {
selectedClass.push('is-indeterminate');
}
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
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);
2017-08-17 22:00:37 +05:30
}
2018-03-17 18:26:18 +05:30
selectedClass.push('is-active');
2016-09-13 17:45:13 +05:30
}
2018-03-17 18:26:18 +05:30
} else {
if (this.id(label)) {
2018-12-13 13:39:08 +05:30
dropdownValue = this.id(label)
.toString()
.replace(/'/g, "\\'");
if (
$form.find(
"input[type='hidden'][name='" +
2019-07-07 11:18:12 +05:30
this.fieldName +
2018-12-13 13:39:08 +05:30
"'][value='" +
dropdownValue +
"']",
).length
) {
2018-03-17 18:26:18 +05:30
selectedClass.push('is-active');
2016-09-13 17:45:13 +05:30
}
}
2016-11-03 12:29:30 +05:30
2019-07-07 11:18:12 +05:30
if (this.multiSelect && removesAll) {
2018-03-17 18:26:18 +05:30
selectedClass.push('dropdown-clear-active');
2016-11-03 12:29:30 +05:30
}
2018-03-17 18:26:18 +05:30
}
2019-07-07 11:18:12 +05:30
2019-02-15 15:39:39 +05:30
if (label.color) {
colorEl =
"<span class='dropdown-label-box' style='background: " + label.color + "'></span>";
2018-12-13 13:39:08 +05:30
} else {
2018-03-17 18:26:18 +05:30
colorEl = '';
}
2019-07-07 11:18:12 +05:30
linkEl = document.createElement('a');
linkEl.href = '#';
2018-03-17 18:26:18 +05:30
// We need to identify which items are actually labels
if (label.id) {
selectedClass.push('label-item');
2019-07-07 11:18:12 +05:30
linkEl.dataset.labelId = label.id;
2018-03-17 18:26:18 +05:30
}
2019-07-07 11:18:12 +05:30
linkEl.className = selectedClass.join(' ');
linkEl.innerHTML = `${colorEl} ${_.escape(label.title)}`;
listItemEl = document.createElement('li');
listItemEl.appendChild(linkEl);
return listItemEl;
2018-03-17 18:26:18 +05:30
},
search: {
2018-12-13 13:39:08 +05:30
fields: ['title'],
2018-03-17 18:26:18 +05:30
},
selectable: true,
filterable: true,
selected: $dropdown.data('selected') || [],
toggleLabel: function(selected, el) {
2018-03-27 19:54:05 +05:30
var $dropdownParent = $dropdown.parent();
var $dropdownInputField = $dropdownParent.find('.dropdown-input-field');
2018-03-17 18:26:18 +05:30
var isSelected = el !== null ? el.hasClass('is-active') : false;
2018-11-08 19:23:39 +05:30
2018-11-18 11:00:15 +05:30
var title = selected ? selected.title : null;
2018-03-17 18:26:18 +05:30
var selectedLabels = this.selected;
2018-03-27 19:54:05 +05:30
if ($dropdownInputField.length && $dropdownInputField.val().length) {
$dropdownParent.find('.dropdown-input-clear').trigger('click');
}
2018-11-18 11:00:15 +05:30
if (selected && selected.id === 0) {
2018-03-17 18:26:18 +05:30
this.selected = [];
2019-09-04 21:01:54 +05:30
return __('No Label');
2018-12-13 13:39:08 +05:30
} else if (isSelected) {
2018-03-17 18:26:18 +05:30
this.selected.push(title);
2018-12-13 13:39:08 +05:30
} else if (!isSelected && title) {
2018-03-17 18:26:18 +05:30
var index = this.selected.indexOf(title);
this.selected.splice(index, 1);
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
if (selectedLabels.length === 1) {
return selectedLabels;
2018-12-13 13:39:08 +05:30
} else if (selectedLabels.length) {
2018-11-20 20:47:30 +05:30
return sprintf(__('%{firstLabel} +%{labelCount} more'), {
firstLabel: selectedLabels[0],
2018-12-13 13:39:08 +05:30
labelCount: selectedLabels.length - 1,
2018-11-20 20:47:30 +05:30
});
2018-12-13 13:39:08 +05:30
} else {
2018-03-17 18:26:18 +05:30
return defaultLabel;
}
},
2018-03-27 19:54:05 +05:30
fieldName: $dropdown.data('fieldName'),
2018-03-17 18:26:18 +05:30
id: function(label) {
if (label.id <= 0) return label.title;
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
if ($dropdown.hasClass('js-issuable-form-dropdown')) {
return label.id;
}
2016-11-03 12:29:30 +05:30
2018-12-13 13:39:08 +05:30
if ($dropdown.hasClass('js-filter-submit') && label.isAny == null) {
2018-03-17 18:26:18 +05:30
return label.title;
2018-12-13 13:39:08 +05:30
} else {
2018-03-17 18:26:18 +05:30
return label.id;
}
},
hidden: function() {
var isIssueIndex, isMRIndex, page, selectedLabels;
page = $('body').attr('data-page');
isIssueIndex = page === 'projects:issues:index';
isMRIndex = page === 'projects:merge_requests:index';
$selectbox.hide();
// display:block overrides the hide-collapse rule
$value.removeAttr('style');
if ($dropdown.hasClass('js-issuable-form-dropdown')) {
return;
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
if ($('html').hasClass('issue-boards-page')) {
return;
}
if ($dropdown.hasClass('js-multiselect')) {
if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
2018-12-13 13:39:08 +05:30
selectedLabels = $dropdown
.closest('form')
.find("input:hidden[name='" + $dropdown.data('fieldName') + "']");
2018-03-17 18:26:18 +05:30
Issuable.filterResults($dropdown.closest('form'));
2018-12-13 13:39:08 +05:30
} else if ($dropdown.hasClass('js-filter-submit')) {
2018-03-17 18:26:18 +05:30
$dropdown.closest('form').submit();
2018-12-13 13:39:08 +05:30
} else {
2018-03-17 18:26:18 +05:30
if (!$dropdown.hasClass('js-filter-bulk-update')) {
saveLabelData();
2019-07-07 11:18:12 +05:30
$dropdown.data('glDropdown').clearMenu();
2018-03-17 18:26:18 +05:30
}
2016-11-03 12:29:30 +05:30
}
2018-03-17 18:26:18 +05:30
}
},
multiSelect: $dropdown.hasClass('js-multiselect'),
vue: $dropdown.hasClass('js-issue-board-sidebar'),
2018-12-13 13:39:08 +05:30
clicked: function(clickEvent) {
2018-03-27 19:54:05 +05:30
const { $el, e, isMarking } = clickEvent;
const label = clickEvent.selectedObj;
2018-03-17 18:26:18 +05:30
var isIssueIndex, isMRIndex, page, boardsModel;
var fadeOutLoader = () => {
$loading.fadeOut();
};
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
page = $('body').attr('data-page');
isIssueIndex = page === 'projects:issues:index';
isMRIndex = page === 'projects:merge_requests:index';
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) {
2018-12-13 13:39:08 +05:30
$dropdown
.parent()
2018-03-17 18:26:18 +05:30
.find('.dropdown-clear-active')
.removeClass('is-active');
}
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
if ($dropdown.hasClass('js-issuable-form-dropdown')) {
return;
}
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
if ($dropdown.hasClass('js-filter-bulk-update')) {
_this.enableBulkLabelDropdown();
_this.setDropdownData($dropdown, isMarking, label.id);
return;
}
if ($dropdown.closest('.add-issues-modal').length) {
2018-10-15 14:42:47 +05:30
boardsModel = ModalStore.store.filter;
2018-03-17 18:26:18 +05:30
}
2016-09-13 17:45:13 +05:30
2018-03-17 18:26:18 +05:30
if (boardsModel) {
if (label.isAny) {
boardsModel['label_name'] = [];
} else if ($el.hasClass('is-active')) {
boardsModel['label_name'].push(label.title);
2016-11-03 12:29:30 +05:30
}
2018-03-17 18:26:18 +05:30
e.preventDefault();
return;
2018-12-13 13:39:08 +05:30
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
2018-03-17 18:26:18 +05:30
if (!$dropdown.hasClass('js-multiselect')) {
selectedLabel = label.title;
return Issuable.filterResults($dropdown.closest('form'));
2016-11-03 12:29:30 +05:30
}
2018-12-13 13:39:08 +05:30
} else if ($dropdown.hasClass('js-filter-submit')) {
2018-03-17 18:26:18 +05:30
return $dropdown.closest('form').submit();
2018-12-13 13:39:08 +05:30
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
2018-03-17 18:26:18 +05:30
if ($el.hasClass('is-active')) {
2018-12-13 13:39:08 +05:30
boardsStore.detail.issue.labels.push(
new ListLabel({
id: label.id,
title: label.title,
2019-02-15 15:39:39 +05:30
color: label.color,
2018-12-13 13:39:08 +05:30
textColor: '#fff',
}),
);
} else {
var { labels } = boardsStore.detail.issue;
labels = labels.filter(function(selectedLabel) {
2018-03-17 18:26:18 +05:30
return selectedLabel.id !== label.id;
});
2018-12-13 13:39:08 +05:30
boardsStore.detail.issue.labels = labels;
2018-03-17 18:26:18 +05:30
}
$loading.fadeIn();
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
boardsStore.detail.issue
.update($dropdown.attr('data-issue-update'))
2018-03-17 18:26:18 +05:30
.then(fadeOutLoader)
.catch(fadeOutLoader);
2018-12-13 13:39:08 +05:30
} else if (handleClick) {
2018-03-17 18:26:18 +05:30
e.preventDefault();
handleClick(label);
2018-12-13 13:39:08 +05:30
} else {
2018-03-17 18:26:18 +05:30
if ($dropdown.hasClass('js-multiselect')) {
2018-12-13 13:39:08 +05:30
} else {
2018-03-17 18:26:18 +05:30
return saveLabelData();
2016-09-13 17:45:13 +05:30
}
2018-03-17 18:26:18 +05:30
}
},
2018-11-18 11:00:15 +05:30
opened: function(e) {
if ($dropdown.hasClass('js-issue-board-sidebar')) {
const previousSelection = $dropdown.attr('data-selected');
this.selected = previousSelection ? previousSelection.split(',') : [];
$dropdown.data('glDropdown').updateLabel();
}
},
preserveContext: true,
2016-09-13 17:45:13 +05:30
});
2018-03-17 18:26:18 +05:30
// Set dropdown data
_this.setOriginalDropdownData($dropdownContainer, $dropdown);
});
this.bindEvents();
}
2018-03-27 19:54:05 +05:30
static getLabelTemplate(tplData) {
// We could use ES6 template string here
// and properly indent markup for readability
// but that also introduces unintended white-space
// so best approach is to use traditional way of
// concatenation
// see: http://2ality.com/2016/05/template-literal-whitespace.html#joining-arrays
2019-07-07 11:18:12 +05:30
const labelTemplate = _.template(
2018-12-13 13:39:08 +05:30
[
'<a href="<%- issueUpdateURL.slice(0, issueUpdateURL.lastIndexOf("/")) %>?label_name[]=<%- encodeURIComponent(label.title) %>">',
2019-07-07 11:18:12 +05:30
'<span class="badge label has-tooltip color-label" <%= linkAttrs %> title="<%= tooltipTitleTemplate({ label, isScopedLabel, enableScopedLabels, escapeStr }) %>" style="background-color: <%= escapeStr(label.color) %>; color: <%= escapeStr(label.text_color) %>;">',
2018-12-13 13:39:08 +05:30
'<%- label.title %>',
'</span>',
'</a>',
2019-07-07 11:18:12 +05:30
].join(''),
);
const infoIconTemplate = _.template(
[
'<a href="<%= scopedLabelsDocumentationLink %>" class="label scoped-label" target="_blank" rel="noopener">',
'<i class="fa fa-question-circle" style="background-color: <%= escapeStr(label.color) %>; color: <%= escapeStr(label.text_color) %>;"></i>',
'</a>',
].join(''),
);
const tooltipTitleTemplate = _.template(
[
'<% if (isScopedLabel(label) && enableScopedLabels) { %>',
"<span class='font-weight-bold scoped-label-tooltip-title'>Scoped label</span>",
'<br />',
'<%= escapeStr(label.description) %>',
'<% } else { %>',
'<%= escapeStr(label.description) %>',
'<% } %>',
].join(''),
);
const tpl = _.template(
[
'<% _.each(labels, function(label){ %>',
'<% if (isScopedLabel(label) && enableScopedLabels) { %>',
'<span class="d-inline-block position-relative scoped-label-wrapper">',
'<%= labelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, tooltipTitleTemplate, escapeStr, linkAttrs: \'data-html="true"\' }) %>',
'<%= infoIconTemplate({ label, scopedLabelsDocumentationLink, escapeStr }) %>',
'</span>',
'<% } else { %>',
'<%= labelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, tooltipTitleTemplate, escapeStr, linkAttrs: "" }) %>',
'<% } %>',
2018-12-13 13:39:08 +05:30
'<% }); %>',
].join(''),
);
2018-03-27 19:54:05 +05:30
2019-07-07 11:18:12 +05:30
return tpl({
...tplData,
labelTemplate,
infoIconTemplate,
tooltipTitleTemplate,
isScopedLabel,
escapeStr: _.escape,
});
2018-03-27 19:54:05 +05:30
}
2018-03-17 18:26:18 +05:30
bindEvents() {
2018-12-05 23:21:45 +05:30
return $('body').on('change', '.selected-issuable', this.onSelectCheckboxIssue);
2018-03-17 18:26:18 +05:30
}
// eslint-disable-next-line class-methods-use-this
onSelectCheckboxIssue() {
2018-12-05 23:21:45 +05:30
if ($('.selected-issuable:checked').length) {
2018-03-17 18:26:18 +05:30
return;
}
2019-09-04 21:01:54 +05:30
return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text(__('Label'));
2018-03-17 18:26:18 +05:30
}
// eslint-disable-next-line class-methods-use-this
enableBulkLabelDropdown() {
IssuableBulkUpdateActions.willUpdateLabels = true;
}
// eslint-disable-next-line class-methods-use-this
setDropdownData($dropdown, isMarking, value) {
var i, markedIds, unmarkedIds, indeterminateIds;
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);
2016-09-13 17:45:13 +05:30
}
2018-03-17 18:26:18 +05:30
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);
2017-08-17 22:00:37 +05:30
}
2018-03-17 18:26:18 +05:30
// If an indeterminate item is being unmarked
if (IssuableBulkUpdateActions.getOriginalIndeterminateIds().indexOf(value) > -1) {
unmarkedIds.push(value);
}
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
// If a marked item is being unmarked
// (a marked item could also be a label that is present in all selection)
if (IssuableBulkUpdateActions.getOriginalCommonIds().indexOf(value) > -1) {
unmarkedIds.push(value);
}
}
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
$dropdown.data('marked', markedIds);
$dropdown.data('unmarked', unmarkedIds);
$dropdown.data('indeterminate', indeterminateIds);
}
// eslint-disable-next-line class-methods-use-this
setOriginalDropdownData($container, $dropdown) {
const labels = [];
$container.find('[name="label_name[]"]').map(function() {
return labels.push(this.value);
});
$dropdown.data('marked', labels);
}
}