diff --git a/src/application/controllers/backend_api.php b/src/application/controllers/backend_api.php index 4b85f7a7..2b1f4552 100644 --- a/src/application/controllers/backend_api.php +++ b/src/application/controllers/backend_api.php @@ -14,7 +14,6 @@ class Backend_api extends CI_Controller { $this->privileges = $this->roles_model->get_privileges($this->session->userdata('role_slug')); } - /** * [AJAX] Get the registered appointments for the given date period and record. * diff --git a/src/application/controllers/google.php b/src/application/controllers/google.php index 482fafa3..6e6484b8 100644 --- a/src/application/controllers/google.php +++ b/src/application/controllers/google.php @@ -73,12 +73,13 @@ class Google extends CI_Controller { * * @param numeric $provider_id Provider record to be synced. * - * @task This method must be executed only by the system and noone else outside. - * It is a big security issue. So whenever this method is used we should check for - * user credentials. */ public function sync($provider_id = NULL) { try { + // The user must be logged in. + $this->load->library('session'); + if ($this->session->userdata('user_id') == FALSE) return; + if ($provider_id === NULL) { throw new Exception('Provider id not specified.'); } @@ -139,7 +140,7 @@ class Google extends CI_Controller { // Appointment is synced with google calendar. try { $google_event = $this->google_sync->get_event($appointment['id_google_calendar']); - + // If gcal event is different from e!a appointment then update e!a record. $is_different = FALSE; $appt_start = strtotime($appointment['start_datetime']); @@ -156,6 +157,7 @@ class Google extends CI_Controller { $appointment['end_datetime'] = date('Y-m-d H:i:s', $event_end); $this->appointments_model->add($appointment); } + } catch(Exception $exc) { // Appointment not found on gcal, delete from e!a. $this->appointments_model->delete($appointment['id']); diff --git a/src/application/helpers/general_helper.php b/src/application/helpers/general_helper.php index 9f665c8d..7ccd941b 100644 --- a/src/application/helpers/general_helper.php +++ b/src/application/helpers/general_helper.php @@ -44,7 +44,7 @@ function hash_password($salt, $password) { $hash = hash('sha256', $hash); } - return $hash; // @task include salt and hash more times. + return $hash; } /** diff --git a/src/application/libraries/Unit_tests/Unit_tests.php b/src/application/libraries/Unit_tests/Unit_tests.php index 43c1e74e..449b0ab9 100644 --- a/src/application/libraries/Unit_tests/Unit_tests.php +++ b/src/application/libraries/Unit_tests/Unit_tests.php @@ -35,8 +35,6 @@ class Unit_tests extends CI_Driver_Library { * If a new group of tests is added, it should be also added in * this method, in order to be executed when all the tests need to * be run. - * - * @task In order to run the tests the user must be logged in as admin. */ public function run_all_tests() { $this->run_model_tests(false); @@ -74,7 +72,7 @@ class Unit_tests extends CI_Driver_Library { * report will be outputted. */ public function run_library_tests($output_report = true) { - // @task Implement unit tests for the libraries. + // No tests for libraries at the moment. if ($output_report) { $this->CI->output->append_output($this->CI->unit->report()); } diff --git a/src/assets/css/backend.css b/src/assets/css/backend.css index 9963aad8..432d977a 100644 --- a/src/assets/css/backend.css +++ b/src/assets/css/backend.css @@ -134,43 +134,6 @@ body .jspTrack { background: #EBEBEB; } -body .ui-dialog .ui-dialog-titlebar-close { - display: none; -} - -body .ui-draggable .ui-dialog-titlebar { - background: #3DD481; - color: #FFF; - text-shadow: 1px 1px 0px #327451; - padding: 14px 10px; - border-bottom: 4px solid #1A865F; - margin-bottom: 10px; -} - -body .ui-dialog { - padding: 0; -} - -body .ui-dialog .ui-dialog-buttonpane { - padding: .3em 1em .3em .4em; -} - -.breaks tr:hover td { - background: #FFFFC2 !important; -} - -.working-plan td { - vertical-align: middle; -} - -.breaks td { - vertical-align: middle; -} - -body .ui-icon, .ui-widget-content .ui-icon { - background-image: url(libs/jquery/images/ui-icons_52b799_256x240.png); -} - /* BACKEND CALENDAR PAGE -------------------------------------------------------------------- */ #calendar-page #calendar-toolbar { diff --git a/src/assets/css/general.css b/src/assets/css/general.css index 3abb2673..d9f3ee10 100644 --- a/src/assets/css/general.css +++ b/src/assets/css/general.css @@ -7,6 +7,43 @@ body .custom-qtip { border-radius: 6px; } +body .ui-dialog .ui-dialog-titlebar-close { + display: none; +} + +body .ui-draggable .ui-dialog-titlebar { + background: #3DD481; + color: #FFF; + text-shadow: 1px 1px 0px #327451; + padding: 14px 10px; + border-bottom: 4px solid #1A865F; + margin-bottom: 10px; +} + +body .ui-dialog { + padding: 0; +} + +body .ui-dialog .ui-dialog-buttonpane { + padding: .3em 1em .3em .4em; +} + +.breaks tr:hover td { + background: #FFFFC2 !important; +} + +.working-plan td { + vertical-align: middle; +} + +.breaks td { + vertical-align: middle; +} + +body .ui-icon, .ui-widget-content .ui-icon { + background-image: url(libs/jquery/images/ui-icons_52b799_256x240.png); +} + /* JQUERY UI DATETIME PICKER ADDON ------------------------------------------------------------------------- */ .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; } diff --git a/src/assets/js/backend_calendar.js b/src/assets/js/backend_calendar.js index 6d6ad5f1..a171c5dc 100644 --- a/src/assets/js/backend_calendar.js +++ b/src/assets/js/backend_calendar.js @@ -97,7 +97,8 @@ var BackendCalendar = { // Privileges Checks if (GlobalVariables.user.role_slug == Backend.DB_SLUG_PROVIDER) { - $('#select-filter-item optgroup:eq(0)').val(GlobalVariables.user.id); + $('#select-filter-item optgroup:eq(0)') + .find('option[value="' + GlobalVariables.user.id + '"]').prop('selected', true); $('#select-filter-item').prop('disabled', true); } @@ -844,10 +845,8 @@ var BackendCalendar = { * @param {date} startDate Visible start date of the calendar. * @param {type} endDate Visible end date of the calendar. */ - refreshCalendarAppointments: function($calendar, recordId, filterType, - startDate, endDate) { + refreshCalendarAppointments: function($calendar, recordId, filterType, startDate, endDate) { var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_get_calendar_appointments'; - var postData = { 'record_id': recordId, 'start_date': startDate.toString('yyyy-MM-dd'), @@ -857,21 +856,10 @@ var BackendCalendar = { $.post(postUrl, postData, function(response) { //////////////////////////////////////////////////////////////////// - //console.log('Refresh Calendar Appointments Response :', response); + console.log('Refresh Calendar Appointments Response :', response); //////////////////////////////////////////////////////////////////// - if (response.exceptions) { - response.exceptions = GeneralFunctions.parseExceptions(response.exceptions); - GeneralFunctions.displayMessageBox(GeneralFunctions.EXCEPTIONS_TITLE, GeneralFunctions.EXCEPTIONS_MESSAGE); - $('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions)); - return; - } - - if (response.warnings) { - response.warnings = GeneralFunctions.parseExceptions(response.exceptions); - GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE); - $('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings)); - } + if (!GeneralFunctions.handleAjaxExceptions(response)) return; // :: ADD APPOINTMENTS TO CALENDAR var calendarEvents = []; @@ -898,12 +886,10 @@ var BackendCalendar = { // :: ADD PROVIDER'S UNAVAILABLE TIME PERIODS var calendarView = $calendar.fullCalendar('getView').name; - if (filterType === BackendCalendar.FILTER_TYPE_PROVIDER - && calendarView !== 'month') { - + if (filterType === BackendCalendar.FILTER_TYPE_PROVIDER && calendarView !== 'month') { $.each(GlobalVariables.availableProviders, function(index, provider) { if (provider['id'] == recordId) { - var workingPlan = jQuery.parseJSON(provider['settings']['working_plan']); + var workingPlan = jQuery.parseJSON(provider.settings.working_plan); var unavailablePeriod; switch(calendarView) { @@ -993,7 +979,44 @@ var BackendCalendar = { var currDateEnd = GeneralFunctions.clone(currDateStart).addDays(1); $.each(workingPlan, function(index, workingDay) { - if (workingDay == null) return; // Go to the next loop. + + // Add custom unavailable periods (they are always displayed + // on the calendar, even if the provider won't work on that day). + $.each(response.unavailables, function(index, unavailable) { + if (currDateStart.toString('dd/MM/yyyy') + === Date.parse(unavailable.start_datetime).toString('dd/MM/yyyy')) { + var unavailablePeriod = { + 'title': 'Unavailable', + 'start': Date.parse(unavailable.start_datetime), + 'end': Date.parse(unavailable.end_datetime), + 'allDay': false, + 'color': '#879DB4', + 'editable': true, + 'className': 'fc-unavailable fc-custom', + 'data': unavailable + }; + $calendar.fullCalendar('renderEvent', unavailablePeriod, false); + } + }); + + + if (workingDay == null) { + // Add a full day unavailable event. + unavailablePeriod = { + 'title': 'Not Working', + 'start': GeneralFunctions.clone(currDateStart), + 'end': GeneralFunctions.clone(currDateEnd), + 'allDay': false, + 'color': '#BEBEBE', + 'editable': false, + 'className': 'fc-unavailable' + }; + $calendar.fullCalendar('renderEvent', unavailablePeriod, true); + currDateStart.addDays(1); + currDateEnd.addDays(1); + return; // Go to the next loop. + } + var start, end; // Add unavailable period before work starts. @@ -1009,8 +1032,7 @@ var BackendCalendar = { 'editable': false, 'className': 'fc-unavailable' }; - $calendar.fullCalendar('renderEvent', unavailablePeriod, - true); + $calendar.fullCalendar('renderEvent', unavailablePeriod, true); } // Add unavailable period after work ends. @@ -1048,24 +1070,6 @@ var BackendCalendar = { $calendar.fullCalendar('renderEvent', unavailablePeriod, false); }); - // Add custom unavailable periods. - $.each(response.unavailables, function(index, unavailable) { - if (currDateStart.toString('dd/MM/yyyy') - === Date.parse(unavailable.start_datetime).toString('dd/MM/yyyy')) { - var unavailablePeriod = { - 'title': 'Unavailable', - 'start': Date.parse(unavailable.start_datetime), - 'end': Date.parse(unavailable.end_datetime), - 'allDay': false, - 'color': '#879DB4', - 'editable': true, - 'className': 'fc-unavailable fc-custom', - 'data': unavailable - }; - $calendar.fullCalendar('renderEvent', unavailablePeriod, false); - } - }); - currDateStart.addDays(1); currDateEnd.addDays(1); }); diff --git a/src/assets/js/backend_customers.js b/src/assets/js/backend_customers.js index f7b82599..7a4d15d5 100644 --- a/src/assets/js/backend_customers.js +++ b/src/assets/js/backend_customers.js @@ -416,9 +416,6 @@ CustomersHelper.prototype.getFilterHtml = function(customer) { * @param {numeric} id The record id to be selected from the filter results. * @param {bool} display (OPTIONAL = false) If true then the method will display the record * on the form. - * - * @task The selected row must always be visible (even if a vertical scroll bar is used to - * navigate through the filter results). */ CustomersHelper.prototype.select = function(id, display) { if (display == undefined) display = false; diff --git a/src/assets/js/backend_services.js b/src/assets/js/backend_services.js index 48b5235a..ca20b718 100644 --- a/src/assets/js/backend_services.js +++ b/src/assets/js/backend_services.js @@ -426,9 +426,6 @@ ServicesHelper.prototype.getFilterHtml = function(service) { * @param {numeric} id The record id to be selected from the filter results. * @param {bool} display (OPTIONAL = false) If true then the method will display the record * on the form. - * - * @task The selected row must always be visible (even if a vertical scroll bar is used to - * navigate through the filter results). */ ServicesHelper.prototype.select = function(id, display) { if (display == undefined) display = false; @@ -749,9 +746,6 @@ CategoriesHelper.prototype.getFilterHtml = function(category) { * @param {numeric} id The record id to be selected from the filter results. * @param {bool} display (OPTIONAL = false) If true then the method will display the record * on the form. - * - * @task The selected row must always be visible (even if a vertical scroll bar is used to - * navigate through the filter results). */ CategoriesHelper.prototype.select = function(id, display) { if (display == undefined) display = false; diff --git a/src/assets/js/backend_users_admins.js b/src/assets/js/backend_users_admins.js index 83ee3259..69c1468d 100644 --- a/src/assets/js/backend_users_admins.js +++ b/src/assets/js/backend_users_admins.js @@ -365,9 +365,6 @@ AdminsHelper.prototype.getFilterHtml = function(admin) { * @param {numeric} id The record id to be selected from the filter results. * @param {bool} display (OPTIONAL = false) If true then the method will display the record * on the form. - * - * @task The selected row must always be visible (even if a vertical scroll bar is used to - * navigate through the filter results). */ AdminsHelper.prototype.select = function(id, display) { if (display == undefined) display = false; diff --git a/src/assets/js/backend_users_secretaries.js b/src/assets/js/backend_users_secretaries.js index 5494ebdf..4ecb9655 100644 --- a/src/assets/js/backend_users_secretaries.js +++ b/src/assets/js/backend_users_secretaries.js @@ -386,9 +386,6 @@ SecretariesHelper.prototype.getFilterHtml = function(secretary) { * @param {numeric} id The record id to be selected from the filter results. * @param {bool} display (OPTIONAL = false) If true then the method will display the record * on the form. - * - * @task The selected row must always be visible (even if a vertical scroll bar is used to - * navigate through the filter results). */ SecretariesHelper.prototype.select = function(id, display) { if (display == undefined) display = false; diff --git a/src/assets/js/frontend_book.js b/src/assets/js/frontend_book.js index a32e17f7..b079fd3b 100644 --- a/src/assets/js/frontend_book.js +++ b/src/assets/js/frontend_book.js @@ -550,10 +550,10 @@ var FrontendBook = { $.each(GlobalVariables.availableServices, function(index, service) { if (service.id == serviceId) { // Just found the service. - html = '' + service.name + '
'; + html = '' + service.name + ''; if (service.description != '' && service.description != null) { - html += service.description; + html += '
' + service.description; } if (service.price != '' && service.price != null) {