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

274 lines
9.9 KiB
JavaScript
Raw Normal View History

2020-05-24 23:13:21 +05:30
/* eslint-disable one-var, no-self-compare, consistent-return, no-param-reassign, no-shadow */
2017-08-17 22:00:37 +05:30
/* global Issuable */
2018-05-09 12:01:36 +05:30
import $ from 'jquery';
2020-05-24 23:13:21 +05:30
import { template, escape } from 'lodash';
2020-11-24 15:15:51 +05:30
import Api from '~/api';
2021-03-11 19:13:27 +05:30
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { __, sprintf } from '~/locale';
2021-09-30 23:02:18 +05:30
import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
2021-03-11 19:13:27 +05:30
import axios from './lib/utils/axios_utils';
import { timeFor, parsePikadayDate, dateInWords } from './lib/utils/datetime_utility';
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
export default class MilestoneSelect {
constructor(currentProject, els, options = {}) {
if (currentProject !== null) {
2018-10-15 14:42:47 +05:30
this.currentProject =
typeof currentProject === 'string' ? JSON.parse(currentProject) : currentProject;
2018-03-17 18:26:18 +05:30
}
2017-08-17 22:00:37 +05:30
2018-11-08 19:23:39 +05:30
MilestoneSelect.init(els, options);
2018-03-17 18:26:18 +05:30
}
2017-08-17 22:00:37 +05:30
2018-11-08 19:23:39 +05:30
static init(els, options) {
2018-03-17 18:26:18 +05:30
let $els = $(els);
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
if (!els) {
$els = $('.js-milestone-select');
}
2016-11-03 12:29:30 +05:30
2018-03-17 18:26:18 +05:30
$els.each((i, dropdown) => {
2018-10-15 14:42:47 +05:30
let milestoneLinkNoneTemplate,
milestoneLinkTemplate,
2020-11-24 15:15:51 +05:30
milestoneExpiredLinkTemplate,
2018-10-15 14:42:47 +05:30
selectedMilestone,
selectedMilestoneDefault;
2018-03-17 18:26:18 +05:30
const $dropdown = $(dropdown);
const issueUpdateURL = $dropdown.data('issueUpdate');
2018-03-27 19:54:05 +05:30
const showNo = $dropdown.data('showNo');
const showAny = $dropdown.data('showAny');
2018-03-17 18:26:18 +05:30
const showMenuAbove = $dropdown.data('showMenuAbove');
2018-03-27 19:54:05 +05:30
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');
2018-03-17 18:26:18 +05:30
const $selectBox = $dropdown.closest('.selectbox');
const $block = $selectBox.closest('.block');
const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
const $value = $block.find('.value');
2021-02-22 17:27:13 +05:30
const $loading = $block.find('.block-loading').addClass('gl-display-none');
2018-10-15 14:42:47 +05:30
selectedMilestoneDefault = showAny ? '' : null;
2019-09-04 21:01:54 +05:30
selectedMilestoneDefault =
2020-05-24 23:13:21 +05:30
showNo && defaultNo ? __('No milestone') : selectedMilestoneDefault;
2018-03-17 18:26:18 +05:30
selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
if (issueUpdateURL) {
2020-05-24 23:13:21 +05:30
milestoneLinkTemplate = template(
2018-11-08 19:23:39 +05:30
'<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>',
2018-10-15 14:42:47 +05:30
);
2020-11-24 15:15:51 +05:30
milestoneExpiredLinkTemplate = template(
'<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %> (Past due)</a>',
);
2019-09-04 21:01:54 +05:30
milestoneLinkNoneTemplate = `<span class="no-value">${__('None')}</span>`;
2018-03-17 18:26:18 +05:30
}
2020-11-24 15:15:51 +05:30
return initDeprecatedJQueryDropdown($dropdown, {
2019-12-04 20:38:33 +05:30
showMenuAbove,
2020-11-24 15:15:51 +05:30
data: (term, callback) => {
let contextId = parseInt($dropdown.get(0).dataset.projectId, 10);
let getMilestones = Api.projectMilestones.bind(Api);
const reqParams = { state: 'active', include_parent_milestones: true };
2017-08-17 22:00:37 +05:30
2020-11-24 15:15:51 +05:30
if (term) {
reqParams.search = term.trim();
}
if (!contextId) {
contextId = $dropdown.get(0).dataset.groupId;
delete reqParams.include_parent_milestones;
getMilestones = Api.groupMilestones.bind(Api);
}
// We don't use $.data() as it caches initial value and never updates!
return getMilestones(contextId, reqParams)
.then(({ data }) =>
data
2021-03-08 18:12:59 +05:30
.map((m) => ({
2020-11-24 15:15:51 +05:30
...m,
// Public API includes `title` instead of `name`.
name: m.title,
}))
2021-09-30 23:02:18 +05:30
.sort(sortMilestonesByDueDate),
2020-11-24 15:15:51 +05:30
)
2021-03-08 18:12:59 +05:30
.then((data) => {
2020-11-24 15:15:51 +05:30
const extraOptions = [];
if (showAny) {
extraOptions.push({
id: null,
name: null,
title: __('Any milestone'),
});
}
2021-04-17 20:07:23 +05:30
if (showNo && term.trim() === '') {
2020-11-24 15:15:51 +05:30
extraOptions.push({
id: -1,
name: __('No milestone'),
title: __('No milestone'),
});
}
if (showUpcoming) {
extraOptions.push({
id: -2,
name: '#upcoming',
title: __('Upcoming'),
});
}
if (showStarted) {
extraOptions.push({
id: -3,
name: '#started',
title: __('Started'),
});
}
if (extraOptions.length) {
extraOptions.push({ type: 'divider' });
}
callback(extraOptions.concat(data));
if (showMenuAbove) {
$dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
}
$(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
});
},
2021-03-08 18:12:59 +05:30
renderRow: (milestone) => {
2020-11-24 15:15:51 +05:30
const milestoneName = milestone.title || milestone.name;
let milestoneDisplayName = escape(milestoneName);
if (milestone.expired) {
milestoneDisplayName = sprintf(__('%{milestone} (expired)'), {
milestone: milestoneDisplayName,
});
}
return `
<li data-milestone-id="${escape(milestoneName)}">
2018-03-17 18:26:18 +05:30
<a href='#' class='dropdown-menu-milestone-link'>
2020-11-24 15:15:51 +05:30
${milestoneDisplayName}
2018-03-17 18:26:18 +05:30
</a>
</li>
2020-11-24 15:15:51 +05:30
`;
},
2018-03-17 18:26:18 +05:30
filterable: true,
2020-11-24 15:15:51 +05:30
filterRemote: true,
2018-03-17 18:26:18 +05:30
search: {
2018-10-15 14:42:47 +05:30
fields: ['title'],
2018-03-17 18:26:18 +05:30
},
selectable: true,
2019-12-04 20:38:33 +05:30
toggleLabel: (selected, el) => {
2018-03-17 18:26:18 +05:30
if (selected && 'id' in selected && $(el).hasClass('is-active')) {
return selected.title;
}
2020-05-24 23:13:21 +05:30
return defaultLabel;
2018-03-17 18:26:18 +05:30
},
2019-12-04 20:38:33 +05:30
defaultLabel,
2018-03-27 19:54:05 +05:30
fieldName: $dropdown.data('fieldName'),
2021-03-08 18:12:59 +05:30
text: (milestone) => escape(milestone.title),
id: (milestone) => {
2020-06-23 00:09:42 +05:30
if (milestone !== undefined) {
if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
return milestone.name;
}
return milestone.id;
2018-03-17 18:26:18 +05:30
}
},
hidden: () => {
$selectBox.hide();
// display:block overrides the hide-collapse rule
return $value.css('display', '');
},
2021-03-08 18:12:59 +05:30
opened: (e) => {
2018-03-17 18:26:18 +05:30
const $el = $(e.currentTarget);
2021-11-11 11:23:49 +05:30
if (options.handleClick) {
2018-03-17 18:26:18 +05:30
selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
}
$('a.is-active', $el).removeClass('is-active');
2020-11-24 15:15:51 +05:30
$(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
2018-03-17 18:26:18 +05:30
},
2021-11-11 11:23:49 +05:30
vue: false,
2021-03-08 18:12:59 +05:30
clicked: (clickEvent) => {
2019-12-04 20:38:33 +05:30
const { e } = clickEvent;
2018-03-17 18:26:18 +05:30
let selected = clickEvent.selectedObj;
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
if (!selected) return;
2017-08-17 22:00:37 +05:30
2018-03-17 18:26:18 +05:30
if (options.handleClick) {
e.preventDefault();
options.handleClick(selected);
return;
}
const page = $('body').attr('data-page');
const isIssueIndex = page === 'projects:issues:index';
2018-10-15 14:42:47 +05:30
const isMRIndex = page === page && page === 'projects:merge_requests:index';
const isSelecting = selected.name !== selectedMilestone;
2018-03-17 18:26:18 +05:30
selectedMilestone = isSelecting ? selected.name : selectedMilestoneDefault;
2018-04-05 14:03:07 +05:30
2018-10-15 14:42:47 +05:30
if (
$dropdown.hasClass('js-filter-bulk-update') ||
$dropdown.hasClass('js-issuable-form-dropdown')
) {
2018-03-17 18:26:18 +05:30
e.preventDefault();
return;
}
2021-04-29 21:17:54 +05:30
if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
2018-03-17 18:26:18 +05:30
return Issuable.filterResults($dropdown.closest('form'));
} else if ($dropdown.hasClass('js-filter-submit')) {
return $dropdown.closest('form').submit();
2021-11-11 11:23:49 +05:30
}
2018-03-17 18:26:18 +05:30
2021-11-11 11:23:49 +05:30
selected = $selectBox.find('input[type="hidden"]').val();
2018-03-17 18:26:18 +05:30
2021-11-11 11:23:49 +05:30
const data = {};
data[abilityName] = {};
data[abilityName].milestone_id = selected != null ? selected : null;
$loading.removeClass('gl-display-none');
$dropdown.trigger('loading.gl.dropdown');
return axios
.put(issueUpdateURL, data)
.then(({ data }) => {
$dropdown.trigger('loaded.gl.dropdown');
$loading.addClass('gl-display-none');
$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(
data.milestone.expired
? milestoneExpiredLinkTemplate({
...data.milestone,
remaining: sprintf(__('%{due_date} (Past due)'), {
due_date: dateInWords(parsePikadayDate(data.milestone.due_date)),
}),
})
: milestoneLinkTemplate(data.milestone),
);
2020-05-24 23:13:21 +05:30
return $sidebarCollapsedValue
2021-11-11 11:23:49 +05:30
.attr(
'data-original-title',
`${data.milestone.name}<br />${data.milestone.remaining}`,
)
2020-05-24 23:13:21 +05:30
.find('span')
2021-11-11 11:23:49 +05:30
.text(data.milestone.title);
}
$value.html(milestoneLinkNoneTemplate);
return $sidebarCollapsedValue
.attr('data-original-title', __('Milestone'))
.find('span')
.text(__('None'));
})
.catch(() => {
$loading.addClass('gl-display-none');
});
2018-10-15 14:42:47 +05:30
},
2016-09-13 17:45:13 +05:30
});
2018-03-17 18:26:18 +05:30
});
}
}
2018-11-08 19:23:39 +05:30
window.MilestoneSelect = MilestoneSelect;