easyappointments/assets/js/working_plan_exceptions_modal.js
2021-11-25 08:40:48 +01:00

415 lines
14 KiB
JavaScript

$(function () {
'use strict';
var $modal = $('#working-plan-exceptions-modal');
var $date = $('#working-plan-exceptions-date');
var $start = $('#working-plan-exceptions-start');
var $end = $('#working-plan-exceptions-end');
var $breaks = $('#working-plan-exceptions-breaks');
var $save = $('#working-plan-exceptions-save');
var deferred = null;
var enableSubmit = false;
var enableCancel = false;
function resetModal() {
$date.val('');
$start.val('');
$end.val('');
$breaks.find('tbody').empty();
}
function validate() {
$modal.find('.is-invalid').removeClass('is-invalid');
var date = $date.datepicker('getDate');
if (!date) {
$date.addClass('is-invalid');
}
var start = $start.timepicker('getDate');
if (!start) {
$start.addClass('is-invalid');
}
var end = $end.timepicker('getDate');
if (!end) {
$end.addClass('is-invalid');
}
return !$modal.find('.is-invalid').length;
}
function onModalHidden() {
resetModal();
}
function getBreaks() {
var breaks = [];
$breaks.find('tbody tr').each(function (index, tr) {
var $tr = $(tr);
if ($tr.find('input:text').length) {
return true;
}
var start = $tr.find('.working-plan-exceptions-break-start').text();
var end = $tr.find('.working-plan-exceptions-break-end').text();
breaks.push({
start: moment(start, GlobalVariables.timeFormat === 'regular' ? 'h:mm a' : 'HH:mm').format('HH:mm'),
end: moment(end, GlobalVariables.timeFormat === 'regular' ? 'h:mm a' : 'HH:mm').format('HH:mm')
});
});
// Sort breaks increasingly by hour within day
breaks.sort(function (break1, break2) {
// We can do a direct string comparison since we have time based on 24 hours clock.
return break1.start.localeCompare(break2.start);
});
return breaks;
}
function onSaveClick() {
if (!deferred) {
return;
}
if (!validate()) {
return;
}
var date = moment($date.datepicker('getDate')).format('YYYY-MM-DD');
var workingPlanException = {
start: moment($start.datetimepicker('getDate')).format('HH:mm'),
end: moment($end.datetimepicker('getDate')).format('HH:mm'),
breaks: getBreaks()
};
deferred.resolve(date, workingPlanException);
$modal.modal('hide');
resetModal();
}
function editableTimeCell($target) {
$target.editable(
function (value) {
// Do not return the value because the user needs to press the "Save" button.
return value;
},
{
event: 'edit',
height: '30px',
submit: $('<button/>', {
'type': 'button',
'class': 'd-none submit-editable',
'text': EALang.save
}).get(0).outerHTML,
cancel: $('<button/>', {
'type': 'button',
'class': 'd-none cancel-editable',
'text': EALang.cancel
}).get(0).outerHTML,
onblur: 'ignore',
onreset: function () {
if (!enableCancel) {
return false; // disable ESC button
}
},
onsubmit: function () {
if (!enableSubmit) {
return false; // disable Enter button
}
}
}
);
}
function add() {
deferred = jQuery.Deferred();
$date.datepicker('setDate', new Date());
$start.timepicker('setDate', moment('08:00', 'HH:mm').toDate());
$end.timepicker('setDate', moment('20:00', 'HH:mm').toDate());
$modal.modal('show');
return deferred.promise();
}
function edit(date, workingPlanException) {
deferred = jQuery.Deferred();
$date.datepicker('setDate', moment(date, 'YYYY-MM-DD').toDate());
$start.timepicker('setDate', moment(workingPlanException.start, 'HH:mm').toDate());
$end.timepicker('setDate', moment(workingPlanException.end, 'HH:mm').toDate());
workingPlanException.breaks.forEach(function (workingPlanExceptionBreak) {
renderBreakRow(workingPlanExceptionBreak).appendTo($breaks.find('tbody'));
});
editableTimeCell(
$breaks.find('tbody .working-plan-exceptions-break-start, tbody .working-plan-exceptions-break-end')
);
$modal.modal('show');
return deferred.promise();
}
function renderBreakRow(breakPeriod) {
var timeFormat = GlobalVariables.timeFormat === 'regular' ? 'h:mm a' : 'HH:mm';
return $('<tr/>', {
'html': [
$('<td/>', {
'class': 'working-plan-exceptions-break-start editable',
'text': moment(breakPeriod.start, 'HH:mm').format(timeFormat)
}),
$('<td/>', {
'class': 'working-plan-exceptions-break-end editable',
'text': moment(breakPeriod.end, 'HH:mm').format(timeFormat)
}),
$('<td/>', {
'html': [
$('<button/>', {
'type': 'button',
'class': 'btn btn-outline-secondary btn-sm me-2 working-plan-exceptions-edit-break',
'title': EALang.edit,
'html': [
$('<span/>', {
'class': 'fas fa-edit'
})
]
}),
$('<button/>', {
'type': 'button',
'class': 'btn btn-outline-secondary btn-sm working-plan-exceptions-delete-break',
'title': EALang.delete,
'html': [
$('<span/>', {
'class': 'fas fa-trash-alt'
})
]
}),
$('<button/>', {
'type': 'button',
'class': 'btn btn-outline-secondary btn-sm me-2 working-plan-exceptions-save-break d-none',
'title': EALang.save,
'html': [
$('<span/>', {
'class': 'fas fa-check-circle'
})
]
}),
$('<button/>', {
'type': 'button',
'class': 'btn btn-outline-secondary btn-sm working-plan-exceptions-cancel-break d-none',
'title': EALang.cancel,
'html': [
$('<span/>', {
'class': 'fas fa-ban'
})
]
})
]
})
]
});
}
function onAddBreakClick() {
var $newBreak = renderBreakRow({
start: '12:00',
end: '14:00'
}).appendTo('#working-plan-exceptions-breaks tbody');
// Bind editable and event handlers.
editableTimeCell($newBreak.find('.working-plan-exceptions-break-start, .working-plan-exceptions-break-end'));
$newBreak.find('.working-plan-exceptions-edit-break').trigger('click');
$('.working-plan-exceptions-add-break').prop('disabled', true);
}
function onEditBreakClick() {
// Reset previous editable table cells.
var $previousEdits = $(this).closest('table').find('.editable');
$previousEdits.each(function (index, editable) {
if (editable.reset) {
editable.reset();
}
});
// Make all cells in current row editable.
var $tr = $(this).closest('tr');
$tr.children().trigger('edit');
initializeTimepicker(
$tr.find('.working-plan-exceptions-break-start input, .working-plan-exceptions-break-end input')
);
$(this).closest('tr').find('.working-plan-exceptions-break-start').focus();
// Show save - cancel buttons.
$tr = $(this).closest('tr');
$tr.find('.working-plan-exceptions-edit-break, .working-plan-exceptions-delete-break').addClass('d-none');
$tr.find('.working-plan-exceptions-save-break, .working-plan-exceptions-cancel-break').removeClass('d-none');
$tr.find('select,input:text').addClass('form-control input-sm');
$('.working-plan-exceptions-add-break').prop('disabled', true);
}
function onDeleteBreakClick() {
$(this).closest('tr').remove();
}
function onSaveBreakClick() {
// Break's start time must always be prior to break's end.
var $tr = $(this).closest('tr');
var start = moment(
$tr.find('.working-plan-exceptions-break-start input').val(),
GlobalVariables.timeFormat === 'regular' ? 'h:mm a' : 'HH:mm'
);
var end = moment(
$tr.find('.working-plan-exceptions-break-end input').val(),
GlobalVariables.timeFormat === 'regular' ? 'h:mm a' : 'HH:mm'
);
if (start > end) {
$tr.find('.working-plan-exceptions-break-end input').val(
start.add(1, 'hour').format(GlobalVariables.timeFormat === 'regular' ? 'h:mm a' : 'HH:mm')
);
}
enableSubmit = true;
$tr.find('.editable .submit-editable').trigger('click');
enableSubmit = false;
$tr.find('.working-plan-exceptions-save-break, .working-plan-exceptions-cancel-break').addClass('d-none');
$tr.closest('table')
.find('.working-plan-exceptions-edit-break, .working-plan-exceptions-delete-break')
.removeClass('d-none');
$('.working-plan-exceptions-add-break').prop('disabled', false);
}
function onCancelBreakClick() {
var $tr = $(this).closest('tr');
enableCancel = true;
$tr.find('.cancel-editable').trigger('click');
enableCancel = false;
$breaks
.find('.working-plan-exceptions-edit-break, .working-plan-exceptions-delete-break')
.removeClass('d-none');
$tr.find('.working-plan-exceptions-save-break, .working-plan-exceptions-cancel-break').addClass('d-none');
$('.working-plan-exceptions-add-break').prop('disabled', false);
}
function initializeDatepicker($target) {
var dateFormat;
switch (GlobalVariables.dateFormat) {
case 'DMY':
dateFormat = 'dd/mm/yy';
break;
case 'MDY':
dateFormat = 'mm/dd/yy';
break;
case 'YMD':
dateFormat = 'yy/mm/dd';
break;
default:
throw new Error('Invalid date format setting provided: ' + GlobalVariables.dateFormat);
}
$target.datepicker({
dateFormat: dateFormat,
firstDay: GeneralFunctions.getWeekDayId(GlobalVariables.firstWeekday),
minDate: 0,
defaultDate: moment().toDate(),
dayNames: [
EALang.sunday,
EALang.monday,
EALang.tuesday,
EALang.wednesday,
EALang.thursday,
EALang.friday,
EALang.saturday
],
dayNamesShort: [
EALang.sunday.substr(0, 3),
EALang.monday.substr(0, 3),
EALang.tuesday.substr(0, 3),
EALang.wednesday.substr(0, 3),
EALang.thursday.substr(0, 3),
EALang.friday.substr(0, 3),
EALang.saturday.substr(0, 3)
],
dayNamesMin: [
EALang.sunday.substr(0, 2),
EALang.monday.substr(0, 2),
EALang.tuesday.substr(0, 2),
EALang.wednesday.substr(0, 2),
EALang.thursday.substr(0, 2),
EALang.friday.substr(0, 2),
EALang.saturday.substr(0, 2)
],
monthNames: [
EALang.january,
EALang.february,
EALang.march,
EALang.april,
EALang.may,
EALang.june,
EALang.july,
EALang.august,
EALang.september,
EALang.october,
EALang.november,
EALang.december
],
prevText: EALang.previous,
nextText: EALang.next,
currentText: EALang.now,
closeText: EALang.close
});
}
function initializeTimepicker($target) {
$target.timepicker({
timeFormat: GlobalVariables.timeFormat === 'regular' ? 'h:mm tt' : 'HH:mm',
currentText: EALang.now,
closeText: EALang.close,
timeOnlyTitle: EALang.select_time,
timeText: EALang.time,
hourText: EALang.hour,
minuteText: EALang.minutes
});
}
initializeDatepicker($date);
initializeTimepicker($start);
initializeTimepicker($end);
$modal
.on('hidden.bs.modal', onModalHidden)
.on('click', '.working-plan-exceptions-add-break', onAddBreakClick)
.on('click', '.working-plan-exceptions-edit-break', onEditBreakClick)
.on('click', '.working-plan-exceptions-delete-break', onDeleteBreakClick)
.on('click', '.working-plan-exceptions-save-break', onSaveBreakClick)
.on('click', '.working-plan-exceptions-cancel-break', onCancelBreakClick);
$save.on('click', onSaveClick);
window.WorkingPlanExceptionsModal = {
add: add,
edit: edit
};
});