From 97ab8539968d52b709cd61c2dd4229d404903e14 Mon Sep 17 00:00:00 2001 From: Rajat Jain Date: Tue, 2 Apr 2019 12:46:21 +0200 Subject: [frontend] backport of scoped labels Scoped labels in EE require additional changes in CE code. --- app/assets/javascripts/labels_select.js | 95 +++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 5 deletions(-) (limited to 'app/assets/javascripts/labels_select.js') diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index cca4927c115..b021dcc1853 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -11,6 +11,7 @@ import CreateLabelDropdown from './create_label'; import flash from './flash'; import ModalStore from './boards/stores/modal_store'; import boardsStore from './boards/stores/boards_store'; +import { isEE } from '~/lib/utils/common_utils'; export default class LabelsSelect { constructor(els, options = {}) { @@ -86,8 +87,9 @@ export default class LabelsSelect { return this.value; }) .get(); + const scopedLabels = $dropdown.data('scopedLabels'); + const scopedLabelsDocumentationLink = $dropdown.data('scopedLabelsDocumentationLink'); const { handleClick } = options; - $sidebarLabelTooltip.tooltip(); if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) { @@ -132,8 +134,48 @@ export default class LabelsSelect { template = LabelsSelect.getLabelTemplate({ labels: data.labels, issueUpdateURL, + enableScopedLabels: scopedLabels, + scopedLabelsDocumentationLink, }); labelCount = data.labels.length; + + // 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 + "']") + .remove(); + }); + } } else { template = 'None'; } @@ -358,6 +400,7 @@ export default class LabelsSelect { } else { if (!$dropdown.hasClass('js-filter-bulk-update')) { saveLabelData(); + $dropdown.data('glDropdown').clearMenu(); } } } @@ -471,19 +514,61 @@ export default class LabelsSelect { // so best approach is to use traditional way of // concatenation // see: http://2ality.com/2016/05/template-literal-whitespace.html#joining-arrays - const tpl = _.template( + + const labelTemplate = _.template( [ - '<% _.each(labels, function(label){ %>', '?label_name[]=<%- encodeURIComponent(label.title) %>">', - '', + ' title="<%= tooltipTitleTemplate({ label, isScopedLabel, enableScopedLabels }) %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">', '<%- label.title %>', '', '', + ].join(''), + ); + + const infoIconTemplate = _.template( + [ + '', + '', + '', + ].join(''), + ); + + const tooltipTitleTemplate = _.template( + [ + '<% if (isScopedLabel(label) && enableScopedLabels) { %>', + "Scoped label", + '
', + '<%- label.description %>', + '<% } else { %>', + '<%- label.description %>', + '<% } %>', + ].join(''), + ); + + const isScopedLabel = label => label.title.indexOf('::') !== -1; + + const tpl = _.template( + [ + '<% _.each(labels, function(label){ %>', + '<% if (isScopedLabel(label) && enableScopedLabels) { %>', + '', + '<%= labelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, tooltipTitleTemplate, linkAttrs: \'data-html="true"\' }) %>', + '<%= infoIconTemplate({ label,scopedLabelsDocumentationLink }) %>', + '', + '<% } else { %>', + '<%= labelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, tooltipTitleTemplate, linkAttrs: "" }) %>', + '<% } %>', '<% }); %>', ].join(''), ); - return tpl(tplData); + return tpl({ + ...tplData, + labelTemplate, + infoIconTemplate, + tooltipTitleTemplate, + isScopedLabel, + }); } bindEvents() { -- cgit v1.2.3