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

147 lines
4.4 KiB
JavaScript
Raw Normal View History

2019-12-04 20:38:33 +05:30
/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, func-names */
2018-05-09 12:01:36 +05:30
import $ from 'jquery';
2018-11-08 19:23:39 +05:30
import Sortable from 'sortablejs';
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
import flash from './flash';
import axios from './lib/utils/axios_utils';
2019-09-04 21:01:54 +05:30
import { __ } from './locale';
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
export default class LabelManager {
constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
this.togglePriorityButton = togglePriorityButton || $('.js-toggle-priority');
this.prioritizedLabels = prioritizedLabels || $('.js-prioritized-labels');
this.otherLabels = otherLabels || $('.js-other-labels');
2019-09-04 21:01:54 +05:30
this.errorMessage = __('Unable to update label prioritization at this time');
2018-03-17 18:26:18 +05:30
this.emptyState = document.querySelector('#js-priority-labels-empty-state');
2018-11-08 19:23:39 +05:30
this.$badgeItemTemplate = $('#js-badge-item-template');
2019-07-31 22:56:46 +05:30
if ('sortable' in this.prioritizedLabels.data()) {
Sortable.create(this.prioritizedLabels.get(0), {
filter: '.empty-message',
forceFallback: true,
fallbackClass: 'is-dragging',
dataIdAttr: 'data-id',
onUpdate: this.onPrioritySortUpdate.bind(this),
});
}
2018-03-17 18:26:18 +05:30
this.bindEvents();
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
bindEvents() {
this.prioritizedLabels.find('.btn-action').on('mousedown', this, this.onButtonActionClick);
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')}`);
2018-11-08 19:23:39 +05:30
$tooltip.tooltip('dispose');
2018-03-17 18:26:18 +05:30
_this.toggleLabelPriority($label, action);
_this.toggleEmptyState($label, $btn, action);
}
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
onButtonActionClick(e) {
e.stopPropagation();
$(e.currentTarget).tooltip('hide');
}
2019-12-04 20:38:33 +05:30
toggleEmptyState() {
2018-12-13 13:39:08 +05:30
this.emptyState.classList.toggle(
'hidden',
2019-09-04 21:01:54 +05:30
Boolean(this.prioritizedLabels[0].querySelector(':scope > li')),
2018-12-13 13:39:08 +05:30
);
2018-03-17 18:26:18 +05:30
}
toggleLabelPriority($label, action, persistState) {
if (persistState == null) {
persistState = true;
2017-09-10 17:25:29 +05:30
}
2018-03-17 18:26:18 +05:30
const url = $label.find('.js-toggle-priority').data('url');
let $target = this.prioritizedLabels;
let $from = this.otherLabels;
const rollbackLabelPosition = this.rollbackLabelPosition.bind(this, $label, action);
2017-09-10 17:25:29 +05:30
2018-03-17 18:26:18 +05:30
if (action === 'remove') {
$target = this.otherLabels;
$from = this.prioritizedLabels;
}
2018-11-08 19:23:39 +05:30
const $detachedLabel = $label.detach();
this.toggleLabelPriorityBadge($detachedLabel, action);
2019-03-02 22:35:43 +05:30
const $labelEls = $target.find('li.label-list-item');
/*
* If there is a label element in the target, we'd want to
* append the new label just right next to it.
*/
if ($labelEls.length) {
$labelEls.last().after($detachedLabel);
} else {
$detachedLabel.appendTo($target);
}
2018-11-08 19:23:39 +05:30
2018-03-17 18:26:18 +05:30
if ($from.find('li').length) {
$from.find('.empty-message').removeClass('hidden');
2016-11-03 12:29:30 +05:30
}
2018-03-17 18:26:18 +05:30
if ($target.find('> li:not(.empty-message)').length) {
$target.find('.empty-message').addClass('hidden');
}
// Return if we are not persisting state
if (!persistState) {
return;
}
if (action === 'remove') {
2018-12-13 13:39:08 +05:30
axios.delete(url).catch(rollbackLabelPosition);
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
// Restore empty message
if (!$from.find('li').length) {
2016-11-03 12:29:30 +05:30
$from.find('.empty-message').removeClass('hidden');
}
2018-03-17 18:26:18 +05:30
} else {
2018-12-13 13:39:08 +05:30
this.savePrioritySort($label, action).catch(rollbackLabelPosition);
2016-11-03 12:29:30 +05:30
}
2018-03-17 18:26:18 +05:30
}
2016-11-03 12:29:30 +05:30
2018-11-08 19:23:39 +05:30
toggleLabelPriorityBadge($label, action) {
if (action === 'remove') {
$('.js-priority-badge', $label).remove();
} else {
$('.label-links', $label).append(this.$badgeItemTemplate.clone().html());
}
}
2018-03-17 18:26:18 +05:30
onPrioritySortUpdate() {
2018-12-13 13:39:08 +05:30
this.savePrioritySort().catch(() => flash(this.errorMessage));
2018-03-17 18:26:18 +05:30
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
savePrioritySort() {
return axios.post(this.prioritizedLabels.data('url'), {
label_ids: this.getSortedLabelsIds(),
});
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
rollbackLabelPosition($label, originalAction) {
const action = originalAction === 'remove' ? 'add' : 'remove';
this.toggleLabelPriority($label, action, false);
flash(this.errorMessage);
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
getSortedLabelsIds() {
const sortedIds = [];
this.prioritizedLabels.find('> li').each(function() {
const id = $(this).data('id');
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
if (id) {
sortedIds.push(id);
}
});
return sortedIds;
2016-11-03 12:29:30 +05:30
}
2018-03-17 18:26:18 +05:30
}