* Finished with unavailable time periods management (backend).
* Started google sync operation (complete sync). * Minor changes on js files.
This commit is contained in:
parent
f5250e5581
commit
8455891262
15 changed files with 818 additions and 324 deletions
|
@ -30,29 +30,25 @@ class Appointments extends CI_Controller {
|
|||
// Load the appointments data and enable the manage mode of the page.
|
||||
$manage_mode = TRUE;
|
||||
|
||||
$appointments_results = $this->appointments_model
|
||||
->get_batch(array('hash' => $appointment_hash));
|
||||
$results = $this->appointments_model->get_batch(array('hash' => $appointment_hash));
|
||||
|
||||
if (count($appointments_results) === 0) {
|
||||
if (count($results) === 0) {
|
||||
// The requested appointment doesn't exist in the database. Display
|
||||
// a message to the customer.
|
||||
$view_data = array(
|
||||
$view = array(
|
||||
'message_title' => 'Appointment Not Found!',
|
||||
'message_text' => 'The appointment you requested does not exist in '
|
||||
. 'the system database anymore.',
|
||||
'message_icon' => $this->config->item('base_url')
|
||||
. 'assets/images/error.png'
|
||||
);
|
||||
$this->load->view('appointments/message', $view_data);
|
||||
$this->load->view('appointments/message', $view);
|
||||
return;
|
||||
}
|
||||
|
||||
$appointment = $appointments_results[0];
|
||||
|
||||
$provider = $this->providers_model
|
||||
->get_row($appointment['id_users_provider']);
|
||||
$customer = $this->customers_model
|
||||
->get_row($appointment['id_users_customer']);
|
||||
$appointment = $results[0];
|
||||
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
|
||||
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||
|
||||
} else {
|
||||
// The customer is going to book a new appointment so there is no
|
||||
|
@ -64,7 +60,7 @@ class Appointments extends CI_Controller {
|
|||
}
|
||||
|
||||
// Load the book appointment view.
|
||||
$view_data = array (
|
||||
$view = array (
|
||||
'available_services' => $available_services,
|
||||
'available_providers' => $available_providers,
|
||||
'company_name' => $company_name,
|
||||
|
@ -75,10 +71,10 @@ class Appointments extends CI_Controller {
|
|||
);
|
||||
|
||||
} catch(Exception $exc) {
|
||||
$view_data['exceptions'][] = $exc;
|
||||
$view['exceptions'][] = $exc;
|
||||
}
|
||||
|
||||
$this->load->view('appointments/book', $view_data);
|
||||
$this->load->view('appointments/book', $view);
|
||||
|
||||
} else {
|
||||
// The page is a post-back. Register the appointment and send notification emails
|
||||
|
@ -135,7 +131,7 @@ class Appointments extends CI_Controller {
|
|||
}
|
||||
}
|
||||
} catch(Exception $exc) {
|
||||
$view_data['exceptions'][] = $exc;
|
||||
$view['exceptions'][] = $exc;
|
||||
}
|
||||
|
||||
// :: SEND NOTIFICATION EMAILS TO BOTH CUSTOMER AND PROVIDER
|
||||
|
@ -175,11 +171,11 @@ class Appointments extends CI_Controller {
|
|||
$service, $customer, $company_settings, $provider_title,
|
||||
$provider_message, $provider_link, $provider['email']);
|
||||
} catch(Exception $exc) {
|
||||
$view_data['exceptions'][] = $exc;
|
||||
$view['exceptions'][] = $exc;
|
||||
}
|
||||
|
||||
// :: LOAD THE BOOK SUCCESS VIEW
|
||||
$view_data = array(
|
||||
$view = array(
|
||||
'appointment_data' => $appointment,
|
||||
'provider_data' => $provider,
|
||||
'service_data' => $service,
|
||||
|
@ -187,10 +183,10 @@ class Appointments extends CI_Controller {
|
|||
);
|
||||
|
||||
} catch(Exception $exc) {
|
||||
$view_data['exceptions'][] = $exc;
|
||||
$view['exceptions'][] = $exc;
|
||||
}
|
||||
|
||||
$this->load->view('appointments/book_success', $view_data);
|
||||
$this->load->view('appointments/book_success', $view);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,10 +269,10 @@ class Appointments extends CI_Controller {
|
|||
}
|
||||
|
||||
if (isset($exceptions)) {
|
||||
$view_data['exceptions'] = $exceptions;
|
||||
$view['exceptions'] = $exceptions;
|
||||
}
|
||||
|
||||
$this->load->view('appointments/cancel', $view_data);
|
||||
$this->load->view('appointments/cancel', $view);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -451,12 +447,12 @@ class Appointments extends CI_Controller {
|
|||
$this->load->model('providers_model');
|
||||
|
||||
// Get the provider's working plan and reserved appointments.
|
||||
$working_plan = json_decode($this->providers_model
|
||||
->get_setting('working_plan', $provider_id), true);
|
||||
$working_plan = json_decode($this->providers_model->get_setting('working_plan',
|
||||
$provider_id), true);
|
||||
|
||||
$where_clause = array(
|
||||
'DATE(start_datetime)' => date('Y-m-d', strtotime($selected_date)),
|
||||
'id_users_provider' => $provider_id
|
||||
'DATE(start_datetime)' => date('Y-m-d', strtotime($selected_date)),
|
||||
'id_users_provider' => $provider_id
|
||||
);
|
||||
|
||||
$reserved_appointments = $this->appointments_model->get_batch($where_clause);
|
||||
|
@ -474,8 +470,7 @@ class Appointments extends CI_Controller {
|
|||
// Find the empty spaces on the plan. The first split between the plan is due to
|
||||
// a break (if exist). After that every reserved appointment is considered to be
|
||||
// a taken space in the plan.
|
||||
$selected_date_working_plan = $working_plan[strtolower(date('l',
|
||||
strtotime($selected_date)))];
|
||||
$selected_date_working_plan = $working_plan[strtolower(date('l', strtotime($selected_date)))];
|
||||
$available_periods_with_breaks = array();
|
||||
|
||||
if (isset($selected_date_working_plan['breaks'])) {
|
||||
|
@ -486,22 +481,22 @@ class Appointments extends CI_Controller {
|
|||
|
||||
if (count($available_periods_with_breaks) === 0) {
|
||||
$start_hour = $selected_date_working_plan['start'];
|
||||
$end_hour = $break['start'];
|
||||
$end_hour = $break['start'];
|
||||
} else {
|
||||
$start_hour = $selected_date_working_plan['breaks'][$last_break_index]['end'];
|
||||
$end_hour = $break['start'];
|
||||
$end_hour = $break['start'];
|
||||
}
|
||||
|
||||
$available_periods_with_breaks[] = array(
|
||||
'start' => $start_hour,
|
||||
'end' => $end_hour
|
||||
'end' => $end_hour
|
||||
);
|
||||
}
|
||||
|
||||
// Add the period from the last break to the end of the day.
|
||||
$available_periods_with_breaks[] = array(
|
||||
'start' => $selected_date_working_plan['breaks'][$index]['end'],
|
||||
'end' => $selected_date_working_plan['end']
|
||||
'end' => $selected_date_working_plan['end']
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -512,19 +507,19 @@ class Appointments extends CI_Controller {
|
|||
|
||||
foreach($available_periods_with_breaks as $period) {
|
||||
|
||||
foreach($reserved_appointments as $index=>$excluded_appointment) {
|
||||
$appointment_start = date('H:i', strtotime($excluded_appointment['start_datetime']));
|
||||
$appointment_end = date('H:i', strtotime($excluded_appointment['end_datetime']));
|
||||
$period_start = date('H:i', strtotime($period['start']));
|
||||
$period_end = date('H:i', strtotime($period['end']));
|
||||
foreach($reserved_appointments as $index=>$appointment) {
|
||||
$appointment_start = date('H:i', strtotime($appointment['start_datetime']));
|
||||
$appointment_end = date('H:i', strtotime($appointment['end_datetime']));
|
||||
$period_start = date('H:i', strtotime($period['start']));
|
||||
$period_end = date('H:i', strtotime($period['end']));
|
||||
|
||||
if ($period_start < $appointment_start && $period_end > $appointment_end) {
|
||||
if ($period_start <= $appointment_start && $period_end >= $appointment_end) {
|
||||
// We need to check whether another appointment fits in the current
|
||||
// time period. If this happens, then we need to consider the whole
|
||||
// appointment time as one, because the provider will not be available.
|
||||
foreach ($reserved_appointments as $tmp_appointment) {
|
||||
$appt_start = date('H:i', strtotime($tmp_appointment['start_datetime']));
|
||||
$appt_end = date('H:i', strtotime($tmp_appointment['end_datetime']));
|
||||
$appt_start = date('H:i', strtotime($tmp_appointment['start_datetime']));
|
||||
$appt_end = date('H:i', strtotime($tmp_appointment['end_datetime']));
|
||||
|
||||
if ($period_start < $appt_start && $period_end > $appt_end) {
|
||||
if ($appointment_start > $appt_start) {
|
||||
|
|
|
@ -8,23 +8,34 @@ class Backend extends CI_Controller {
|
|||
* view this page which displays a calendar with the events of the selected
|
||||
* provider or service. If a user has more priviledges he will see more menus
|
||||
* at the top of the page.
|
||||
*
|
||||
* @param string $appointment_hash If given, the appointment edit dialog will
|
||||
* appear when the page loads.
|
||||
*/
|
||||
public function index() {
|
||||
public function index($appointment_hash = '') {
|
||||
// @task Require user to be logged in the application.
|
||||
|
||||
$this->load->model('appointments_model');
|
||||
$this->load->model('providers_model');
|
||||
$this->load->model('services_model');
|
||||
$this->load->model('settings_model');
|
||||
|
||||
$view_data['base_url'] = $this->config->item('base_url');
|
||||
$view_data['book_advance_timeout'] = $this->settings_model->get_setting('book_advance_timeout');
|
||||
$view_data['company_name'] = $this->settings_model->get_setting('company_name');
|
||||
$view_data['available_providers'] = $this->providers_model->get_available_providers();
|
||||
$view_data['available_services'] = $this->services_model->get_available_services();
|
||||
$view['base_url'] = $this->config->item('base_url');
|
||||
$view['book_advance_timeout'] = $this->settings_model->get_setting('book_advance_timeout');
|
||||
$view['company_name'] = $this->settings_model->get_setting('company_name');
|
||||
$view['available_providers'] = $this->providers_model->get_available_providers();
|
||||
$view['available_services'] = $this->services_model->get_available_services();
|
||||
|
||||
$this->load->view('backend/header', $view_data);
|
||||
$this->load->view('backend/calendar', $view_data);
|
||||
$this->load->view('backend/footer', $view_data);
|
||||
if ($appointment_hash != '') {
|
||||
$results = $this->appointments_model->get_batch(array('hash' => $appointment_hash));
|
||||
$view['edit_appointment'] = $results[0]; // This will display the appointment edit dialog on page load.
|
||||
} else {
|
||||
$view['edit_appointment'] = NULL;
|
||||
}
|
||||
|
||||
$this->load->view('backend/header', $view);
|
||||
$this->load->view('backend/calendar', $view);
|
||||
$this->load->view('backend/footer', $view);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,15 +51,15 @@ class Backend extends CI_Controller {
|
|||
$this->load->model('services_model');
|
||||
$this->load->model('settings_model');
|
||||
|
||||
$view_data['base_url'] = $this->config->item('base_url');
|
||||
$view_data['company_name'] = $this->settings_model->get_setting('company_name');
|
||||
$view_data['customers'] = $this->customers_model->get_batch();
|
||||
$view_data['available_providers'] = $this->providers_model->get_available_providers();
|
||||
$view_data['available_services'] = $this->services_model->get_available_services();
|
||||
$view['base_url'] = $this->config->item('base_url');
|
||||
$view['company_name'] = $this->settings_model->get_setting('company_name');
|
||||
$view['customers'] = $this->customers_model->get_batch();
|
||||
$view['available_providers'] = $this->providers_model->get_available_providers();
|
||||
$view['available_services'] = $this->services_model->get_available_services();
|
||||
|
||||
$this->load->view('backend/header', $view_data);
|
||||
$this->load->view('backend/customers', $view_data);
|
||||
$this->load->view('backend/footer', $view_data);
|
||||
$this->load->view('backend/header', $view);
|
||||
$this->load->view('backend/customers', $view);
|
||||
$this->load->view('backend/footer', $view);
|
||||
}
|
||||
|
||||
public function services() {
|
||||
|
|
|
@ -7,12 +7,11 @@ class Backend_api extends CI_Controller {
|
|||
/**
|
||||
* [AJAX] Get the registered appointments for the given date period and record.
|
||||
*
|
||||
* This method returns the database appointments for the user selected date
|
||||
* period and record type (provider or service).
|
||||
* This method returns the database appointments and unavailable periods for the
|
||||
* user selected date period and record type (provider or service).
|
||||
*
|
||||
* @param {numeric} $_POST['record_id'] Selected record id.
|
||||
* @param {string} $_POST['filter_type'] Could be either FILTER_TYPE_PROVIDER
|
||||
* or FILTER_TYPE_SERVICE.
|
||||
* @param {string} $_POST['filter_type'] Could be either FILTER_TYPE_PROVIDER or FILTER_TYPE_SERVICE.
|
||||
* @param {string} $_POST['start_date'] The user selected start date.
|
||||
* @param {string} $_POST['end_date'] The user selected end date.
|
||||
*/
|
||||
|
@ -29,23 +28,35 @@ class Backend_api extends CI_Controller {
|
|||
$where_id = 'id_services';
|
||||
}
|
||||
|
||||
// Get appointments
|
||||
$where_clause = array(
|
||||
$where_id => $_POST['record_id'],
|
||||
'start_datetime >=' => $_POST['start_date'],
|
||||
'end_datetime <=' => $_POST['end_date']
|
||||
'end_datetime <=' => $_POST['end_date'],
|
||||
'is_unavailable' => FALSE
|
||||
);
|
||||
|
||||
$response['appointments'] = $this->appointments_model->get_batch($where_clause);
|
||||
|
||||
$appointments = $this->appointments_model->get_batch($where_clause);
|
||||
|
||||
foreach($appointments as &$appointment) {
|
||||
if ($appointment['is_unavailable'] == FALSE) {
|
||||
$appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']);
|
||||
$appointment['service'] = $this->services_model->get_row($appointment['id_services']);
|
||||
$appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||
}
|
||||
foreach($response['appointments'] as &$appointment) {
|
||||
$appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']);
|
||||
$appointment['service'] = $this->services_model->get_row($appointment['id_services']);
|
||||
$appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||
}
|
||||
|
||||
echo json_encode($appointments);
|
||||
|
||||
// Get unavailable periods (only for provider).
|
||||
if ($_POST['filter_type'] == FILTER_TYPE_PROVIDER) {
|
||||
$where_clause = array(
|
||||
$where_id => $_POST['record_id'],
|
||||
'start_datetime >=' => $_POST['start_date'],
|
||||
'end_datetime <=' => $_POST['end_date'],
|
||||
'is_unavailable' => TRUE
|
||||
);
|
||||
|
||||
$response['unavailables'] = $this->appointments_model->get_batch($where_clause);
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
|
||||
} catch(Exception $exc) {
|
||||
echo json_encode(array(
|
||||
|
@ -205,10 +216,10 @@ class Backend_api extends CI_Controller {
|
|||
$this->load->model('services_model');
|
||||
$this->load->model('settings_model');
|
||||
|
||||
$appointment_data = $this->appointments_model->get_row($_POST['appointment_id']);
|
||||
$provider_data = $this->providers_model->get_row($appointment_data['id_users_provider']);
|
||||
$customer_data = $this->customers_model->get_row($appointment_data['id_users_customer']);
|
||||
$service_data = $this->services_model->get_row($appointment_data['id_services']);
|
||||
$appointment = $this->appointments_model->get_row($_POST['appointment_id']);
|
||||
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
|
||||
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||
$service = $this->services_model->get_row($appointment['id_services']);
|
||||
|
||||
$company_settings = array(
|
||||
'company_name' => $this->settings_model->get_setting('company_name'),
|
||||
|
@ -220,16 +231,16 @@ class Backend_api extends CI_Controller {
|
|||
$this->appointments_model->delete($_POST['appointment_id']);
|
||||
|
||||
// :: SYNC DELETE WITH GOOGLE CALENDAR
|
||||
if ($appointment_data['id_google_calendar'] != NULL) {
|
||||
if ($appointment['id_google_calendar'] != NULL) {
|
||||
try {
|
||||
$google_sync = $this->providers_model->get_setting('google_sync', $provider_data['id']);
|
||||
$google_sync = $this->providers_model->get_setting('google_sync', $provider['id']);
|
||||
|
||||
if ($google_sync == TRUE) {
|
||||
$google_token = json_decode($this->providers_model
|
||||
->get_setting('google_token', $provider_data['id']));
|
||||
->get_setting('google_token', $provider['id']));
|
||||
$this->load->library('Google_Sync');
|
||||
$this->google_sync->refresh_token($google_token->refresh_token);
|
||||
$this->google_sync->delete_appointment($appointment_data['id_google_calendar']);
|
||||
$this->google_sync->delete_appointment($appointment['id_google_calendar']);
|
||||
}
|
||||
} catch(Exception $exc) {
|
||||
$warnings[] = exceptionToJavascript($exc);
|
||||
|
@ -239,11 +250,11 @@ class Backend_api extends CI_Controller {
|
|||
// :: SEND NOTIFICATION EMAILS TO PROVIDER AND CUSTOMER
|
||||
try {
|
||||
$this->load->library('Notifications');
|
||||
$this->notifications->send_delete_appointment($appointment_data, $provider_data,
|
||||
$service_data, $customer_data, $company_settings, $provider_data['email'],
|
||||
$this->notifications->send_delete_appointment($appointment, $provider,
|
||||
$service, $customer, $company_settings, $provider['email'],
|
||||
$_POST['delete_reason']);
|
||||
$this->notifications->send_delete_appointment($appointment_data, $provider_data,
|
||||
$service_data, $customer_data, $company_settings, $customer_data['email'],
|
||||
$this->notifications->send_delete_appointment($appointment, $provider,
|
||||
$service, $customer, $company_settings, $customer['email'],
|
||||
$_POST['delete_reason']);
|
||||
} catch(Exception $exc) {
|
||||
$warnings[] = exceptionToJavascript($exc);
|
||||
|
@ -334,7 +345,8 @@ class Backend_api extends CI_Controller {
|
|||
|
||||
// Add appointment
|
||||
$unavailable = json_decode($_POST['unavailable'], true);
|
||||
$this->appointments_model->add_unavailable($unavailable);
|
||||
$unavailable['id'] = $this->appointments_model->add_unavailable($unavailable);
|
||||
$unavailable = $this->appointments_model->get_row($unavailable['id']);
|
||||
|
||||
// Google Sync
|
||||
try {
|
||||
|
@ -348,11 +360,13 @@ class Backend_api extends CI_Controller {
|
|||
$this->load->library('google_sync');
|
||||
$this->google_sync->refresh_token($google_token->refresh_token);
|
||||
|
||||
// @task Sync with gcal.
|
||||
$google_event = $this->google_sync->add_unavailable($unavailable);
|
||||
|
||||
$unavailable['id_google_calendar'] = $google_event->id;
|
||||
$this->appointments_model->add_unavailable($unavailable);
|
||||
if ($unavailable['id_google_calendar'] == NULL) {
|
||||
$google_event = $this->google_sync->add_unavailable($unavailable);
|
||||
$unavailable['id_google_calendar'] = $google_event->id;
|
||||
$this->appointments_model->add_unavailable($unavailable);
|
||||
} else {
|
||||
$google_event = $this->google_sync->update_unavailable($unavailable);
|
||||
}
|
||||
}
|
||||
} catch(Exception $exc) {
|
||||
$warnings[] = $exc;
|
||||
|
@ -380,9 +394,35 @@ class Backend_api extends CI_Controller {
|
|||
*/
|
||||
public function ajax_delete_unavailable() {
|
||||
try {
|
||||
// Delete unavailable
|
||||
$this->load->model('appointments_model');
|
||||
$this->load->model('providers_model');
|
||||
|
||||
$unavailable = $this->appointments_model->get_row($_POST['unavailable_id']);
|
||||
$provider = $this->providers_model->get_row($unavailable['id_users_provider']);
|
||||
|
||||
// Delete unavailable
|
||||
$this->appointments_model->delete_unavailable($unavailable['id']);
|
||||
|
||||
// Google Sync
|
||||
try {
|
||||
$google_sync = $this->providers_model->get_setting('google_sync', $provider['id']);
|
||||
if ($google_sync == TRUE) {
|
||||
$google_token = json_decode($this->providers_model->get_setting('google_token', $provider['id']));
|
||||
$this->load->library('google_sync');
|
||||
$this->google_sync->refresh_token($google_token->refresh_token);
|
||||
$this->google_sync->delete_unavailable($unavailable['id_google_calendar']);
|
||||
}
|
||||
} catch(Exception $exc) {
|
||||
$warnings[] = $exc;
|
||||
}
|
||||
|
||||
if (isset($warnings)) {
|
||||
echo json_encode(array(
|
||||
'warnings' => $warnings
|
||||
));
|
||||
} else {
|
||||
echo json_encode('SUCCESS');
|
||||
}
|
||||
|
||||
} catch(Exception $exc) {
|
||||
echo json_encode(array(
|
||||
|
|
|
@ -63,6 +63,125 @@ class Google extends CI_Controller {
|
|||
echo '<h1>Authorization Failed!</h1>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete synchronization of appointments between Google Calendar and Easy!Appointments.
|
||||
*
|
||||
* This method will completely sync the appointments of a provider with his Google Calendar
|
||||
* account. The sync period needs to be relatively small, because a lot of API calls might
|
||||
* be necessary and this will lead to consuming the Google limit for the Calendar API usage.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public function sync($provider_id = NULL) {
|
||||
try {
|
||||
if ($provider_id === NULL) {
|
||||
throw new Exception('Provider id not specified.');
|
||||
}
|
||||
|
||||
$this->load->model('appointments_model');
|
||||
$this->load->model('providers_model');
|
||||
$this->load->model('services_model');
|
||||
$this->load->model('customers_model');
|
||||
$this->load->model('settings_model');
|
||||
|
||||
$provider = $this->providers_model->get_row($provider_id);
|
||||
|
||||
// Check whether the selected provider has google sync enabled.
|
||||
$google_sync = $this->providers_model->get_setting('google_sync', $provider['id']);
|
||||
if (!$google_sync) {
|
||||
throw new Exception('The selected provider has not the google synchronization '
|
||||
. 'setting enabled.');
|
||||
}
|
||||
|
||||
$google_token = json_decode($this->providers_model->get_setting('google_token', $provider['id']));
|
||||
$this->load->library('google_sync');
|
||||
$this->google_sync->refresh_token($google_token->refresh_token);
|
||||
|
||||
// Fetch provider's appointments that belong to the sync time period.
|
||||
$sync_past_days = $this->providers_model->get_setting('sync_past_days', $provider['id']);
|
||||
$sync_future_days = $this->providers_model->get_setting('sync_future_days', $provider['id']);
|
||||
$start = strtotime('-' . $sync_past_days . ' days', strtotime(date('Y-m-d')));
|
||||
$end = strtotime('+' . $sync_future_days . ' days', strtotime(date('Y-m-d')));
|
||||
|
||||
$where_clause = array(
|
||||
'start_datetime >=' => date('Y-m-d H:i:s', $start),
|
||||
'end_datetime <=' => date('Y-m-d H:i:s', $end),
|
||||
'id_users_provider' => $provider['id'],
|
||||
'is_unavailable' => FALSE
|
||||
);
|
||||
|
||||
$appointments = $this->appointments_model->get_batch($where_clause);
|
||||
|
||||
$company_settings = array(
|
||||
'company_name' => $this->settings_model->get_setting('company_name'),
|
||||
'company_link' => $this->settings_model->get_setting('company_link'),
|
||||
'company_email' => $this->settings_model->get_setting('company_email')
|
||||
);
|
||||
|
||||
// Sync each appointment with Google Calendar by following the project's sync
|
||||
// protocol (see documentation).
|
||||
foreach($appointments as $appointment) {
|
||||
$service = $this->services_model->get_row($appointment['id_services']);
|
||||
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||
|
||||
// :: APPOINTMENT WITH NO GCAL_ID -> ADD TO GCAL
|
||||
if ($appointment['id_google_calendar'] == NULL) {
|
||||
$google_event = $this->google_sync->add_appointment($appointment, $provider,
|
||||
$service, $customer, $company_settings);
|
||||
$appointment['id_google_calendar'] = $google_event->id;
|
||||
$this->appointments_model->add($appointment); // save gcal id
|
||||
}
|
||||
|
||||
// :: SYNCED APPOINTMENT NOT FOUND ON GCAL -> DELETE E!A RECORD
|
||||
if ($appointment['id_google_calendar'] != NULL) {
|
||||
try {
|
||||
$google_event = $this->google_sync->get_event($appointment['id_google_calendar']);
|
||||
} catch(Exception $exc) {
|
||||
$this->appointments_model->delete($appointment['id']);
|
||||
$appointment['id_google_calendar'] = NULL; // Do not proceed with the rest sync actions.
|
||||
}
|
||||
}
|
||||
|
||||
// :: SYNCED APPOINTMENT DIFFERENT FROM GCAL EVENT -> UPDATE E!A RECORD
|
||||
if ($appointment['id_google_calendar'] != NULL) {
|
||||
$is_different = FALSE;
|
||||
$appt_start = strtotime($appointment['start_datetime']);
|
||||
$appt_end = strtotime($appointment['end_datetime']);
|
||||
$event_start = strtotime($google_event->getStart()->getDateTime());
|
||||
$event_end = strtotime($google_event->getEnd()->getDateTime());
|
||||
|
||||
if ($appt_start != $event_start
|
||||
|| $appt_end != $event_end) {
|
||||
$is_different = TRUE;
|
||||
}
|
||||
|
||||
if ($is_different) {
|
||||
$appointment['start_datetime'] = date('Y-m-d H:i:s', $event_start);
|
||||
$appointment['end_datetime'] = date('Y-m-d H:i:s', $event_end);
|
||||
$this->appointments_model->add($appointment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// @task :: GCAL EVENT NOT FOUND ON E!A -> ADD EVENT TO E!A
|
||||
|
||||
|
||||
}
|
||||
|
||||
// @task Sync unavailable periods with Google Calendar
|
||||
|
||||
|
||||
echo json_encode('SUCCESS');
|
||||
|
||||
} catch(Exception $exc) {
|
||||
echo json_encode(array(
|
||||
'exceptions' => array($exc)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* End of file google.php */
|
||||
|
|
|
@ -82,6 +82,7 @@ class Unit_tests_appointments_model extends CI_Driver {
|
|||
unset($db_data['hash']);
|
||||
unset($db_data['book_datetime']);
|
||||
unset($db_data['id_google_calendar']);
|
||||
unset($db_data['is_unavailable']);
|
||||
|
||||
$this->CI->unit->run($appointment, $db_data, 'Test if add() appointment (insert '
|
||||
. 'operation) has successfully inserted a record.');
|
||||
|
@ -438,6 +439,7 @@ class Unit_tests_appointments_model extends CI_Driver {
|
|||
$db_data = $this->CI->appointments_model->get_row($appointment['id']);
|
||||
unset($db_data['book_datetime']);
|
||||
unset($db_data['id_google_calendar']);
|
||||
unset($db_data['is_unavailable']);
|
||||
|
||||
// Check if this is the record we seek.
|
||||
$this->CI->unit->run($db_data, $appointment, 'Test get_row() method.');
|
||||
|
|
|
@ -160,8 +160,6 @@ class Google_Sync {
|
|||
|
||||
$event = $this->service->events->get('primary', $appointment['id_google_calendar']);
|
||||
|
||||
// Convert event to object
|
||||
|
||||
$event->setSummary($service['name']);
|
||||
$event->setLocation($company_settings['company_name']);
|
||||
|
||||
|
@ -203,8 +201,76 @@ class Google_Sync {
|
|||
$this->service->events->delete('primary', $google_calendar_id);
|
||||
}
|
||||
|
||||
public function add_unavailble($unavailable) {
|
||||
// @task Implement
|
||||
/**
|
||||
* Add unavailable period event to Google Calendar.
|
||||
*
|
||||
* @param array $unavailable Contains unavailable period's data.
|
||||
* @return Google_Event Returns the google event's object.
|
||||
*/
|
||||
public function add_unavailable($unavailable) {
|
||||
$this->CI->load->helper('general');
|
||||
|
||||
$event = new Google_Event();
|
||||
$event->setSummary('Unavailalbe');
|
||||
$event->setDescription($unavailable['notes']);
|
||||
|
||||
$start = new Google_EventDateTime();
|
||||
$start->setDateTime(date3339(strtotime($unavailable['start_datetime'])));
|
||||
$event->setStart($start);
|
||||
|
||||
$end = new Google_EventDateTime();
|
||||
$end->setDateTime(date3339(strtotime($unavailable['end_datetime'])));
|
||||
$event->setEnd($end);
|
||||
|
||||
// Add the new event to the "primary" calendar.
|
||||
$created_event = $this->service->events->insert('primary', $event);
|
||||
|
||||
return $created_event;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Google Calendar unavailable period event.
|
||||
*
|
||||
* @param array $unavailable Contains the unavailable period data.
|
||||
* @return Google_Event Returns the Google_Event object.
|
||||
*/
|
||||
public function update_unavailable($unavailable) {
|
||||
$this->CI->load->helper('general');
|
||||
|
||||
$event = $this->service->events->get('primary', $unavailable['id_google_calendar']);
|
||||
$event->setDescription($unavailable['notes']);
|
||||
|
||||
$start = new Google_EventDateTime();
|
||||
$start->setDateTime(date3339(strtotime($unavailable['start_datetime'])));
|
||||
$event->setStart($start);
|
||||
|
||||
$end = new Google_EventDateTime();
|
||||
$end->setDateTime(date3339(strtotime($unavailable['end_datetime'])));
|
||||
$event->setEnd($end);
|
||||
|
||||
$updated_event = $this->service->events->update('primary', $event->getId(), $event);
|
||||
|
||||
return $updated_event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete unavailable period event from Google Calendar.
|
||||
*
|
||||
* @param string $google_calendar_id Google Calendar event id to be deleted.
|
||||
*/
|
||||
public function delete_unavailable($google_calendar_id) {
|
||||
$this->service->events->delete('primary', $google_calendar_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an event object from gcal
|
||||
*
|
||||
* @param string $google_calendar_id Id of the google calendar event
|
||||
* @return Google_Event Returns the google event object.
|
||||
*/
|
||||
public function get_event($google_calendar_id) {
|
||||
return $this->service->events->get('primary', $google_calendar_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -360,7 +360,7 @@ class Appointments_Model extends CI_Model {
|
|||
*/
|
||||
public function delete_unavailable($unavailable_id) {
|
||||
if (!is_numeric($unavailable_id)) {
|
||||
throw new Exception('Invalid argument type $appointment_id (value:"' .
|
||||
throw new Exception('Invalid argument type $unavailable_id (value:"' .
|
||||
$unavailable_id . '")');
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ class Customers_Model extends CI_Model {
|
|||
*/
|
||||
public function find_record_id($customer) {
|
||||
if (!isset($customer['email'])) {
|
||||
throw new InvalidArgumentException('Customer\'s email was not provided : '
|
||||
throw new Exception('Customer\'s email was not provided : '
|
||||
. print_r($customer, TRUE));
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ class Customers_Model extends CI_Model {
|
|||
}
|
||||
|
||||
if (!is_string($field_name)) {
|
||||
throw new IException('$field_name argument is not a string : '
|
||||
throw new Exception('$field_name argument is not a string : '
|
||||
. $field_name);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
'availableProviders' : <?php echo json_encode($available_providers); ?>,
|
||||
'availableServices' : <?php echo json_encode($available_services); ?>,
|
||||
'baseUrl' : <?php echo '"' . $base_url . '"'; ?>,
|
||||
'bookAdvanceTimeout' : <?php echo $book_advance_timeout; ?>
|
||||
'bookAdvanceTimeout' : <?php echo $book_advance_timeout; ?>,
|
||||
'editAppointment' : <?php echo json_encode($edit_appointment); ?>
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Easy!Appointments Backend</title>
|
||||
<title>Easy!Appointments Backend | <?php echo $company_name; ?></title>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
|
||||
<link rel="icon" type="image/x-icon"
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<td style="padding: 3px;">$customer_address</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h2>Appointment Link</h2>
|
||||
<a href="$appointment_link" style="width: 600px;">$appointment_link</a>
|
||||
</div>
|
||||
|
|
|
@ -51,6 +51,7 @@ root {
|
|||
font-size: 24px; border: none; border-radius: 0; font-weight: bold; color: #333;
|
||||
text-shadow: 0px 1px 0px #FFF;}
|
||||
#calendar-page #calendar .fc-break { background-image: url('../images/break.jpg'); }
|
||||
#calendar-page #calendar .fc-custom { background-image: url('../images/custom.jpg'); }
|
||||
|
||||
/* BACKEND CUSTOMERS PAGE
|
||||
-------------------------------------------------------------------- */
|
||||
|
|
BIN
src/assets/images/custom.jpg
Normal file
BIN
src/assets/images/custom.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 156 KiB |
|
@ -28,6 +28,8 @@ var BackendCalendar = {
|
|||
'height': BackendCalendar.getCalendarHeight(),
|
||||
'editable': true,
|
||||
'slotMinutes': 30,
|
||||
'axisFormat': 'HH:mm',
|
||||
'timeFormat': 'HH:mm{ - HH:mm}',
|
||||
'columnFormat': {
|
||||
'month': 'ddd',
|
||||
'week': 'ddd d/M',
|
||||
|
@ -85,6 +87,11 @@ var BackendCalendar = {
|
|||
BackendCalendar.bindEventHandlers();
|
||||
$('#select-filter-item').trigger('change');
|
||||
}
|
||||
|
||||
// :: DISPLAY EDIT DIALOG IF APPOINTMENT HASH IS PROVIDED
|
||||
if (GlobalVariables.editAppointment != null) {
|
||||
// @task Display appointment edit dialog to user.
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -160,38 +167,58 @@ var BackendCalendar = {
|
|||
$(document).on('click', '.edit-popover', function() {
|
||||
$(this).parents().eq(2).remove(); // Hide the popover
|
||||
|
||||
var appointment = BackendCalendar.lastFocusedEventData.data;
|
||||
var $dialog = $('#manage-appointment');
|
||||
var $dialog;
|
||||
|
||||
BackendCalendar.resetAppointmentDialog();
|
||||
if (BackendCalendar.lastFocusedEventData.data.is_unavailable == false) {
|
||||
var appointment = BackendCalendar.lastFocusedEventData.data;
|
||||
$dialog = $('#manage-appointment');
|
||||
|
||||
BackendCalendar.resetAppointmentDialog();
|
||||
|
||||
// :: APPLY APPOINTMENT DATA AND SHOW TO MODAL DIALOG
|
||||
$dialog.find('.modal-header h3').text('Edit Appointment');
|
||||
$dialog.find('#appointment-id').val(appointment['id']);
|
||||
$dialog.find('#select-service').val(appointment['id_services']);
|
||||
$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').toString('dd/MM/yyyy HH:mm');
|
||||
$dialog.find('#start-datetime').val(startDatetime);
|
||||
|
||||
var endDatetime = Date.parseExact(appointment['end_datetime'],
|
||||
'yyyy-MM-dd HH:mm:ss').toString('dd/MM/yyyy HH:mm');
|
||||
$dialog.find('#end-datetime').val(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('#notes').val(appointment['notes']);
|
||||
} else {
|
||||
var unavailable = BackendCalendar.lastFocusedEventData.data;
|
||||
|
||||
// Replace string date values with actual date objects.
|
||||
unavailable.start_datetime = GeneralFunctions.clone(BackendCalendar.lastFocusedEventData.start);
|
||||
unavailable.end_datetime = GeneralFunctions.clone(BackendCalendar.lastFocusedEventData.end);
|
||||
|
||||
$dialog = $('#manage-unavailable');
|
||||
BackendCalendar.resetUnavailableDialog();
|
||||
|
||||
// :: APPLY UNAVAILABLE DATA TO DIALOG
|
||||
$dialog.find('.modal-header h3').text('Edit Unavailable Period');
|
||||
$dialog.find('#unavailable-id').val(unavailable.id);
|
||||
$dialog.find('#unavailable-start').val(unavailable.start_datetime.toString('dd/MM/yyyy HH:mm'));
|
||||
$dialog.find('#unavailable-end').val(unavailable.end_datetime.toString('dd/MM/yyyy HH:mm'));
|
||||
$dialog.find('#unavailable-notes').val(unavailable.notes);
|
||||
}
|
||||
|
||||
// :: APPLY APPOINTMENT DATA AND SHOW TO MODAL DIALOG
|
||||
$dialog.find('.modal-header h3').text('Edit Appointment');
|
||||
$dialog.find('#appointment-id').val(appointment['id']);
|
||||
$dialog.find('#select-service').val(appointment['id_services']);
|
||||
$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').toString('dd/MM/yyyy HH:mm');
|
||||
$dialog.find('#start-datetime').val(startDatetime);
|
||||
|
||||
var endDatetime = Date.parseExact(appointment['end_datetime'],
|
||||
'yyyy-MM-dd HH:mm:ss').toString('dd/MM/yyyy HH:mm');
|
||||
$dialog.find('#end-datetime').val(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('#notes').val(appointment['notes']);
|
||||
|
||||
// :: DISPLAY THE MANAGE APPOINTMENTS MODAL DIALOG
|
||||
// :: DIAPLY EDIT DIALOG
|
||||
$dialog.modal('show');
|
||||
});
|
||||
|
||||
|
@ -205,48 +232,81 @@ var BackendCalendar = {
|
|||
$(document).on('click', '.delete-popover', function() {
|
||||
$(this).parents().eq(2).remove(); // Hide the popover
|
||||
|
||||
var messageButtons = {
|
||||
'OK': function() {
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_delete_appointment';
|
||||
|
||||
var postData = {
|
||||
'appointment_id' : BackendCalendar.lastFocusedEventData.data['id'],
|
||||
'delete_reason': $('#delete-reason').val()
|
||||
};
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
/////////////////////////////////////////////////////////
|
||||
console.log('Delete Appointment Response :', response);
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
if (BackendCalendar.lastFocusedEventData.data.is_unavailable == false) {
|
||||
var messageButtons = {
|
||||
'OK': function() {
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_delete_appointment';
|
||||
|
||||
var postData = {
|
||||
'appointment_id' : BackendCalendar.lastFocusedEventData.data['id'],
|
||||
'delete_reason': $('#delete-reason').val()
|
||||
};
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
/////////////////////////////////////////////////////////
|
||||
console.log('Delete Appointment Response :', response);
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
$('#message_box').dialog('close');
|
||||
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
// Refresh calendar event items.
|
||||
$('#select-filter-item').trigger('change');
|
||||
}, 'json');
|
||||
},
|
||||
'Cancel': function() {
|
||||
$('#message_box').dialog('close');
|
||||
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
// Refresh calendar event items.
|
||||
$('#select-filter-item').trigger('change');
|
||||
}, 'json');
|
||||
},
|
||||
'Cancel': function() {
|
||||
}
|
||||
};
|
||||
|
||||
GeneralFunctions.displayMessageBox('Delete Appointment', 'Please take a minute '
|
||||
+ 'to write the reason you are deleting the appointment:', messageButtons);
|
||||
$('#message_box').append('<textarea id="delete-reason"></textarea>');
|
||||
$('#delete-reason').css('width', '320px');
|
||||
} else {
|
||||
// Do not display confirmation promt.
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_delete_unavailable';
|
||||
|
||||
var postData = {
|
||||
'unavailable_id' : BackendCalendar.lastFocusedEventData.data.id
|
||||
};
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
/////////////////////////////////////////////////////////
|
||||
console.log('Delete Unavailable Response :', response);
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
$('#message_box').dialog('close');
|
||||
}
|
||||
};
|
||||
|
||||
GeneralFunctions.displayMessageBox('Delete Appointment', 'Please take a minute '
|
||||
+ 'to write the reason you are deleting the appointment:', messageButtons);
|
||||
$('#message_box').append('<textarea id="delete-reason"></textarea>');
|
||||
$('#delete-reason').css('width', '320px');
|
||||
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
// Refresh calendar event items.
|
||||
$('#select-filter-item').trigger('change');
|
||||
}, 'json');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -353,6 +413,11 @@ var BackendCalendar = {
|
|||
successCallback, errorCallback);
|
||||
});
|
||||
|
||||
/**
|
||||
* Event: Manage Unavailable Dialog Save Button "Click"
|
||||
*
|
||||
* Stores the unavailable period changes or inserts a new record.
|
||||
*/
|
||||
$('#manage-unavailable #save-unavailable').click(function() {
|
||||
var $dialog = $('#manage-unavailable');
|
||||
|
||||
|
@ -365,6 +430,7 @@ var BackendCalendar = {
|
|||
'<div class="alert alert-error">' +
|
||||
'Start date value is bigger than end date!' +
|
||||
'</div>');
|
||||
$dialog.find('.modal-message').show();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -376,6 +442,11 @@ var BackendCalendar = {
|
|||
'id_users_provider': $('#select-filter-item').val() // curr provider
|
||||
};
|
||||
|
||||
if ($dialog.find('#unavailable-id').val() !== '') {
|
||||
// Set the id value, only if we are editing an appointment.
|
||||
unavailable.id = $dialog.find('#unavailable-id').val();
|
||||
}
|
||||
|
||||
var successCallback = function(response) {
|
||||
///////////////////////////////////////////////////////////////////
|
||||
console.log('Save Unavailable Time Period Response:', response);
|
||||
|
@ -385,6 +456,12 @@ var BackendCalendar = {
|
|||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
|
||||
$dialog.find('.modal-header').append(
|
||||
'<br><div class="alert alert-error">' +
|
||||
'Unexpected issues occured!' +
|
||||
'</div>');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -393,8 +470,20 @@ var BackendCalendar = {
|
|||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
$('#manage-unavailable').modal('hide');
|
||||
|
||||
// Display success message to the user.
|
||||
$dialog.find('.modal-header').append(
|
||||
'<br><div class="alert alert-success">' +
|
||||
'Appointment saved successfully!' +
|
||||
'</div>');
|
||||
|
||||
// Close the modal dialog and refresh the calendar appointments
|
||||
// after one second.
|
||||
setTimeout(function() {
|
||||
$dialog.find('.alert').remove();
|
||||
$dialog.modal('hide');
|
||||
$('#select-filter-item').trigger('change');
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
var errorCallback = function(jqXHR, textStatus, errorThrown) {
|
||||
|
@ -404,11 +493,21 @@ var BackendCalendar = {
|
|||
|
||||
GeneralFunctions.displayMessageBox('Communication Error', 'Unfortunately ' +
|
||||
'the operation could not complete due to server communication errors.');
|
||||
|
||||
$dialog.find('.modal-header').append(
|
||||
'<br><div class="alert alert-error">' +
|
||||
'A server communication error occured, please try again.' +
|
||||
'</div>');
|
||||
};
|
||||
|
||||
BackendCalendar.saveUnavalable(unavailable, successCallback, errorCallback);
|
||||
BackendCalendar.saveUnavailable(unavailable, successCallback, errorCallback);
|
||||
});
|
||||
|
||||
/**
|
||||
* Event: Manage Unavailable Dialog Cancel Button "Click"
|
||||
*
|
||||
* Closes the dialog without saveing any changes to the database.
|
||||
*/
|
||||
$('#manage-unavailable #cancel-unavailable').click(function() {
|
||||
$('#manage-unavailable').modal('hide');
|
||||
});
|
||||
|
@ -551,8 +650,9 @@ var BackendCalendar = {
|
|||
|
||||
// :: ADD APPOINTMENTS TO CALENDAR
|
||||
var calendarEvents = [];
|
||||
var $calendar = $('#calendar');
|
||||
|
||||
$.each(response, function(index, appointment){
|
||||
$.each(response.appointments, function(index, appointment){
|
||||
var event = {
|
||||
'id': appointment['id'],
|
||||
'title': appointment['service']['name'] + ' - '
|
||||
|
@ -571,7 +671,8 @@ var BackendCalendar = {
|
|||
$calendar.fullCalendar('addEventSource', calendarEvents);
|
||||
|
||||
// :: ADD PROVIDER'S UNAVAILABLE TIME PERIODS
|
||||
var calendarView = $('#calendar').fullCalendar('getView').name;
|
||||
var calendarView = $calendar.fullCalendar('getView').name;
|
||||
|
||||
if (filterType === BackendCalendar.FILTER_TYPE_PROVIDER
|
||||
&& calendarView !== 'month') {
|
||||
|
||||
|
@ -582,11 +683,11 @@ var BackendCalendar = {
|
|||
|
||||
switch(calendarView) {
|
||||
case 'agendaDay':
|
||||
var selDayName = $('#calendar').fullCalendar('getView')
|
||||
var selDayName = $calendar.fullCalendar('getView')
|
||||
.start.toString('dddd').toLowerCase();
|
||||
|
||||
// Add unavailable period before work starts.
|
||||
var calendarDateStart = $('#calendar').fullCalendar('getView').start;
|
||||
var calendarDateStart = $calendar.fullCalendar('getView').start;
|
||||
var workDateStart = Date.parseExact(
|
||||
calendarDateStart.toString('dd/MM/yyyy') + ' '
|
||||
+ workingPlan[selDayName].start,
|
||||
|
@ -602,11 +703,11 @@ var BackendCalendar = {
|
|||
'editable': false,
|
||||
'className': 'fc-unavailable'
|
||||
};
|
||||
$('#calendar').fullCalendar('renderEvent', unavailablePeriod, true);
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod, false);
|
||||
}
|
||||
|
||||
// Add unavailable period after work ends.
|
||||
var calendarDateEnd = $('#calendar').fullCalendar('getView').end;
|
||||
var calendarDateEnd = $calendar.fullCalendar('getView').end;
|
||||
var workDateEnd = Date.parseExact(
|
||||
calendarDateStart.toString('dd/MM/yyyy') + ' '
|
||||
+ workingPlan[selDayName].end,
|
||||
|
@ -621,7 +722,7 @@ var BackendCalendar = {
|
|||
'editable': false,
|
||||
'className': 'fc-unavailable'
|
||||
};
|
||||
$('#calendar').fullCalendar('renderEvent', unavailablePeriod, true);
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod, false);
|
||||
}
|
||||
|
||||
// Add unavailable periods for breaks.
|
||||
|
@ -640,16 +741,28 @@ var BackendCalendar = {
|
|||
'editable': false,
|
||||
'className': 'fc-unavailable fc-break'
|
||||
};
|
||||
$('#calendar').fullCalendar('renderEvent', unavailablePeriod, true);
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod, false);
|
||||
});
|
||||
|
||||
// @task Add custom unavailable periods.
|
||||
|
||||
// Add custom unavailable periods.
|
||||
$.each(response.unavailables, function(index, unavailable) {
|
||||
var unavailablePeriod = {
|
||||
'title': 'Unavailable',
|
||||
'start': Date.parse(unavailable.start_datetime),
|
||||
'end': Date.parse(unavailable.end_datetime),
|
||||
'allDay': false,
|
||||
'color': '#123456',
|
||||
'editable': true,
|
||||
'className': 'fc-unavailable fc-custom',
|
||||
'data': unavailable
|
||||
};
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod, false);
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case 'agendaWeek':
|
||||
var currDateStart = GeneralFunctions.clone($('#calendar').fullCalendar('getView').start);
|
||||
var currDateStart = GeneralFunctions.clone($calendar.fullCalendar('getView').start);
|
||||
var currDateEnd = GeneralFunctions.clone(currDateStart).addDays(1);
|
||||
|
||||
$.each(workingPlan, function(index, workingDay) {
|
||||
|
@ -668,7 +781,7 @@ var BackendCalendar = {
|
|||
'editable': false,
|
||||
'className': 'fc-unavailable'
|
||||
};
|
||||
$('#calendar').fullCalendar('renderEvent', unavailablePeriod,
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod,
|
||||
true);
|
||||
}
|
||||
|
||||
|
@ -685,7 +798,7 @@ var BackendCalendar = {
|
|||
'editable': false,
|
||||
'className': 'fc-unavailable fc-brake'
|
||||
};
|
||||
$('#calendar').fullCalendar('renderEvent', unavailablePeriod, true);
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod, false);
|
||||
}
|
||||
|
||||
// Add unavailable periods during day breaks.
|
||||
|
@ -704,10 +817,26 @@ var BackendCalendar = {
|
|||
'editable': false,
|
||||
'className': 'fc-unavailable fc-break'
|
||||
};
|
||||
$('#calendar').fullCalendar('renderEvent', unavailablePeriod, true);
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod, false);
|
||||
});
|
||||
|
||||
// @task Add custom unavailable periods.
|
||||
// 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': '#123456',
|
||||
'editable': true,
|
||||
'className': 'fc-unavailable fc-custom',
|
||||
'data': unavailable
|
||||
};
|
||||
$calendar.fullCalendar('renderEvent', unavailablePeriod, false);
|
||||
}
|
||||
});
|
||||
|
||||
currDateStart.addDays(1);
|
||||
currDateEnd.addDays(1);
|
||||
|
@ -778,7 +907,7 @@ var BackendCalendar = {
|
|||
* @param {function} successCallback The ajax success callback function.
|
||||
* @param {function} errorCallback The ajax failure callback function.
|
||||
*/
|
||||
saveUnavalable: function(unavailable, successCallback, errorCallback) {
|
||||
saveUnavailable: function(unavailable, successCallback, errorCallback) {
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_unavailable';
|
||||
|
||||
var postData = {
|
||||
|
@ -809,64 +938,117 @@ var BackendCalendar = {
|
|||
$('#notification').hide('bind');
|
||||
}
|
||||
|
||||
// :: PREPARE THE APPOINTMENT DATA
|
||||
var appointment = GeneralFunctions.clone(event.data);
|
||||
if (event.data.is_unavailable == false) {
|
||||
// :: PREPARE THE APPOINTMENT DATA
|
||||
var appointment = GeneralFunctions.clone(event.data);
|
||||
|
||||
// Must delete the following because only appointment data should be
|
||||
// provided to the ajax call.
|
||||
delete appointment['customer'];
|
||||
delete appointment['provider'];
|
||||
delete appointment['service'];
|
||||
// Must delete the following because only appointment data should be
|
||||
// provided to the ajax call.
|
||||
delete appointment['customer'];
|
||||
delete appointment['provider'];
|
||||
delete appointment['service'];
|
||||
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ minutes: minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ minutes: minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
// :: DEFINE THE SUCCESS CALLBACK FUNCTION
|
||||
var successCallback = function(response) {
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
// :: DEFINE THE SUCCESS CALLBACK FUNCTION
|
||||
var successCallback = function(response) {
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
// Display success notification to user.
|
||||
var undoFunction = function() {
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_appointment';
|
||||
var postData = { 'appointment_data': JSON.stringify(appointment) };
|
||||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
$('#notification').hide('blind');
|
||||
revertFunc();
|
||||
});
|
||||
// Display success notification to user.
|
||||
var undoFunction = function() {
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_appointment';
|
||||
var postData = { 'appointment_data': JSON.stringify(appointment) };
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
$('#notification').hide('blind');
|
||||
revertFunc();
|
||||
});
|
||||
};
|
||||
|
||||
Backend.displayNotification('Appointment updated successfully!', [
|
||||
{
|
||||
'label': 'Undo',
|
||||
'function': undoFunction
|
||||
}
|
||||
]);
|
||||
$('#footer').css('position', 'static'); // Footer position fix.
|
||||
};
|
||||
|
||||
Backend.displayNotification('Appointment updated successfully!', [
|
||||
{
|
||||
'label': 'Undo',
|
||||
'function': undoFunction
|
||||
}
|
||||
]);
|
||||
$('#footer').css('position', 'static'); // Footer position fix.
|
||||
};
|
||||
// :: UPDATE APPOINTMENT DATA VIA AJAX CALL
|
||||
BackendCalendar.saveAppointment(appointment, undefined,
|
||||
successCallback, undefined);
|
||||
} else {
|
||||
// :: UPDATE UNAVAILABLE TIME PERIOD
|
||||
var unavailable = {
|
||||
'id': event.data.id,
|
||||
'start_datetime': event.start.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'end_datetime': event.end.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'id_users_provider': event.data.id_users_provider
|
||||
};
|
||||
|
||||
// :: UPDATE APPOINTMENT DATA VIA AJAX CALL
|
||||
BackendCalendar.saveAppointment(appointment, undefined,
|
||||
successCallback, undefined);
|
||||
// :: DEFINE THE SUCCESS CALLBACK FUNCTION
|
||||
var successCallback = function(response) {
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
// Display success notification to user.
|
||||
var undoFunction = function() {
|
||||
unavailable['end_datetime'] = Date.parseExact(
|
||||
unavailable['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_unavailable';
|
||||
var postData = { 'unavailable': JSON.stringify(unavailable) };
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
$('#notification').hide('blind');
|
||||
revertFunc();
|
||||
});
|
||||
};
|
||||
|
||||
Backend.displayNotification('Unavailable time period updated successfully!', [
|
||||
{
|
||||
'label': 'Undo',
|
||||
'function': undoFunction
|
||||
}
|
||||
]);
|
||||
$('#footer').css('position', 'static'); // Footer position fix.
|
||||
};
|
||||
|
||||
BackendCalendar.saveUnavailable(unavailable, successCallback, undefined);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -905,10 +1087,23 @@ var BackendCalendar = {
|
|||
calendarEventClick: function(event, jsEvent, view) {
|
||||
$('.popover').remove(); // Close all open popovers.
|
||||
|
||||
var html;
|
||||
var html; // Popover's html code
|
||||
|
||||
if ($(jsEvent.target.offsetParent).hasClass('fc-unavailable')
|
||||
|| $(jsEvent.target).parents().eq(1).hasClass('fc-unavailable')) {
|
||||
// Depending where the user clicked the event (title or empty space) we
|
||||
// need to use different selectors to reach the parent element.
|
||||
var $parent = $(jsEvent.target.offsetParent);
|
||||
var $altParent = $(jsEvent.target).parents().eq(1);
|
||||
|
||||
if ($parent.hasClass('fc-unavailable') || $altParent.hasClass('fc-unavailable')) {
|
||||
var displayEdit = ($parent.hasClass('fc-custom') || $altParent.hasClass('fc-custom'))
|
||||
? '' : 'hide';
|
||||
var displayDelete = displayEdit; // Same value at the time.
|
||||
|
||||
var notes = '';
|
||||
if (event.data) { // Only custom unavailable periods have notes.
|
||||
notes = '<strong>Notes</strong> ' + event.data.notes;
|
||||
}
|
||||
|
||||
html =
|
||||
'<style type="text/css">'
|
||||
+ '.popover-content strong {min-width: 80px; display:inline-block;}'
|
||||
|
@ -919,10 +1114,12 @@ var BackendCalendar = {
|
|||
+ '<br>' +
|
||||
'<strong>End</strong> '
|
||||
+ event.end.toString('dd/MM/yyyy HH:mm')
|
||||
+ '<br>' +
|
||||
+ '<br>'
|
||||
+ notes
|
||||
+ '<hr>' +
|
||||
'<center>' +
|
||||
'<button class="edit-popover btn btn-primary">Edit</button>' +
|
||||
'<button class="delete-popover btn btn-danger">Delete</button>' +
|
||||
'<button class="edit-popover btn btn-primary ' + displayEdit + '">Edit</button>' +
|
||||
'<button class="delete-popover btn btn-danger ' + displayDelete + '">Delete</button>' +
|
||||
'<button class="close-popover btn" data-po=' + jsEvent.target + '>Close</button>' +
|
||||
'</center>';
|
||||
} else {
|
||||
|
@ -966,6 +1163,9 @@ var BackendCalendar = {
|
|||
|
||||
BackendCalendar.lastFocusedEventData = event;
|
||||
$(jsEvent.target).popover('show');
|
||||
|
||||
// Fix popover position
|
||||
if ($('.popover').position().top < 200) $('.popover').css('top', '200px');
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -979,84 +1179,147 @@ var BackendCalendar = {
|
|||
revertFunc, jsEvent, ui, view) {
|
||||
if ($('#notification').is(':visible')) {
|
||||
$('#notification').hide('bind');
|
||||
}
|
||||
}
|
||||
|
||||
if (event.data.is_unavailable == false) {
|
||||
|
||||
// :: PREPARE THE APPOINTMENT DATA
|
||||
var appointment = GeneralFunctions.clone(event.data);
|
||||
|
||||
// Must delete the following because only appointment data should be
|
||||
// provided to the ajax call.
|
||||
delete appointment['customer'];
|
||||
delete appointment['provider'];
|
||||
delete appointment['service'];
|
||||
// :: PREPARE THE APPOINTMENT DATA
|
||||
var appointment = GeneralFunctions.clone(event.data);
|
||||
|
||||
appointment['start_datetime'] = Date.parseExact(
|
||||
appointment['start_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: dayDelta, minutes: minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: dayDelta, minutes: minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
event.data['start_datetime'] = appointment['start_datetime'];
|
||||
event.data['end_datetime'] = appointment['end_datetime'];
|
||||
|
||||
// :: DEFINE THE SUCCESS CALLBACK FUNCTION
|
||||
var successCallback = function(response) {
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
// Define the undo function, if the user needs to reset the last change.
|
||||
var undoFunction = function() {
|
||||
appointment['start_datetime'] = Date.parseExact(
|
||||
appointment['start_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: -dayDelta, minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
// Must delete the following because only appointment data should be
|
||||
// provided to the ajax call.
|
||||
delete appointment['customer'];
|
||||
delete appointment['provider'];
|
||||
delete appointment['service'];
|
||||
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: -dayDelta, minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
event.data['start_datetime'] = appointment['start_datetime'];
|
||||
event.data['end_datetime'] = appointment['end_datetime'];
|
||||
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_appointment';
|
||||
|
||||
var postData = { 'appointment_data': JSON.stringify(appointment) };
|
||||
appointment['start_datetime'] = Date.parseExact(
|
||||
appointment['start_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: dayDelta, minutes: minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
$('#notification').hide('blind');
|
||||
revertFunc();
|
||||
});
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: dayDelta, minutes: minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
event.data['start_datetime'] = appointment['start_datetime'];
|
||||
event.data['end_datetime'] = appointment['end_datetime'];
|
||||
|
||||
// :: DEFINE THE SUCCESS CALLBACK FUNCTION
|
||||
var successCallback = function(response) {
|
||||
if (response.exceptions) {
|
||||
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
// Define the undo function, if the user needs to reset the last change.
|
||||
var undoFunction = function() {
|
||||
appointment['start_datetime'] = Date.parseExact(
|
||||
appointment['start_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: -dayDelta, minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
appointment['end_datetime'] = Date.parseExact(
|
||||
appointment['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: -dayDelta, minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
event.data['start_datetime'] = appointment['start_datetime'];
|
||||
event.data['end_datetime'] = appointment['end_datetime'];
|
||||
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_appointment';
|
||||
|
||||
var postData = { 'appointment_data': JSON.stringify(appointment) };
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
$('#notification').hide('blind');
|
||||
revertFunc();
|
||||
});
|
||||
};
|
||||
|
||||
Backend.displayNotification('Appointment updated successfully!', [
|
||||
{
|
||||
'label': 'Undo',
|
||||
'function': undoFunction
|
||||
}
|
||||
]);
|
||||
|
||||
$('#footer').css('position', 'static'); // Footer position fix.
|
||||
};
|
||||
|
||||
Backend.displayNotification('Appointment updated successfully!', [
|
||||
{
|
||||
'label': 'Undo',
|
||||
'function': undoFunction
|
||||
}
|
||||
]);
|
||||
// :: UPDATE APPOINTMENT DATA VIA AJAX CALL
|
||||
BackendCalendar.saveAppointment(appointment, undefined,
|
||||
successCallback, undefined);
|
||||
} else {
|
||||
// :: UPDATE UNAVAILABLE TIME PERIOD
|
||||
var unavailable = {
|
||||
'id': event.data.id,
|
||||
'start_datetime': event.start.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'end_datetime': event.end.toString('yyyy-MM-dd HH:mm:ss'),
|
||||
'id_users_provider': event.data.id_users_provider
|
||||
}
|
||||
|
||||
$('#footer').css('position', 'static'); // Footer position fix.
|
||||
};
|
||||
var successCallback = function(response) {
|
||||
console.log('Drop Unavailable Event Response:', response);
|
||||
|
||||
if (response.exceptions) {
|
||||
reponse.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
|
||||
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.warnings) {
|
||||
reponse.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
var undoFunction = function() {
|
||||
unavailable['start_datetime'] = Date.parseExact(
|
||||
unavailable['start_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: -dayDelta, minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
// :: UPDATE APPOINTMENT DATA VIA AJAX CALL
|
||||
BackendCalendar.saveAppointment(appointment, undefined,
|
||||
successCallback, undefined);
|
||||
unavailable['end_datetime'] = Date.parseExact(
|
||||
unavailable['end_datetime'], 'yyyy-MM-dd HH:mm:ss')
|
||||
.add({ days: -dayDelta, minutes: -minuteDelta })
|
||||
.toString('yyyy-MM-dd HH:mm:ss');
|
||||
|
||||
event.data['start_datetime'] = unavailable['start_datetime'];
|
||||
event.data['end_datetime'] = unavailable['end_datetime'];
|
||||
|
||||
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_unavailable';
|
||||
|
||||
var postData = { 'unavailable': JSON.stringify(unavailable) };
|
||||
|
||||
$.post(postUrl, postData, function(response) {
|
||||
$('#notification').hide('blind');
|
||||
revertFunc();
|
||||
});
|
||||
};
|
||||
|
||||
Backend.displayNotification('Unavailable period updated successfully!', [
|
||||
{
|
||||
'label': 'Undo',
|
||||
'function': undoFunction
|
||||
}
|
||||
]);
|
||||
|
||||
$('#footer').css('position', 'static'); // Footer position fix.
|
||||
};
|
||||
|
||||
BackendCalendar.saveUnavailable(unavailable, successCallback, undefined);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1165,14 +1428,12 @@ var BackendCalendar = {
|
|||
.addMinutes(serviceDuration).toString('dd/MM/yyyy HH:mm');
|
||||
|
||||
$dialog.find('#start-datetime').datetimepicker({
|
||||
'dateFormat': 'dd/mm/yy',
|
||||
'minDate': 0
|
||||
'dateFormat': 'dd/mm/yy'
|
||||
});
|
||||
$dialog.find('#start-datetime').val(startDatetime);
|
||||
|
||||
$dialog.find('#end-datetime').datetimepicker({
|
||||
'dateFormat': 'dd/mm/yy',
|
||||
'minDate': 0
|
||||
'dateFormat': 'dd/mm/yy'
|
||||
});
|
||||
$dialog.find('#end-datetime').val(endDatetime);
|
||||
},
|
||||
|
@ -1228,14 +1489,12 @@ var BackendCalendar = {
|
|||
var end = new Date().addHours(1).toString('dd/MM/yyyy HH:mm');
|
||||
|
||||
$dialog.find('#unavailable-start').datetimepicker({
|
||||
'dateFormat': 'dd/mm/yy',
|
||||
'minDate': 0
|
||||
'dateFormat': 'dd/mm/yy'
|
||||
});
|
||||
$dialog.find('#unavailable-start').val(start);
|
||||
|
||||
$dialog.find('#unavailable-end').datetimepicker({
|
||||
'dateFormat': 'dd/mm/yy',
|
||||
'minDate': 0
|
||||
'dateFormat': 'dd/mm/yy'
|
||||
});
|
||||
$dialog.find('#unavailable-end').val(end);
|
||||
|
||||
|
|
|
@ -345,7 +345,7 @@ var FrontendBook = {
|
|||
FrontendBook.updateConfirmFrame();
|
||||
|
||||
} else {
|
||||
$('#available-hours').text('There are no available appointment'
|
||||
$('#available-hours').text('There are no available appointment '
|
||||
+ 'hours for the selected date. Please choose another date.');
|
||||
}
|
||||
}, 'json');
|
||||
|
|
Loading…
Reference in a new issue