2017-01-10 18:02:20 -05:00
|
|
|
/* eslint-disable comma-dangle, class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, consistent-return, func-names, space-before-function-paren, max-len */
|
2018-03-09 15:18:59 -05:00
|
|
|
|
|
|
|
import $ from 'jquery';
|
2018-05-31 08:10:41 -04:00
|
|
|
import Sortable from 'sortablejs';
|
2016-12-13 22:01:05 -05:00
|
|
|
|
2018-01-24 22:03:21 -05:00
|
|
|
import flash from './flash';
|
|
|
|
import axios from './lib/utils/axios_utils';
|
2017-10-02 08:32:53 -04:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
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');
|
|
|
|
this.errorMessage = 'Unable to update label prioritization at this time';
|
|
|
|
this.emptyState = document.querySelector('#js-priority-labels-empty-state');
|
|
|
|
this.sortable = Sortable.create(this.prioritizedLabels.get(0), {
|
|
|
|
filter: '.empty-message',
|
|
|
|
forceFallback: true,
|
|
|
|
fallbackClass: 'is-dragging',
|
|
|
|
dataIdAttr: 'data-id',
|
|
|
|
onUpdate: this.onPrioritySortUpdate.bind(this),
|
|
|
|
});
|
|
|
|
this.bindEvents();
|
|
|
|
}
|
2016-09-12 13:05:47 -04:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
bindEvents() {
|
|
|
|
this.prioritizedLabels.find('.btn-action').on('mousedown', this, this.onButtonActionClick);
|
|
|
|
return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
|
|
|
|
}
|
2016-09-12 13:05:47 -04:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
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-04-19 15:16:18 -04:00
|
|
|
$tooltip.tooltip('dispose');
|
2017-10-10 13:22:34 -04:00
|
|
|
_this.toggleLabelPriority($label, action);
|
|
|
|
_this.toggleEmptyState($label, $btn, action);
|
|
|
|
}
|
2016-11-12 18:51:47 -05:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
onButtonActionClick(e) {
|
|
|
|
e.stopPropagation();
|
|
|
|
$(e.currentTarget).tooltip('hide');
|
|
|
|
}
|
2017-06-27 06:46:01 -04:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
toggleEmptyState($label, $btn, action) {
|
|
|
|
this.emptyState.classList.toggle('hidden', !!this.prioritizedLabels[0].querySelector(':scope > li'));
|
|
|
|
}
|
2016-09-12 13:05:47 -04:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
toggleLabelPriority($label, action, persistState) {
|
|
|
|
if (persistState == null) {
|
|
|
|
persistState = true;
|
2016-09-12 13:05:47 -04:00
|
|
|
}
|
2017-10-10 13:22:34 -04:00
|
|
|
const _this = this;
|
|
|
|
const url = $label.find('.js-toggle-priority').data('url');
|
|
|
|
let $target = this.prioritizedLabels;
|
|
|
|
let $from = this.otherLabels;
|
2018-01-24 22:03:21 -05:00
|
|
|
const rollbackLabelPosition = this.rollbackLabelPosition.bind(this, $label, action);
|
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
if (action === 'remove') {
|
|
|
|
$target = this.otherLabels;
|
|
|
|
$from = this.prioritizedLabels;
|
2016-09-12 13:05:47 -04:00
|
|
|
}
|
2017-10-10 13:22:34 -04:00
|
|
|
$label.detach().appendTo($target);
|
|
|
|
if ($from.find('li').length) {
|
|
|
|
$from.find('.empty-message').removeClass('hidden');
|
|
|
|
}
|
|
|
|
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-01-24 22:03:21 -05:00
|
|
|
axios.delete(url)
|
|
|
|
.catch(rollbackLabelPosition);
|
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
// Restore empty message
|
|
|
|
if (!$from.find('li').length) {
|
|
|
|
$from.find('.empty-message').removeClass('hidden');
|
|
|
|
}
|
|
|
|
} else {
|
2018-01-24 22:03:21 -05:00
|
|
|
this.savePrioritySort($label, action)
|
|
|
|
.catch(rollbackLabelPosition);
|
2016-09-12 13:05:47 -04:00
|
|
|
}
|
2017-10-10 13:22:34 -04:00
|
|
|
}
|
2016-09-12 13:05:47 -04:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
onPrioritySortUpdate() {
|
2018-01-24 22:03:21 -05:00
|
|
|
this.savePrioritySort()
|
|
|
|
.catch(() => flash(this.errorMessage));
|
2017-10-10 13:22:34 -04:00
|
|
|
}
|
2016-09-12 13:05:47 -04:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
savePrioritySort() {
|
2018-01-24 22:03:21 -05:00
|
|
|
return axios.post(this.prioritizedLabels.data('url'), {
|
|
|
|
label_ids: this.getSortedLabelsIds(),
|
2017-10-10 13:22:34 -04:00
|
|
|
});
|
|
|
|
}
|
2017-01-06 11:52:18 -05:00
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
rollbackLabelPosition($label, originalAction) {
|
|
|
|
const action = originalAction === 'remove' ? 'add' : 'remove';
|
|
|
|
this.toggleLabelPriority($label, action, false);
|
2018-01-24 22:04:55 -05:00
|
|
|
flash(this.errorMessage);
|
2016-09-12 13:05:47 -04:00
|
|
|
}
|
|
|
|
|
2017-10-10 13:22:34 -04:00
|
|
|
getSortedLabelsIds() {
|
|
|
|
const sortedIds = [];
|
|
|
|
this.prioritizedLabels.find('> li').each(function() {
|
|
|
|
const id = $(this).data('id');
|
|
|
|
|
|
|
|
if (id) {
|
|
|
|
sortedIds.push(id);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return sortedIds;
|
|
|
|
}
|
|
|
|
}
|