gitlab-org--gitlab-foss/app/assets/javascripts/milestone_select.js

267 lines
9.6 KiB
JavaScript
Raw Normal View History

/* eslint-disable one-var, no-self-compare, consistent-return, no-param-reassign, no-shadow */
/* global Issuable */
/* global ListMilestone */
import $ from 'jquery';
import { template, escape } from 'lodash';
import { __ } from '~/locale';
import '~/gl_dropdown';
2018-01-31 04:34:25 -05:00
import axios from './lib/utils/axios_utils';
import { timeFor } from './lib/utils/datetime_utility';
import ModalStore from './boards/stores/modal_store';
import boardsStore, {
boardStoreIssueSet,
boardStoreIssueDelete,
} from './boards/stores/boards_store';
2017-12-28 15:07:05 -05:00
export default class MilestoneSelect {
constructor(currentProject, els, options = {}) {
if (currentProject !== null) {
this.currentProject =
typeof currentProject === 'string' ? JSON.parse(currentProject) : currentProject;
2017-12-28 15:07:05 -05:00
}
2017-02-01 12:02:17 -05:00
MilestoneSelect.init(els, options);
2017-12-28 15:07:05 -05:00
}
2017-02-01 12:02:17 -05:00
static init(els, options) {
2017-12-28 15:07:05 -05:00
let $els = $(els);
2017-02-01 12:02:17 -05:00
2017-12-28 15:07:05 -05:00
if (!els) {
$els = $('.js-milestone-select');
}
2017-12-28 15:07:05 -05:00
$els.each((i, dropdown) => {
let milestoneLinkNoneTemplate,
milestoneLinkTemplate,
selectedMilestone,
selectedMilestoneDefault;
2017-12-28 15:07:05 -05:00
const $dropdown = $(dropdown);
const milestonesUrl = $dropdown.data('milestones');
const issueUpdateURL = $dropdown.data('issueUpdate');
2018-02-20 17:20:48 -05:00
const showNo = $dropdown.data('showNo');
const showAny = $dropdown.data('showAny');
2017-12-28 15:07:05 -05:00
const showMenuAbove = $dropdown.data('showMenuAbove');
2018-02-20 17:20:48 -05:00
const showUpcoming = $dropdown.data('showUpcoming');
const showStarted = $dropdown.data('showStarted');
const useId = $dropdown.data('useId');
const defaultLabel = $dropdown.data('defaultLabel');
const defaultNo = $dropdown.data('defaultNo');
const abilityName = $dropdown.data('abilityName');
2017-12-28 15:07:05 -05:00
const $selectBox = $dropdown.closest('.selectbox');
const $block = $selectBox.closest('.block');
const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
const $value = $block.find('.value');
// eslint-disable-next-line no-jquery/no-fade
2017-12-28 15:07:05 -05:00
const $loading = $block.find('.block-loading').fadeOut();
selectedMilestoneDefault = showAny ? '' : null;
selectedMilestoneDefault =
showNo && defaultNo ? __('No milestone') : selectedMilestoneDefault;
2017-12-28 15:07:05 -05:00
selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
2017-12-28 15:07:05 -05:00
if (issueUpdateURL) {
milestoneLinkTemplate = template(
'<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>',
);
milestoneLinkNoneTemplate = `<span class="no-value">${__('None')}</span>`;
2017-12-28 15:07:05 -05:00
}
return $dropdown.glDropdown({
showMenuAbove,
data: (term, callback) =>
axios.get(milestonesUrl).then(({ data }) => {
2018-01-31 04:34:25 -05:00
const extraOptions = [];
if (showAny) {
extraOptions.push({
id: null,
name: null,
title: __('Any milestone'),
2018-01-31 04:34:25 -05:00
});
}
if (showNo) {
extraOptions.push({
id: -1,
name: __('No milestone'),
title: __('No milestone'),
2018-01-31 04:34:25 -05:00
});
}
if (showUpcoming) {
extraOptions.push({
id: -2,
name: '#upcoming',
title: __('Upcoming'),
2018-01-31 04:34:25 -05:00
});
}
if (showStarted) {
extraOptions.push({
id: -3,
name: '#started',
title: __('Started'),
2018-01-31 04:34:25 -05:00
});
}
if (extraOptions.length) {
extraOptions.push({ type: 'divider' });
2018-01-31 04:34:25 -05:00
}
2018-01-31 04:34:25 -05:00
callback(extraOptions.concat(data));
if (showMenuAbove) {
$dropdown.data('glDropdown').positionMenuAbove();
}
$(`[data-milestone-id="${escape(selectedMilestone)}"] > a`).addClass('is-active');
2018-01-31 04:34:25 -05:00
}),
2017-12-28 15:07:05 -05:00
renderRow: milestone => `
<li data-milestone-id="${escape(milestone.name)}">
2017-12-28 15:07:05 -05:00
<a href='#' class='dropdown-menu-milestone-link'>
${escape(milestone.title)}
2017-12-28 15:07:05 -05:00
</a>
</li>
`,
filterable: true,
search: {
fields: ['title'],
2017-12-28 15:07:05 -05:00
},
selectable: true,
toggleLabel: (selected, el) => {
2017-12-28 15:07:05 -05:00
if (selected && 'id' in selected && $(el).hasClass('is-active')) {
return selected.title;
}
return defaultLabel;
2017-12-28 15:07:05 -05:00
},
defaultLabel,
2018-02-20 17:20:48 -05:00
fieldName: $dropdown.data('fieldName'),
text: milestone => escape(milestone.title),
id: milestone => {
if (milestone !== undefined) {
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
return milestone.name;
}
return milestone.id;
2017-12-28 15:07:05 -05:00
}
},
hidden: () => {
$selectBox.hide();
// display:block overrides the hide-collapse rule
return $value.css('display', '');
},
opened: e => {
2017-12-28 15:07:05 -05:00
const $el = $(e.currentTarget);
if ($dropdown.hasClass('js-issue-board-sidebar') || options.handleClick) {
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
}
$('a.is-active', $el).removeClass('is-active');
$(`[data-milestone-id="${escape(selectedMilestone)}"] > a`, $el).addClass('is-active');
2017-12-28 15:07:05 -05:00
},
vue: $dropdown.hasClass('js-issue-board-sidebar'),
clicked: clickEvent => {
const { e } = clickEvent;
2017-12-28 15:07:05 -05:00
let selected = clickEvent.selectedObj;
let data, modalStoreFilter;
2017-12-28 15:07:05 -05:00
if (!selected) return;
2017-02-01 12:02:17 -05:00
2017-12-28 15:07:05 -05:00
if (options.handleClick) {
e.preventDefault();
options.handleClick(selected);
return;
}
2017-02-01 12:02:17 -05:00
2017-12-28 15:07:05 -05:00
const page = $('body').attr('data-page');
const isIssueIndex = page === 'projects:issues:index';
const isMRIndex = page === page && page === 'projects:merge_requests:index';
const isSelecting = selected.name !== selectedMilestone;
2017-12-28 15:07:05 -05:00
selectedMilestone = isSelecting ? selected.name : selectedMilestoneDefault;
if (
$dropdown.hasClass('js-filter-bulk-update') ||
$dropdown.hasClass('js-issuable-form-dropdown')
) {
2017-12-28 15:07:05 -05:00
e.preventDefault();
return;
}
2017-12-28 15:07:05 -05:00
if ($dropdown.closest('.add-issues-modal').length) {
modalStoreFilter = ModalStore.store.filter;
2017-12-28 15:07:05 -05:00
}
if (modalStoreFilter) {
modalStoreFilter[$dropdown.data('fieldName')] = selected.name;
2017-12-28 15:07:05 -05:00
e.preventDefault();
} else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
return Issuable.filterResults($dropdown.closest('form'));
} else if ($dropdown.hasClass('js-filter-submit')) {
return $dropdown.closest('form').submit();
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
if (selected.id !== -1 && isSelecting) {
boardStoreIssueSet(
'milestone',
new ListMilestone({
id: selected.id,
title: selected.name,
}),
);
2016-07-24 16:45:11 -04:00
} else {
boardStoreIssueDelete('milestone');
2017-12-28 15:07:05 -05:00
}
$dropdown.trigger('loading.gl.dropdown');
// eslint-disable-next-line no-jquery/no-fade
2017-12-28 15:07:05 -05:00
$loading.removeClass('hidden').fadeIn();
boardsStore.detail.issue
.update($dropdown.attr('data-issue-update'))
2017-12-28 15:07:05 -05:00
.then(() => {
2016-07-24 16:45:11 -04:00
$dropdown.trigger('loaded.gl.dropdown');
// eslint-disable-next-line no-jquery/no-fade
2016-07-24 16:45:11 -04:00
$loading.fadeOut();
2017-12-28 15:07:05 -05:00
})
.catch(() => {
// eslint-disable-next-line no-jquery/no-fade
2017-12-28 15:07:05 -05:00
$loading.fadeOut();
2016-07-24 16:45:11 -04:00
});
2017-12-28 15:07:05 -05:00
} else {
selected = $selectBox.find('input[type="hidden"]').val();
data = {};
data[abilityName] = {};
data[abilityName].milestone_id = selected != null ? selected : null;
// eslint-disable-next-line no-jquery/no-fade
2017-12-28 15:07:05 -05:00
$loading.removeClass('hidden').fadeIn();
$dropdown.trigger('loading.gl.dropdown');
return axios
.put(issueUpdateURL, data)
2018-01-31 04:34:25 -05:00
.then(({ data }) => {
$dropdown.trigger('loaded.gl.dropdown');
// eslint-disable-next-line no-jquery/no-fade
2018-01-31 04:34:25 -05:00
$loading.fadeOut();
$selectBox.hide();
$value.css('display', '');
if (data.milestone != null) {
data.milestone.remaining = timeFor(data.milestone.due_date);
data.milestone.name = data.milestone.title;
$value.html(milestoneLinkTemplate(data.milestone));
return $sidebarCollapsedValue
.attr(
'data-original-title',
`${data.milestone.name}<br />${data.milestone.remaining}`,
)
.find('span')
.text(data.milestone.title);
2018-01-31 04:34:25 -05:00
}
$value.html(milestoneLinkNoneTemplate);
return $sidebarCollapsedValue
.attr('data-original-title', __('Milestone'))
.find('span')
.text(__('None'));
})
.catch(() => {
// eslint-disable-next-line no-jquery/no-fade
$loading.fadeOut();
2018-01-31 04:34:25 -05:00
});
2016-07-24 16:45:11 -04:00
}
},
2016-07-24 16:45:11 -04:00
});
2017-12-28 15:07:05 -05:00
});
}
}
window.MilestoneSelect = MilestoneSelect;