/* eslint-disable one-var, no-self-compare, consistent-return, no-param-reassign, no-shadow */ /* global Issuable */ import $ from 'jquery'; import { template, escape } from 'lodash'; import Api from '~/api'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import { __, sprintf } from '~/locale'; import { sortMilestonesByDueDate } from '~/milestones/utils'; import axios from '~/lib/utils/axios_utils'; import { timeFor, parsePikadayDate, dateInWords } from '~/lib/utils/datetime_utility'; export default class MilestoneSelect { constructor(currentProject, els, options = {}) { if (currentProject !== null) { this.currentProject = typeof currentProject === 'string' ? JSON.parse(currentProject) : currentProject; } MilestoneSelect.init(els, options); } static init(els, options) { let $els = $(els); if (!els) { $els = $('.js-milestone-select'); } $els.each((i, dropdown) => { let milestoneLinkNoneTemplate, milestoneLinkTemplate, milestoneExpiredLinkTemplate, selectedMilestone, selectedMilestoneDefault; const $dropdown = $(dropdown); const issueUpdateURL = $dropdown.data('issueUpdate'); const showNo = $dropdown.data('showNo'); const showAny = $dropdown.data('showAny'); const showMenuAbove = $dropdown.data('showMenuAbove'); 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'); const $selectBox = $dropdown.closest('.selectbox'); const $block = $selectBox.closest('.block'); const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon'); const $value = $block.find('.value'); const $loading = $block.find('.block-loading').addClass('gl-display-none'); selectedMilestoneDefault = showAny ? '' : null; selectedMilestoneDefault = showNo && defaultNo ? __('No milestone') : selectedMilestoneDefault; selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault; if (issueUpdateURL) { milestoneLinkTemplate = template( '<%- title %>', ); milestoneExpiredLinkTemplate = template( '<%- title %> (Past due)', ); milestoneLinkNoneTemplate = `${__('None')}`; } return initDeprecatedJQueryDropdown($dropdown, { showMenuAbove, 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 }; 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 .map((m) => ({ ...m, // Public API includes `title` instead of `name`. name: m.title, })) .sort(sortMilestonesByDueDate), ) .then((data) => { const extraOptions = []; if (showAny) { extraOptions.push({ id: null, name: null, title: __('Any milestone'), }); } if (showNo && term.trim() === '') { 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 && data.length) { extraOptions.push({ type: 'divider' }); } callback(extraOptions.concat(data)); if (showMenuAbove) { $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove(); } $(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active'); }); }, renderRow: (milestone) => { const milestoneName = milestone.title || milestone.name; let milestoneDisplayName = escape(milestoneName); if (milestone.expired) { milestoneDisplayName = sprintf(__('%{milestone} (expired)'), { milestone: milestoneDisplayName, }); } return `