/* 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 Api from '~/api'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import { __, sprintf } from '~/locale'; import boardsStore, { boardStoreIssueSet, boardStoreIssueDelete, } from './boards/stores/boards_store'; 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((mA, mB) => { const dueDateA = mA.due_date ? parsePikadayDate(mA.due_date) : null; const dueDateB = mB.due_date ? parsePikadayDate(mB.due_date) : null; // Move all expired milestones to the bottom. if (mA.expired) return 1; if (mB.expired) return -1; // Move milestones without due dates just above expired milestones. if (!dueDateA) return 1; if (!dueDateB) return -1; // Sort by due date in ascending order. return dueDateA - dueDateB; }), ) .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) { 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 `