/* ---------------------------------------------------------------------------- * Easy!Appointments - Open Source Web Scheduler * * @package EasyAppointments * @author A.Tselegidis * @copyright Copyright (c) 2013 - 2016, Alex Tselegidis * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 * @link http://easyappointments.org * @since v1.2.0 * ---------------------------------------------------------------------------- */ window.BackendCalendarTableView = window.BackendCalendarTableView || {}; /** * Backend Calendar * * This module implements the table calendar view of backend. * * @module BackendCalendarTableView */ (function (exports) { 'use strict'; var $filterProvider; var $filterService; var lastFocusedEventData; /** * Bind page event handlers. */ function bindEventHandlers() { var $calendarToolbar = $('#calendar-toolbar'); var $calendar = $('#calendar'); $calendar.on('click', '.calendar-header .btn.previous', function () { var dayInterval = $('#select-filter-item').val(); var currentDate = $('.select-date').datepicker('getDate'); var startDate = moment(currentDate).subtract(1, 'days'); var endDate = startDate.clone().add(dayInterval - 1, 'days'); $('.select-date').datepicker('setDate', startDate.toDate()); createView(startDate.toDate(), endDate.toDate()); }); $calendar.on('click', '.calendar-header .btn.next', function () { var dayInterval = $('#select-filter-item').val(); var currentDate = $('.select-date').datepicker('getDate'); var startDate = moment(currentDate).add(1, 'days'); var endDate = startDate.clone().add(dayInterval - 1, 'days'); $('.select-date').datepicker('setDate', startDate.toDate()); createView(startDate.toDate(), endDate.toDate()); }); $calendarToolbar.on('change', '#select-filter-item', function () { var dayInterval = $('#select-filter-item').val(); var currentDate = $('.select-date').datepicker('getDate'); var startDate = moment(currentDate); var endDate = startDate.clone().add(dayInterval - 1, 'days'); createView(startDate.toDate(), endDate.toDate()); }); $calendarToolbar.on('click', '#reload-appointments', function () { // Remove all the events from the tables. $('.calendar-view .event').remove(); // Fetch the events and place them in the existing HTML format. var dayInterval = $('#select-filter-item').val(); var currentDate = $('.select-date').datepicker('getDate'); var startDateMoment = moment(currentDate); var startDate = startDateMoment.toDate(); var endDateMoment = startDateMoment.clone().add(dayInterval - 1, 'days'); var endDate = endDateMoment.toDate(); getCalendarEvents(startDate, endDate) .done(function (response) { var currentDate = startDate; while (currentDate <= endDate) { $('.calendar-view .date-column').each(function (index, dateColumn) { var $dateColumn = $(dateColumn); var date = new Date($dateColumn.data('date')); if (currentDate.getTime() !== date.getTime()) { return true; } $dateColumn.find('.date-column-title').text(GeneralFunctions.formatDate(date, GlobalVariables.dateFormat)); $dateColumn.find('.provider-column').each(function (index, providerColumn) { var $providerColumn = $(providerColumn); var provider = $providerColumn.data('provider'); $providerColumn.find('.calendar-wrapper').fullCalendar('removeEvents'); createNonWorkingHours($providerColumn.find('.calendar-wrapper'), JSON.parse($providerColumn.data('provider').settings.working_plan)); // Add the appointments to the column. createAppointments($providerColumn, response.appointments); // Add the unavailabilities to the column. createUnavailabilities($providerColumn, response.unavailabilities); // Add the provider breaks to the column. var workingPlan = JSON.parse(provider.settings.working_plan); var day = date.toString('dddd').toLowerCase(); if (workingPlan[day]) { var breaks = workingPlan[day].breaks; createBreaks($providerColumn, breaks); } }); }); currentDate.add({days: 1}); } // setCalendarViewSize(); Backend.placeFooterToBottom(); }) .fail(GeneralFunctions.ajaxFailureHandler); }); /** * Event: On Window Resize */ $(window).on('resize', function () { setCalendarViewSize(); }); /** * Event: Popover Close Button "Click" * * Hides the open popover element. */ $calendar.on('click', '.close-popover', function () { $(this).parents().eq(2).popover('destroy'); }); /** * Event: Popover Edit Button "Click" * * Enables the edit dialog of the selected table event. */ $calendar.on('click', '.edit-popover', function () { $(this).parents().eq(2).remove(); // Hide the popover var $dialog; if (lastFocusedEventData.data.is_unavailable == false) { var appointment = lastFocusedEventData.data; $dialog = $('#manage-appointment'); BackendCalendarAppointmentsModal.resetAppointmentDialog(); // Apply appointment data and show modal dialog. $dialog.find('.modal-header h3').text(EALang.edit_appointment_title); $dialog.find('#appointment-id').val(appointment.id); $dialog.find('#select-service').val(appointment.id_services).trigger('change'); $dialog.find('#select-provider').val(appointment.id_users_provider); // Set the start and end datetime of the appointment. var startDatetime = Date.parseExact(appointment.start_datetime, 'yyyy-MM-dd HH:mm:ss'); $dialog.find('#start-datetime').datetimepicker('setDate', startDatetime); var endDatetime = Date.parseExact(appointment.end_datetime, 'yyyy-MM-dd HH:mm:ss'); $dialog.find('#end-datetime').datetimepicker('setDate', endDatetime); var customer = appointment.customer; $dialog.find('#customer-id').val(appointment.id_users_customer); $dialog.find('#first-name').val(customer.first_name); $dialog.find('#last-name').val(customer.last_name); $dialog.find('#email').val(customer.email); $dialog.find('#phone-number').val(customer.phone_number); $dialog.find('#address').val(customer.address); $dialog.find('#city').val(customer.city); $dialog.find('#zip-code').val(customer.zip_code); $dialog.find('#appointment-location').val(appointment.location); $dialog.find('#appointment-notes').val(appointment.notes); $dialog.find('#customer-notes').val(customer.notes); } else { var unavailable = lastFocusedEventData.data; // Replace string date values with actual date objects. unavailable.start_datetime = lastFocusedEventData.start.format('YYYY-MM-DD HH:mm:ss'); var startDatetime = Date.parseExact(unavailable.start_datetime, 'yyyy-MM-dd HH:mm:ss'); unavailable.end_datetime = lastFocusedEventData.end.format('YYYY-MM-DD HH:mm:ss'); var endDatetime = Date.parseExact(unavailable.end_datetime, 'yyyy-MM-dd HH:mm:ss'); $dialog = $('#manage-unavailable'); BackendCalendarUnavailabilitiesModal.resetUnavailableDialog(); // Apply unavailable data to dialog. $dialog.find('.modal-header h3').text('Edit Unavailable Period'); $dialog.find('#unavailable-start').datetimepicker('setDate', startDatetime); $dialog.find('#unavailable-id').val(unavailable.id); $dialog.find('#unavailable-provider').val(unavailable.id_users_provider); $dialog.find('#unavailable-end').datetimepicker('setDate', endDatetime); $dialog.find('#unavailable-notes').val(unavailable.notes); } // :: DISPLAY EDIT DIALOG $dialog.modal('show'); }); /** * Event: Popover Delete Button "Click" * * Displays a prompt on whether the user wants the appointment to be deleted. If he confirms the * deletion then an ajax call is made to the server and deletes the appointment from the database. */ $calendar.on('click', '.delete-popover', function () { $(this).parents().eq(2).remove(); // Hide the popover. // If id_role parameter exists the popover is an extra working day. if (lastFocusedEventData.data.hasOwnProperty('id_roles')) { // Do not display confirmation prompt. var url = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_delete_extra_period'; var data = { csrfToken: GlobalVariables.csrfToken, extra_period: lastFocusedEventData.start.format('YYYY-MM-DD'), provider_id: lastFocusedEventData.data.id }; $.post(url, data, function (response) { $('#message_box').dialog('close'); var extraWorkingPlan = jQuery.parseJSON(lastFocusedEventData.data.settings.extra_working_plan); delete extraWorkingPlan[lastFocusedEventData.start.format('YYYY-MM-DD')]; lastFocusedEventData.data.settings.extra_working_plan = JSON.stringify(extraWorkingPlan); // Refresh calendar event items. $('#select-filter-item').trigger('change'); }, 'json').fail(GeneralFunctions.ajaxFailureHandler); } else if (lastFocusedEventData.data.is_unavailable == false) { var buttons = [ { text: 'OK', click: function () { var url = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_delete_appointment'; var data = { csrfToken: GlobalVariables.csrfToken, appointment_id: lastFocusedEventData.data.id, delete_reason: $('#delete-reason').val() }; $.post(url, data, function (response) { $('#message_box').dialog('close'); // Refresh calendar event items. $('#select-filter-item').trigger('change'); }, 'json').fail(GeneralFunctions.ajaxFailureHandler); } }, { text: EALang.cancel, click: function () { $('#message_box').dialog('close'); } } ]; GeneralFunctions.displayMessageBox(EALang.delete_appointment_title, EALang.write_appointment_removal_reason, buttons); $('#message_box').append(''); $('#delete-reason').css('width', '100%'); } else { // Do not display confirmation prompt. var url = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_delete_unavailable'; var data = { csrfToken: GlobalVariables.csrfToken, unavailable_id: lastFocusedEventData.data.id }; $.post(url, data, function (response) { $('#message_box').dialog('close'); // Refresh calendar event items. $('#select-filter-item').trigger('change'); }, 'json').fail(GeneralFunctions.ajaxFailureHandler); } }); } /** * Create table view header container. * * The header contains the date navigation elements (buttons and datepicker). */ function createHeader() { var $calendarFilter = $('#calendar-filter'); $calendarFilter .find('select') .empty() .append(new Option('1 ' + EALang.day, 1)) .append(new Option('3 ' + EALang.days, 3)); var $calendarHeader = $('
').appendTo('#calendar'); $calendarHeader .html( '' + '' + '' ); 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); } $calendarHeader.find('.select-date').datepicker({ defaultDate: new Date(), dateFormat: dateFormat, onSelect: function (dateText, instance) { var startDate = new Date(instance.currentYear, instance.currentMonth, instance.currentDay); var endDate = new Date(startDate.getTime()).add({days: parseInt($('#select-filter-item').val()) - 1}); createView(startDate, endDate); } }); var providers = GlobalVariables.availableProviders.filter(function (provider) { return GlobalVariables.user.role_slug === Backend.DB_SLUG_ADMIN || (GlobalVariables.user.role_slug === Backend.DB_SLUG_SECRETARY && GlobalVariables.secretaryProviders.indexOf(provider.id) !== -1) || (GlobalVariables.user.role_slug === Backend.DB_SLUG_PROVIDER && Number(provider.id) === Number(GlobalVariables.user.id)); }); // Create providers and service filters. if (GlobalVariables.user.role_slug !== Backend.DB_SLUG_PROVIDER) { $('