2020-02-18 04:09:24 -05:00
|
|
|
/* eslint-disable max-classes-per-file */
|
2018-03-09 15:18:59 -05:00
|
|
|
import $ from 'jquery';
|
2017-08-09 07:57:45 -04:00
|
|
|
import Pikaday from 'pikaday';
|
2018-07-02 03:46:40 -04:00
|
|
|
import dateFormat from 'dateformat';
|
2018-04-19 10:43:20 -04:00
|
|
|
import { __ } from '~/locale';
|
2018-01-26 05:41:44 -05:00
|
|
|
import axios from './lib/utils/axios_utils';
|
2018-10-24 06:51:33 -04:00
|
|
|
import { timeFor, parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
|
2018-10-10 13:08:43 -04:00
|
|
|
import boardsStore from './boards/stores/boards_store';
|
2020-08-24 14:10:19 -04:00
|
|
|
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
|
2017-07-18 13:38:40 -04:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
class DueDateSelect {
|
|
|
|
constructor({ $dropdown, $loading } = {}) {
|
|
|
|
const $dropdownParent = $dropdown.closest('.dropdown');
|
|
|
|
const $block = $dropdown.closest('.block');
|
|
|
|
this.$loading = $loading;
|
|
|
|
this.$dropdown = $dropdown;
|
|
|
|
this.$dropdownParent = $dropdownParent;
|
|
|
|
this.$datePicker = $dropdownParent.find('.js-due-date-calendar');
|
|
|
|
this.$block = $block;
|
2018-04-19 10:43:20 -04:00
|
|
|
this.$sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
|
2017-03-11 02:30:44 -05:00
|
|
|
this.$selectbox = $dropdown.closest('.selectbox');
|
|
|
|
this.$value = $block.find('.value');
|
|
|
|
this.$valueContent = $block.find('.value-content');
|
|
|
|
this.$sidebarValue = $('.js-due-date-sidebar-value', $block);
|
2018-02-20 17:20:48 -05:00
|
|
|
this.fieldName = $dropdown.data('fieldName');
|
|
|
|
this.abilityName = $dropdown.data('abilityName');
|
|
|
|
this.issueUpdateURL = $dropdown.data('issueUpdate');
|
2017-03-11 02:30:44 -05:00
|
|
|
|
|
|
|
this.rawSelectedDate = null;
|
|
|
|
this.displayedDate = null;
|
|
|
|
this.datePayload = null;
|
|
|
|
|
|
|
|
this.initGlDropdown();
|
|
|
|
this.initRemoveDueDate();
|
|
|
|
this.initDatePicker();
|
|
|
|
}
|
2017-01-04 08:16:14 -05:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
initGlDropdown() {
|
2020-08-24 14:10:19 -04:00
|
|
|
initDeprecatedJQueryDropdown(this.$dropdown, {
|
2017-03-11 02:30:44 -05:00
|
|
|
opened: () => {
|
|
|
|
const calendar = this.$datePicker.data('pikaday');
|
|
|
|
calendar.show();
|
|
|
|
},
|
|
|
|
hidden: () => {
|
|
|
|
this.$selectbox.hide();
|
|
|
|
this.$value.css('display', '');
|
2017-10-18 07:31:01 -04:00
|
|
|
},
|
2020-02-26 10:08:56 -05:00
|
|
|
shouldPropagate: false,
|
2017-03-11 02:30:44 -05:00
|
|
|
});
|
|
|
|
}
|
2017-01-04 08:16:14 -05:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
initDatePicker() {
|
|
|
|
const $dueDateInput = $(`input[name='${this.fieldName}']`);
|
|
|
|
const calendar = new Pikaday({
|
|
|
|
field: $dueDateInput.get(0),
|
|
|
|
theme: 'gitlab-theme',
|
|
|
|
format: 'yyyy-mm-dd',
|
2017-10-18 07:31:01 -04:00
|
|
|
parse: dateString => parsePikadayDate(dateString),
|
|
|
|
toString: date => pikadayToString(date),
|
2018-07-02 03:46:40 -04:00
|
|
|
onSelect: dateText => {
|
2017-10-18 07:31:01 -04:00
|
|
|
$dueDateInput.val(calendar.toString(dateText));
|
2017-01-04 08:16:14 -05:00
|
|
|
|
2016-10-20 03:54:33 -04:00
|
|
|
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
|
2018-10-10 13:08:43 -04:00
|
|
|
boardsStore.detail.issue.dueDate = $dueDateInput.val();
|
2016-10-20 03:54:33 -04:00
|
|
|
this.updateIssueBoardIssue();
|
|
|
|
} else {
|
2017-03-11 02:30:44 -05:00
|
|
|
this.saveDueDate(true);
|
2016-10-20 03:54:33 -04:00
|
|
|
}
|
2017-10-18 07:31:01 -04:00
|
|
|
},
|
2018-11-06 16:16:49 -05:00
|
|
|
firstDay: gon.first_day_of_week,
|
2017-03-11 02:30:44 -05:00
|
|
|
});
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2017-10-18 07:31:01 -04:00
|
|
|
calendar.setDate(parsePikadayDate($dueDateInput.val()));
|
2017-03-11 02:30:44 -05:00
|
|
|
this.$datePicker.append(calendar.el);
|
|
|
|
this.$datePicker.data('pikaday', calendar);
|
|
|
|
}
|
|
|
|
|
|
|
|
initRemoveDueDate() {
|
2018-07-02 03:46:40 -04:00
|
|
|
this.$block.on('click', '.js-remove-due-date', e => {
|
2017-03-11 02:30:44 -05:00
|
|
|
const calendar = this.$datePicker.data('pikaday');
|
|
|
|
e.preventDefault();
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
calendar.setDate(null);
|
2016-11-11 07:57:51 -05:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
|
2018-10-10 13:08:43 -04:00
|
|
|
boardsStore.detail.issue.dueDate = '';
|
2017-03-11 02:30:44 -05:00
|
|
|
this.updateIssueBoardIssue();
|
2016-10-11 04:19:18 -04:00
|
|
|
} else {
|
2017-10-18 07:31:01 -04:00
|
|
|
$(`input[name='${this.fieldName}']`).val('');
|
|
|
|
this.saveDueDate(false);
|
2016-10-11 04:19:18 -04:00
|
|
|
}
|
2017-03-11 02:30:44 -05:00
|
|
|
});
|
|
|
|
}
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
saveDueDate(isDropdown) {
|
|
|
|
this.parseSelectedDate();
|
|
|
|
this.prepSelectedDate();
|
|
|
|
this.submitSelectedDate(isDropdown);
|
|
|
|
}
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
parseSelectedDate() {
|
|
|
|
this.rawSelectedDate = $(`input[name='${this.fieldName}']`).val();
|
2016-10-20 03:54:33 -04:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
if (this.rawSelectedDate.length) {
|
|
|
|
// Construct Date object manually to avoid buggy dateString support within Date constructor
|
|
|
|
const dateArray = this.rawSelectedDate.split('-').map(v => parseInt(v, 10));
|
|
|
|
const dateObj = new Date(dateArray[0], dateArray[1] - 1, dateArray[2]);
|
|
|
|
this.displayedDate = dateFormat(dateObj, 'mmm d, yyyy');
|
|
|
|
} else {
|
2019-04-17 13:17:59 -04:00
|
|
|
this.displayedDate = __('None');
|
2016-10-20 03:54:33 -04:00
|
|
|
}
|
2017-03-11 02:30:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
prepSelectedDate() {
|
|
|
|
const datePayload = {};
|
|
|
|
datePayload[this.abilityName] = {};
|
|
|
|
datePayload[this.abilityName].due_date = this.rawSelectedDate;
|
|
|
|
this.datePayload = datePayload;
|
|
|
|
}
|
|
|
|
|
2017-10-18 07:31:01 -04:00
|
|
|
updateIssueBoardIssue() {
|
2019-12-18 07:07:48 -05:00
|
|
|
// eslint-disable-next-line no-jquery/no-fade
|
2017-03-11 02:30:44 -05:00
|
|
|
this.$loading.fadeIn();
|
|
|
|
this.$dropdown.trigger('loading.gl.dropdown');
|
|
|
|
this.$selectbox.hide();
|
|
|
|
this.$value.css('display', '');
|
2017-04-20 07:11:51 -04:00
|
|
|
const fadeOutLoader = () => {
|
2019-12-18 07:07:48 -05:00
|
|
|
// eslint-disable-next-line no-jquery/no-fade
|
2017-04-20 07:11:51 -04:00
|
|
|
this.$loading.fadeOut();
|
|
|
|
};
|
2017-03-11 02:30:44 -05:00
|
|
|
|
2018-10-10 13:08:43 -04:00
|
|
|
boardsStore.detail.issue
|
2018-07-02 03:46:40 -04:00
|
|
|
.update(this.$dropdown.attr('data-issue-update'))
|
2017-04-20 07:11:51 -04:00
|
|
|
.then(fadeOutLoader)
|
|
|
|
.catch(fadeOutLoader);
|
2017-03-11 02:30:44 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
submitSelectedDate(isDropdown) {
|
2018-01-26 05:41:44 -05:00
|
|
|
const selectedDateValue = this.datePayload[this.abilityName].due_date;
|
2019-04-17 13:17:59 -04:00
|
|
|
const hasDueDate = this.displayedDate !== __('None');
|
2018-04-19 10:43:20 -04:00
|
|
|
const displayedDateStyle = hasDueDate ? 'bold' : 'no-value';
|
2017-03-11 02:30:44 -05:00
|
|
|
|
2019-12-18 07:07:48 -05:00
|
|
|
// eslint-disable-next-line no-jquery/no-fade
|
2018-01-26 05:41:44 -05:00
|
|
|
this.$loading.removeClass('hidden').fadeIn();
|
2016-10-20 03:54:33 -04:00
|
|
|
|
2018-01-26 05:41:44 -05:00
|
|
|
if (isDropdown) {
|
|
|
|
this.$dropdown.trigger('loading.gl.dropdown');
|
|
|
|
this.$selectbox.hide();
|
|
|
|
}
|
2017-03-11 02:30:44 -05:00
|
|
|
|
2018-01-26 05:41:44 -05:00
|
|
|
this.$value.css('display', '');
|
|
|
|
this.$valueContent.html(`<span class='${displayedDateStyle}'>${this.displayedDate}</span>`);
|
|
|
|
this.$sidebarValue.html(this.displayedDate);
|
2017-03-11 02:30:44 -05:00
|
|
|
|
2018-01-26 05:41:44 -05:00
|
|
|
$('.js-remove-due-date-holder').toggleClass('hidden', selectedDateValue.length);
|
|
|
|
|
2018-07-02 03:46:40 -04:00
|
|
|
return axios.put(this.issueUpdateURL, this.datePayload).then(() => {
|
|
|
|
const tooltipText = hasDueDate
|
|
|
|
? `${__('Due date')}<br />${selectedDateValue} (${timeFor(selectedDateValue)})`
|
|
|
|
: __('Due date');
|
|
|
|
if (isDropdown) {
|
|
|
|
this.$dropdown.trigger('loaded.gl.dropdown');
|
|
|
|
this.$dropdown.dropdown('toggle');
|
|
|
|
}
|
|
|
|
this.$sidebarCollapsedValue.attr('data-original-title', tooltipText);
|
2018-04-19 10:43:20 -04:00
|
|
|
|
2019-12-18 07:07:48 -05:00
|
|
|
// eslint-disable-next-line no-jquery/no-fade
|
2018-07-02 03:46:40 -04:00
|
|
|
return this.$loading.fadeOut();
|
|
|
|
});
|
2016-10-11 04:19:18 -04:00
|
|
|
}
|
2017-03-11 02:30:44 -05:00
|
|
|
}
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2017-10-18 07:31:01 -04:00
|
|
|
export default class DueDateSelectors {
|
2017-03-11 02:30:44 -05:00
|
|
|
constructor() {
|
|
|
|
this.initMilestoneDatePicker();
|
|
|
|
this.initIssuableSelect();
|
|
|
|
}
|
2017-10-18 07:31:01 -04:00
|
|
|
// eslint-disable-next-line class-methods-use-this
|
2017-03-11 02:30:44 -05:00
|
|
|
initMilestoneDatePicker() {
|
2017-10-18 07:31:01 -04:00
|
|
|
$('.datepicker').each(function initPikadayMilestone() {
|
2017-03-11 02:30:44 -05:00
|
|
|
const $datePicker = $(this);
|
2018-06-29 19:04:03 -04:00
|
|
|
const datePickerVal = $datePicker.val();
|
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
const calendar = new Pikaday({
|
|
|
|
field: $datePicker.get(0),
|
2017-04-21 11:05:38 -04:00
|
|
|
theme: 'gitlab-theme animate-picker',
|
2017-03-11 02:30:44 -05:00
|
|
|
format: 'yyyy-mm-dd',
|
2017-04-21 11:05:38 -04:00
|
|
|
container: $datePicker.parent().get(0),
|
2017-10-18 07:31:01 -04:00
|
|
|
parse: dateString => parsePikadayDate(dateString),
|
|
|
|
toString: date => pikadayToString(date),
|
2017-03-11 02:30:44 -05:00
|
|
|
onSelect(dateText) {
|
2017-10-18 07:31:01 -04:00
|
|
|
$datePicker.val(calendar.toString(dateText));
|
|
|
|
},
|
2018-11-06 16:16:49 -05:00
|
|
|
firstDay: gon.first_day_of_week,
|
2016-11-15 12:48:30 -05:00
|
|
|
});
|
2017-06-13 14:53:40 -04:00
|
|
|
|
2018-06-29 19:04:03 -04:00
|
|
|
calendar.setDate(parsePikadayDate(datePickerVal));
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
$datePicker.data('pikaday', calendar);
|
|
|
|
});
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2018-07-02 03:46:40 -04:00
|
|
|
$('.js-clear-due-date,.js-clear-start-date').on('click', e => {
|
2017-03-11 02:30:44 -05:00
|
|
|
e.preventDefault();
|
2018-07-02 03:46:40 -04:00
|
|
|
const calendar = $(e.target)
|
|
|
|
.siblings('.datepicker')
|
|
|
|
.data('pikaday');
|
2017-03-11 02:30:44 -05:00
|
|
|
calendar.setDate(null);
|
|
|
|
});
|
|
|
|
}
|
2017-10-18 07:31:01 -04:00
|
|
|
// eslint-disable-next-line class-methods-use-this
|
2017-03-11 02:30:44 -05:00
|
|
|
initIssuableSelect() {
|
2018-07-02 03:46:40 -04:00
|
|
|
const $loading = $('.js-issuable-update .due_date')
|
|
|
|
.find('.block-loading')
|
|
|
|
.hide();
|
2016-10-11 04:19:18 -04:00
|
|
|
|
2017-03-11 02:30:44 -05:00
|
|
|
$('.js-due-date-select').each((i, dropdown) => {
|
|
|
|
const $dropdown = $(dropdown);
|
2017-10-18 07:31:01 -04:00
|
|
|
// eslint-disable-next-line no-new
|
2017-03-11 02:30:44 -05:00
|
|
|
new DueDateSelect({
|
|
|
|
$dropdown,
|
2017-10-18 07:31:01 -04:00
|
|
|
$loading,
|
2016-10-11 04:19:18 -04:00
|
|
|
});
|
2017-03-11 02:30:44 -05:00
|
|
|
});
|
2016-10-11 04:19:18 -04:00
|
|
|
}
|
2017-03-11 02:30:44 -05:00
|
|
|
}
|