* Fixed google sync problem with unavailable time periods.
* Fixed minor issues with backend. * Fixed get_provider_available_time_periods() method - now works correctly. * Added unavailable notes in the calendar (under the "Unavailable" title). * Updated the thesis code snippets. * Added listings.pdf, a free ebook about latex listings.
This commit is contained in:
parent
140cb62627
commit
2e7e668465
20 changed files with 276 additions and 302 deletions
|
@ -47,7 +47,7 @@
|
|||
emph =[1]{php},
|
||||
emphstyle =[1]\color{black},
|
||||
emph =[2]{if,and,or,else,public,function,try,catch,return},
|
||||
emphstyle =[2]\color{dkyellow},
|
||||
emphstyle =[2]\color{dkblue},
|
||||
numbers = left,
|
||||
tabsize = 2,
|
||||
backgroundcolor = \color{ltgrey},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* Complete synchronization of appointments between Google Calendar
|
||||
* and Easy!Appointments.
|
||||
* 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
|
||||
|
@ -35,7 +35,7 @@ public function sync($provider_id = NULL) {
|
|||
->get_setting('google_sync', $provider['id']);
|
||||
if (!$google_sync) {
|
||||
throw new Exception('The selected provider has not the '
|
||||
. 'google synchronization setting enabled.');
|
||||
. 'Google synchronization setting enabled.');
|
||||
}
|
||||
|
||||
$google_token = json_decode($this->providers_model
|
||||
|
@ -43,49 +43,53 @@ public function sync($provider_id = NULL) {
|
|||
$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.
|
||||
// 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')));
|
||||
$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
|
||||
'id_users_provider' => $provider['id']
|
||||
);
|
||||
|
||||
$appointments = $this->appointments_model
|
||||
->get_batch($where_clause);
|
||||
$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')
|
||||
'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) {
|
||||
if ($appointment['is_unavailable'] == FALSE) {
|
||||
$service = $this->services_model
|
||||
->get_row($appointment['id_services']);
|
||||
$customer = $this->customers_model
|
||||
->get_row($appointment['id_users_customer']);
|
||||
} else {
|
||||
$service = NULL;
|
||||
$customer = NULL;
|
||||
}
|
||||
|
||||
// If current appointment not synced yet, add to gcal.
|
||||
if ($appointment['id_google_calendar'] == NULL) {
|
||||
$google_event = $this->google_sync
|
||||
->add_appointment($appointment, $provider, $service,
|
||||
$customer, $company_settings);
|
||||
->add_appointment($appointment, $provider,
|
||||
$service, $customer, $company_settings);
|
||||
$appointment['id_google_calendar'] = $google_event->id;
|
||||
$this->appointments_model->add($appointment);// Save gcal id
|
||||
} else {
|
||||
|
@ -94,8 +98,13 @@ public function sync($provider_id = NULL) {
|
|||
$google_event = $this->google_sync
|
||||
->get_event($appointment['id_google_calendar']);
|
||||
|
||||
// If gcal event is different from e!a appointment then
|
||||
// update Easy!Appointments record.
|
||||
if ($google_event->status == 'cancelled') {
|
||||
throw new Exception('Event is cancelled, remove the '
|
||||
. 'record from Easy!Appointments.');
|
||||
}
|
||||
|
||||
// If gcal event is different from e!a appointment
|
||||
// then update e!a record.
|
||||
$is_different = FALSE;
|
||||
$appt_start = strtotime($appointment['start_datetime']);
|
||||
$appt_end = strtotime($appointment['end_datetime']);
|
||||
|
@ -146,7 +155,6 @@ public function sync($provider_id = NULL) {
|
|||
'id_users_customer' => NULL,
|
||||
'id_services' => NULL,
|
||||
);
|
||||
|
||||
$this->appointments_model->add($appointment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* @param string $selected_date The date to be checked (MySQL
|
||||
* formatted string).
|
||||
* @param array $exclude_appointments This array contains the ids of
|
||||
* the appointments that will not be taken into consideration when
|
||||
* the available time periods are calculated.
|
||||
* the appointments that will not be taken into consideration when the
|
||||
* available time periods are calculated.
|
||||
* @return array Returns an array with the available time periods of
|
||||
* the provider.
|
||||
*/
|
||||
|
@ -28,13 +28,12 @@ private function get_provider_available_time_periods($provider_id,
|
|||
->get_setting('working_plan', $provider_id), true);
|
||||
|
||||
$where_clause = array(
|
||||
'DATE(start_datetime)' =>
|
||||
date('Y-m-d', strtotime($selected_date)),
|
||||
'DATE(start_datetime)'=>date('Y-m-d', strtotime($selected_date)),
|
||||
'id_users_provider'=>$provider_id
|
||||
);
|
||||
|
||||
$reserved_appointments =
|
||||
$this->appointments_model->get_batch($where_clause);
|
||||
$reserved_appointments = $this->appointments_model
|
||||
->get_batch($where_clause);
|
||||
|
||||
// Sometimes it might be necessary to not take into account some
|
||||
// appointment records in order to display what the providers'
|
||||
|
@ -47,10 +46,9 @@ private function get_provider_available_time_periods($provider_id,
|
|||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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)))];
|
||||
$available_periods_with_breaks = array();
|
||||
|
@ -65,8 +63,8 @@ private function get_provider_available_time_periods($provider_id,
|
|||
$start_hour = $selected_date_working_plan['start'];
|
||||
$end_hour = $break['start'];
|
||||
} else {
|
||||
$start_hour = $selected_date_working_plan
|
||||
['breaks'][$last_break_index]['end'];
|
||||
$start_hour = $selected_date_working_plan['breaks']
|
||||
[$last_break_index]['end'];
|
||||
$end_hour = $break['start'];
|
||||
}
|
||||
|
||||
|
@ -75,7 +73,6 @@ private function get_provider_available_time_periods($provider_id,
|
|||
'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'],
|
||||
|
@ -84,109 +81,59 @@ private function get_provider_available_time_periods($provider_id,
|
|||
}
|
||||
|
||||
// Break the empty periods with the reserved appointments.
|
||||
$available_periods_with_appointments = array();
|
||||
|
||||
if (count($reserved_appointments) > 0) {
|
||||
|
||||
foreach($available_periods_with_breaks as $period) {
|
||||
|
||||
foreach($reserved_appointments as $index=>$reserved) {
|
||||
$appointment_start =
|
||||
date('H:i', strtotime($reserved['start_datetime']));
|
||||
$appointment_end =
|
||||
date('H:i', strtotime($reserved['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) {
|
||||
// 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']));
|
||||
|
||||
if ($period_start < $appt_start
|
||||
&& $period_end > $appt_end) {
|
||||
if ($appointment_start > $appt_start) {
|
||||
$appointment_start = $appt_start;
|
||||
}
|
||||
|
||||
if ($appointment_end < $appt_end) {
|
||||
$appointment_end = $appt_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current appointment is within the current
|
||||
// empty space. So we need to break the empty
|
||||
// space into two other spaces that don't include
|
||||
// the appointment.
|
||||
$new_period = array(
|
||||
'start' => $period_start,
|
||||
'end' => $appointment_start
|
||||
);
|
||||
|
||||
if (!in_array($new_period,
|
||||
$available_periods_with_appointments)) {
|
||||
$available_periods_with_appointments[] = $new_period;
|
||||
}
|
||||
|
||||
$new_period = array(
|
||||
'start' => $appointment_end,
|
||||
'end' => $period_end
|
||||
);
|
||||
|
||||
if (!in_array($new_period,
|
||||
$available_periods_with_appointments)) {
|
||||
$available_periods_with_appointments[] = $new_period;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Check if there are any other appointments
|
||||
// between this time space. If not, it is going
|
||||
// to be added as it is.
|
||||
$found = FALSE;
|
||||
|
||||
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']));
|
||||
|
||||
if ($period_start < $appt_start
|
||||
&& $period_end > $appt_end) {
|
||||
$found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// It is also necessary to check that this time
|
||||
// period doesn't already exist in the
|
||||
// "$empty_spaces_with_appointments" array.
|
||||
$empty_period = array(
|
||||
'start' => $period_start,
|
||||
'end' => $period_end
|
||||
);
|
||||
|
||||
$already_exist = in_array($empty_period,
|
||||
$available_periods_with_appointments);
|
||||
|
||||
if ($found === FALSE && $already_exist === FALSE) {
|
||||
$available_periods_with_appointments[] = $empty_period;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$available_periods_with_appointments =
|
||||
$available_periods_with_breaks;
|
||||
}
|
||||
|
||||
return $available_periods_with_appointments;
|
||||
foreach($reserved_appointments as $appointment) {
|
||||
foreach($available_periods_with_appointments as $index=>&$period){
|
||||
$a_start =
|
||||
date('H:i',strtotime($appointment['start_datetime']));
|
||||
$a_end =
|
||||
date('H:i', strtotime($appointment['end_datetime']));
|
||||
$p_start =
|
||||
date('H:i', strtotime($period['start']));
|
||||
$p_end =
|
||||
date('H:i', strtotime($period['end']));
|
||||
|
||||
if ($a_start <= $p_start && $a_end <= $p_end
|
||||
&& $a_end <= $p_start) {
|
||||
// The appointment does not belong in this time period, so
|
||||
// we will not change anything.
|
||||
} else if ($a_start <= $p_start && $a_end <= $p_end
|
||||
&& $a_end >= $p_start) {
|
||||
// The appointment starts before the period and finishes
|
||||
// somewhere inside.We will need to break this period and
|
||||
// leave the available part.
|
||||
$period['start'] = $a_end;
|
||||
} else if ($a_start >= $p_start && $a_end <= $p_start) {
|
||||
// The appointment is inside the time period, so we will
|
||||
// split the period into two new others.
|
||||
unset($available_periods_with_appointments[$index]);
|
||||
$available_periods_with_appointments[] = array(
|
||||
'start' => $p_start,
|
||||
'end' => $a_start
|
||||
);
|
||||
$available_periods_with_appointments[] = array(
|
||||
'start' => $a_end,
|
||||
'end' => $p_end
|
||||
);
|
||||
} else if ($a_start >= $p_start && $a_end >= $p_start
|
||||
&& $a_start <= $p_end) {
|
||||
// The appointment starts in the period and finishes out
|
||||
// of it. We will need to remove the time that is taken
|
||||
// from the appointment.
|
||||
$period['end'] = $a_start;
|
||||
} else if ($a_start >= $p_start && $a_end >= $p_end
|
||||
&& $a_start >= $p_end) {
|
||||
// The appointment does not belong in the period so do not
|
||||
// change anything.
|
||||
} else if ($a_start <= $p_start && $a_end >= $p_end
|
||||
&& $a_start <= $p_end) {
|
||||
// The appointment is bigger than the period, so this period
|
||||
// needs to be removed.
|
||||
unset($available_periods_with_appointments[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_values($available_periods_with_appointments);
|
||||
}
|
Binary file not shown.
BIN
rsc/misc/ebooks/listings.pdf
Normal file
BIN
rsc/misc/ebooks/listings.pdf
Normal file
Binary file not shown.
|
@ -513,92 +513,53 @@ class Appointments extends CI_Controller {
|
|||
}
|
||||
|
||||
// Break the empty periods with the reserved appointments.
|
||||
$available_periods_with_appointments = array();
|
||||
|
||||
if (count($reserved_appointments) > 0) {
|
||||
|
||||
foreach($available_periods_with_breaks as $period) {
|
||||
|
||||
foreach($reserved_appointments as $index=>$reserved) {
|
||||
$appointment_start = date('H:i', strtotime($reserved['start_datetime']));
|
||||
$appointment_end = date('H:i', strtotime($reserved['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) {
|
||||
// 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']));
|
||||
|
||||
if ($period_start < $appt_start && $period_end > $appt_end) {
|
||||
if ($appointment_start > $appt_start) {
|
||||
$appointment_start = $appt_start;
|
||||
}
|
||||
|
||||
if ($appointment_end < $appt_end) {
|
||||
$appointment_end = $appt_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Current appointment is within the current empty space. So
|
||||
// we need to break the empty space into two other spaces that
|
||||
// don't include the appointment.
|
||||
$new_period = array(
|
||||
'start' => $period_start,
|
||||
'end' => $appointment_start
|
||||
);
|
||||
|
||||
if (!in_array($new_period, $available_periods_with_appointments)) {
|
||||
$available_periods_with_appointments[] = $new_period;
|
||||
}
|
||||
|
||||
$new_period = array(
|
||||
'start' => $appointment_end,
|
||||
'end' => $period_end
|
||||
);
|
||||
|
||||
if (!in_array($new_period, $available_periods_with_appointments)) {
|
||||
$available_periods_with_appointments[] = $new_period;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Check if there are any other appointments between this
|
||||
// time space. If not, it is going to be added as it is.
|
||||
$found = FALSE;
|
||||
|
||||
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']));
|
||||
|
||||
if ($period_start < $appt_start && $period_end > $appt_end) {
|
||||
$found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// It is also necessary to check that this time period doesn't
|
||||
// already exist in the "$empty_spaces_with_appointments" array.
|
||||
$empty_period = array(
|
||||
'start' => $period_start,
|
||||
'end' => $period_end
|
||||
);
|
||||
|
||||
$already_exist = in_array($empty_period, $available_periods_with_appointments);
|
||||
|
||||
if ($found === FALSE && $already_exist === FALSE) {
|
||||
$available_periods_with_appointments[] = $empty_period;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$available_periods_with_appointments = $available_periods_with_breaks;
|
||||
|
||||
foreach($reserved_appointments as $appointment) {
|
||||
foreach($available_periods_with_appointments as $index => &$period) {
|
||||
|
||||
$a_start = date('H:i', strtotime($appointment['start_datetime']));
|
||||
$a_end = date('H:i', strtotime($appointment['end_datetime']));
|
||||
$p_start = date('H:i', strtotime($period['start']));
|
||||
$p_end = date('H:i', strtotime($period['end']));
|
||||
|
||||
if ($a_start <= $p_start && $a_end <= $p_end && $a_end <= $p_start) {
|
||||
// The appointment does not belong in this time period, so we
|
||||
// will not change anything.
|
||||
} else if ($a_start <= $p_start && $a_end <= $p_end && $a_end >= $p_start) {
|
||||
// The appointment starts before the period and finishes somewhere inside.
|
||||
// We will need to break this period and leave the available part.
|
||||
$period['start'] = $a_end;
|
||||
|
||||
} else if ($a_start >= $p_start && $a_end <= $p_start) {
|
||||
// The appointment is inside the time period, so we will split the period
|
||||
// into two new others.
|
||||
unset($available_periods_with_appointments[$index]);
|
||||
$available_periods_with_appointments[] = array(
|
||||
'start' => $p_start,
|
||||
'end' => $a_start
|
||||
);
|
||||
$available_periods_with_appointments[] = array(
|
||||
'start' => $a_end,
|
||||
'end' => $p_end
|
||||
);
|
||||
|
||||
} else if ($a_start >= $p_start && $a_end >= $p_start && $a_start <= $p_end) {
|
||||
// The appointment starts in the period and finishes out of it. We will
|
||||
// need to remove the time that is taken from the appointment.
|
||||
$period['end'] = $a_start;
|
||||
|
||||
} else if ($a_start >= $p_start && $a_end >= $p_end && $a_start >= $p_end) {
|
||||
// The appointment does not belong in the period so do not change anything.
|
||||
} else if ($a_start <= $p_start && $a_end >= $p_end && $a_start <= $p_end) {
|
||||
// The appointment is bigger than the period, so this period needs to be
|
||||
// removed.
|
||||
unset($available_periods_with_appointments[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $available_periods_with_appointments;
|
||||
return array_values($available_periods_with_appointments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -112,8 +112,7 @@ class Google extends CI_Controller {
|
|||
$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
|
||||
'id_users_provider' => $provider['id']
|
||||
);
|
||||
|
||||
$appointments = $this->appointments_model->get_batch($where_clause);
|
||||
|
@ -127,8 +126,13 @@ class Google extends CI_Controller {
|
|||
// Sync each appointment with Google Calendar by following the project's sync
|
||||
// protocol (see documentation).
|
||||
foreach($appointments as $appointment) {
|
||||
if ($appointment['is_unavailable'] == FALSE) {
|
||||
$service = $this->services_model->get_row($appointment['id_services']);
|
||||
$customer = $this->customers_model->get_row($appointment['id_users_customer']);
|
||||
} else {
|
||||
$service = NULL;
|
||||
$customer = NULL;
|
||||
}
|
||||
|
||||
// If current appointment not synced yet, add to gcal.
|
||||
if ($appointment['id_google_calendar'] == NULL) {
|
||||
|
@ -141,6 +145,10 @@ class Google extends CI_Controller {
|
|||
try {
|
||||
$google_event = $this->google_sync->get_event($appointment['id_google_calendar']);
|
||||
|
||||
if ($google_event->status == 'cancelled') {
|
||||
throw new Exception('Event is cancelled, remove the record from Easy!Appointments.');
|
||||
}
|
||||
|
||||
// If gcal event is different from e!a appointment then update e!a record.
|
||||
$is_different = FALSE;
|
||||
$appt_start = strtotime($appointment['start_datetime']);
|
||||
|
|
|
@ -108,7 +108,7 @@ class Google_Sync {
|
|||
$this->CI->load->helper('general');
|
||||
|
||||
$event = new Google_Event();
|
||||
$event->setSummary($service['name']);
|
||||
$event->setSummary(($service != NULL) ? $service['name'] : 'Unavailable');
|
||||
$event->setLocation($company_settings['company_name']);
|
||||
|
||||
$start = new Google_EventDateTime();
|
||||
|
@ -119,20 +119,21 @@ class Google_Sync {
|
|||
$end->setDateTime(date3339(strtotime($appointment['end_datetime'])));
|
||||
$event->setEnd($end);
|
||||
|
||||
$eventProvider = new Google_EventAttendee();
|
||||
$eventProvider->setDisplayName($provider['first_name'] . ' '
|
||||
$event->attendees = array();
|
||||
|
||||
$event_provider = new Google_EventAttendee();
|
||||
$event_provider->setDisplayName($provider['first_name'] . ' '
|
||||
. $provider['last_name']);
|
||||
$eventProvider->setEmail($provider['email']);
|
||||
$event_provider->setEmail($provider['email']);
|
||||
$event->attendees[] = $event_provider;
|
||||
|
||||
$eventCustomer = new Google_EventAttendee();
|
||||
$eventCustomer->setDisplayName($customer['first_name'] . ' '
|
||||
if ($customer != NULL) {
|
||||
$event_customer = new Google_EventAttendee();
|
||||
$event_customer->setDisplayName($customer['first_name'] . ' '
|
||||
. $customer['last_name']);
|
||||
$eventCustomer->setEmail($customer['email']);
|
||||
|
||||
$event->attendees = array(
|
||||
$eventProvider,
|
||||
$eventCustomer
|
||||
);
|
||||
$event_customer->setEmail($customer['email']);
|
||||
$event->attendees[] = $event_customer;
|
||||
}
|
||||
|
||||
// Add the new event to the "primary" calendar.
|
||||
$created_event = $this->service->events->insert('primary', $event);
|
||||
|
@ -171,20 +172,21 @@ class Google_Sync {
|
|||
$end->setDateTime(date3339(strtotime($appointment['end_datetime'])));
|
||||
$event->setEnd($end);
|
||||
|
||||
$event->attendees = array();
|
||||
|
||||
$event_provider = new Google_EventAttendee();
|
||||
$event_provider->setDisplayName($provider['first_name'] . ' '
|
||||
. $provider['last_name']);
|
||||
$event_provider->setEmail($provider['email']);
|
||||
$event->attendees[] = $event_provider;
|
||||
|
||||
if ($customer != NULL) {
|
||||
$event_customer = new Google_EventAttendee();
|
||||
$event_customer->setDisplayName($customer['first_name'] . ' '
|
||||
. $customer['last_name']);
|
||||
$event_customer->setEmail($customer['email']);
|
||||
|
||||
$event->attendees = array(
|
||||
$event_provider,
|
||||
$event_customer
|
||||
);
|
||||
$event->attendees[] = $event_customer;
|
||||
}
|
||||
|
||||
$updated_event = $this->service->events->update('primary', $event->getId(), $event);
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
<form id="cancel-appointment-form" method="post"
|
||||
action="' . $this->config->item('base_url')
|
||||
. 'appointments/cancel/' . $appointment_data['hash'] . '">
|
||||
<textarea name="cancel_reason" style="display:none;"></textarea>
|
||||
<textarea name="cancel_reason" style="display:none"></textarea>
|
||||
<button id="cancel-appointment" class="btn btn-inverse">
|
||||
Cancel</button>
|
||||
</form>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<div id="success-frame" class="frame-container">
|
||||
<img id="success-icon" src="<?php echo $this->config->base_url(); ?>assets/images/success.png" />
|
||||
|
||||
<h3>Your appointment has been successfully canceled!</h3>
|
||||
<h3>Your appointment has been successfully cancelled!</h3>
|
||||
|
||||
<?php
|
||||
// Display exceptions (if any).
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<div class="btn-group">
|
||||
<?php //if ($privileges[PRIV_USERS]['edit'] == TRUE) { ?>
|
||||
<?php if (($role_slug == DB_SLUG_ADMIN || $role_slug == DB_SLUG_PROVIDER)
|
||||
&& $this->config->item('ea_google_sync') == TRUE) { ?>
|
||||
&& $this->config->item('ea_google_sync_feature') == TRUE) { ?>
|
||||
<button id="google-sync" class="btn btn-primary"
|
||||
title="Trigger the Google Calendar synchronization process.">
|
||||
<i class="icon-refresh icon-white"></i>
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
|
||||
<div id="save-cancel-group" class="btn-group" style="display:none;">
|
||||
<button id="save-customer" class="btn btn-primary">
|
||||
<i class="icon-ok"></i>
|
||||
<i class="icon-ok icon-white"></i>
|
||||
Save</button>
|
||||
<button id="cancel-customer" class="btn">
|
||||
<i class="icon-ban-circle"></i>
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
|
||||
<div class="save-cancel-group btn-group" style="display:none;">
|
||||
<button id="save-service" class="btn btn-primary">
|
||||
<i class="icon-ok"></i>
|
||||
<i class="icon-ok icon-white"></i>
|
||||
Save</button>
|
||||
<button id="cancel-service" class="btn">
|
||||
<i class="icon-ban-circle"></i>
|
||||
|
@ -144,7 +144,7 @@
|
|||
|
||||
<div class="save-cancel-group btn-group" style="display:none;">
|
||||
<button id="save-category" class="btn btn-primary">
|
||||
<i class="icon-ok"></i>
|
||||
<i class="icon-ok icon-white"></i>
|
||||
Save</button>
|
||||
<button id="cancel-category" class="btn">
|
||||
<i class="icon-ban-circle"></i>
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
|
||||
<div class="save-cancel-group btn-group" style="display:none;">
|
||||
<button id="save-admin" class="btn btn-primary">
|
||||
<i class="icon-ok"></i>
|
||||
<i class="icon-ok icon-white"></i>
|
||||
Save</button>
|
||||
<button id="cancel-admin" class="btn">
|
||||
<i class="icon-ban-circle"></i>
|
||||
|
@ -201,7 +201,7 @@
|
|||
|
||||
<div class="save-cancel-group btn-group" style="display:none;">
|
||||
<button id="save-provider" class="btn btn-primary">
|
||||
<i class="icon-ok"></i>
|
||||
<i class="icon-ok icon-white"></i>
|
||||
Save</button>
|
||||
<button id="cancel-provider" class="btn">
|
||||
<i class="icon-ban-circle"></i>
|
||||
|
@ -409,7 +409,7 @@
|
|||
|
||||
<div class="save-cancel-group btn-group" style="display:none;">
|
||||
<button id="save-secretary" class="btn btn-primary">
|
||||
<i class="icon-ok"></i>
|
||||
<i class="icon-ok icon-white"></i>
|
||||
Save</button>
|
||||
<button id="cancel-secretary" class="btn">
|
||||
<i class="icon-ban-circle"></i>
|
||||
|
|
|
@ -195,7 +195,7 @@
|
|||
}
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
|
|
|
@ -11,7 +11,7 @@ root {
|
|||
#header {
|
||||
height: 70px;
|
||||
background-color: #35B66F;
|
||||
border-bottom: 6px solid #247A4B;
|
||||
border-bottom: 4px solid #247A4B;
|
||||
}
|
||||
|
||||
#header #header-logo {
|
||||
|
@ -96,7 +96,7 @@ root {
|
|||
}
|
||||
|
||||
#loading {
|
||||
position: absolute;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
|
@ -178,14 +178,19 @@ body .jspTrack {
|
|||
|
||||
#calendar-page #calendar .fc-unavailable {
|
||||
background-image: url('../images/unavailable.jpg');
|
||||
font-size: 24px;
|
||||
font-size: 17px;
|
||||
border-radius: 0;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-shadow: 0px 1px 0px #FFF;
|
||||
text-shadow: 0px 1px 0px #E6E6E6;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
#calendar-page #calendar .fc-event-title small {
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#calendar-page #calendar .fc-break {
|
||||
background-image: url('../images/break.jpg');
|
||||
}
|
||||
|
|
|
@ -52,7 +52,10 @@ var BackendCalendar = {
|
|||
'dayClick': BackendCalendar.calendarDayClick,
|
||||
'eventClick': BackendCalendar.calendarEventClick,
|
||||
'eventResize': BackendCalendar.calendarEventResize,
|
||||
'eventDrop': BackendCalendar.calendarEventDrop
|
||||
'eventDrop': BackendCalendar.calendarEventDrop,
|
||||
'eventAfterAllRender': function(view) {
|
||||
BackendCalendar.convertTitlesToHtml();
|
||||
}
|
||||
});
|
||||
|
||||
// Temporary fix: make the first letter capital in all the lowercase strings
|
||||
|
@ -264,7 +267,7 @@ var BackendCalendar = {
|
|||
|
||||
if (response.warnings) {
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -396,7 +399,7 @@ var BackendCalendar = {
|
|||
|
||||
if (response.warnings) {
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -437,7 +440,7 @@ var BackendCalendar = {
|
|||
|
||||
if (response.warnings) {
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -527,6 +530,7 @@ var BackendCalendar = {
|
|||
$dialog.find('.modal-message').text('Appointment saved successfully!');
|
||||
$dialog.find('.modal-message').addClass('alert-success').removeClass('alert-error');
|
||||
$dialog.find('.modal-message').fadeIn();
|
||||
$dialog.find('.modal-body').scrollTop(0);
|
||||
|
||||
// Close the modal dialog and refresh the calendar appointments
|
||||
// after one second.
|
||||
|
@ -542,6 +546,7 @@ var BackendCalendar = {
|
|||
$dialog.find('.modal-message').text('A server communication error occured, please try again.');
|
||||
$dialog.find('.modal-message').addClass('alert-error');
|
||||
$dialog.find('.modal-message').fadeIn();
|
||||
$dialog.find('.modal-body').scrollTop(0);
|
||||
};
|
||||
|
||||
// :: CALL THE UPDATE APPOINTMENT METHOD
|
||||
|
@ -600,7 +605,7 @@ var BackendCalendar = {
|
|||
|
||||
if (response.warnings) {
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -913,7 +918,7 @@ var BackendCalendar = {
|
|||
|
||||
if (calendarDateStart < workDateStart) {
|
||||
unavailablePeriod = {
|
||||
'title': 'Unavailable',
|
||||
'title': 'Not Working',
|
||||
'start': calendarDateStart,
|
||||
'end': workDateStart,
|
||||
'allDay': false,
|
||||
|
@ -932,7 +937,7 @@ var BackendCalendar = {
|
|||
'dd/MM/yyyy HH:mm'); // Use calendarDateStart ***
|
||||
if (calendarDateEnd > workDateEnd) {
|
||||
var unavailablePeriod = {
|
||||
'title': 'Unavailable',
|
||||
'title': 'Not Working',
|
||||
'start': workDateEnd,
|
||||
'end': calendarDateEnd,
|
||||
'allDay': false,
|
||||
|
@ -965,7 +970,9 @@ var BackendCalendar = {
|
|||
// Add custom unavailable periods.
|
||||
$.each(response.unavailables, function(index, unavailable) {
|
||||
var unavailablePeriod = {
|
||||
'title': 'Unavailable',
|
||||
'title': 'Unavailable <br><small>' + ((unavailable.notes.length > 30)
|
||||
? unavailable.notes.substring(0, 30) + '...'
|
||||
: unavailable.notes) + '</small>',
|
||||
'start': Date.parse(unavailable.start_datetime),
|
||||
'end': Date.parse(unavailable.end_datetime),
|
||||
'allDay': false,
|
||||
|
@ -991,7 +998,9 @@ var BackendCalendar = {
|
|||
if (currDateStart.toString('dd/MM/yyyy')
|
||||
=== Date.parse(unavailable.start_datetime).toString('dd/MM/yyyy')) {
|
||||
var unavailablePeriod = {
|
||||
'title': 'Unavailable',
|
||||
'title': 'Unavailable <br><small>' + ((unavailable.notes.length > 30)
|
||||
? unavailable.notes.substring(0, 30) + '...'
|
||||
: unavailable.notes) + '</small>',
|
||||
'start': Date.parse(unavailable.start_datetime),
|
||||
'end': Date.parse(unavailable.end_datetime),
|
||||
'allDay': false,
|
||||
|
@ -1004,7 +1013,6 @@ var BackendCalendar = {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
if (workingDay == null) {
|
||||
// Add a full day unavailable event.
|
||||
unavailablePeriod = {
|
||||
|
@ -1029,7 +1037,7 @@ var BackendCalendar = {
|
|||
+ ' ' + workingDay.start, 'dd/MM/yyyy HH:mm');
|
||||
if (currDateStart < start) {
|
||||
unavailablePeriod = {
|
||||
'title': 'Unavailable',
|
||||
'title': 'Not Working',
|
||||
'start': GeneralFunctions.clone(currDateStart),
|
||||
'end': GeneralFunctions.clone(start),
|
||||
'allDay': false,
|
||||
|
@ -1045,7 +1053,7 @@ var BackendCalendar = {
|
|||
+ ' ' + workingDay.end, 'dd/MM/yyyy HH:mm');
|
||||
if (currDateEnd > end) {
|
||||
unavailablePeriod = {
|
||||
'title': 'Unavailable',
|
||||
'title': 'Not Working',
|
||||
'start': GeneralFunctions.clone(end),
|
||||
'end': GeneralFunctions.clone(currDateEnd),
|
||||
'allDay': false,
|
||||
|
@ -1082,6 +1090,8 @@ var BackendCalendar = {
|
|||
}
|
||||
}
|
||||
});
|
||||
// Convert the titles to html code.
|
||||
//BackendCalendar.convertTitlesToHtml();
|
||||
}
|
||||
}, 'json');
|
||||
},
|
||||
|
@ -1209,7 +1219,7 @@ var BackendCalendar = {
|
|||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1272,7 @@ var BackendCalendar = {
|
|||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -1307,6 +1317,7 @@ var BackendCalendar = {
|
|||
calendarWindowResize: function(view) {
|
||||
$('#calendar').fullCalendar('option', 'height',
|
||||
BackendCalendar.getCalendarHeight());
|
||||
//BackendCalendar.convertTitlesToHtml();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1476,7 +1487,7 @@ var BackendCalendar = {
|
|||
if (response.warnings) {
|
||||
// Display warning information to the user.
|
||||
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -1539,7 +1550,7 @@ var BackendCalendar = {
|
|||
|
||||
if (response.warnings) {
|
||||
reponse.warnings = GeneralFunctions.parseExceptions(response.warnings);
|
||||
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
|
||||
GeneralFunctions.displayMessageBox(GeneralFunctions.WARNINGS_TITLE, GeneralFunctions.WARNINGS_MESSAGE);
|
||||
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
|
||||
}
|
||||
|
||||
|
@ -1598,8 +1609,17 @@ var BackendCalendar = {
|
|||
$('#select-filter-item option:selected').attr('type'),
|
||||
$('#calendar').fullCalendar('getView').visStart,
|
||||
$('#calendar').fullCalendar('getView').visEnd);
|
||||
$(window).trigger('resize');
|
||||
$(window).trigger('resize'); // Places the footer on the bottom.
|
||||
|
||||
// Change string from "all-day" to "All Day".
|
||||
$('#calendar .fc-agenda-allday .fc-agenda-axis').text('All Day');
|
||||
|
||||
// Remove all open popovers.
|
||||
$('.close-popover').each(function() {
|
||||
$(this).parents().eq(2).remove();
|
||||
});
|
||||
|
||||
// Add new pop overs.
|
||||
$('.fv-events').each(function(index, eventHandle) {
|
||||
$(eventHandle).popover();
|
||||
});
|
||||
|
@ -1759,5 +1779,20 @@ var BackendCalendar = {
|
|||
|
||||
// Clear the unavailable notes field.
|
||||
$dialog.find('#unavailable-notes').val('');
|
||||
},
|
||||
|
||||
/**
|
||||
* On some calendar events the titles contain html markup that is not
|
||||
* displayed properly due to the fullcalendar plugin. This plugin sets
|
||||
* the .fc-event-title value by using the $.text() method and not the
|
||||
* $.html() method. So in order for the title to display the html properly
|
||||
* we convert all the .fc-event-titles where needed into html.
|
||||
*/
|
||||
convertTitlesToHtml: function() {
|
||||
// Convert the titles to html code.
|
||||
$('.fc-custom').each(function() {
|
||||
var title = $(this).find('.fc-event-title').text();
|
||||
$(this).find('.fc-event-title').html(title);
|
||||
});
|
||||
}
|
||||
};
|
|
@ -397,13 +397,17 @@ CustomersHelper.prototype.filter = function(key, selectId, display) {
|
|||
* @return {string} Returns the record html code.
|
||||
*/
|
||||
CustomersHelper.prototype.getFilterHtml = function(customer) {
|
||||
var name = customer.first_name + ' ' + customer.last_name;
|
||||
var info = customer.email;
|
||||
info = (customer.phone_number != '' && customer.phone_number != null)
|
||||
? info + ', ' + customer.phone_number : info;
|
||||
|
||||
var html =
|
||||
'<div class="customer-row" data-id="' + customer.id + '">' +
|
||||
'<strong>' +
|
||||
customer.first_name + ' ' + customer.last_name +
|
||||
name +
|
||||
'</strong><br>' +
|
||||
'<span>' + customer.email + '</span> | ' +
|
||||
'<span>' + customer.phone_number + '</span>' +
|
||||
info +
|
||||
'</div><hr>';
|
||||
|
||||
return html;
|
||||
|
|
|
@ -214,8 +214,8 @@ var FrontendBook = {
|
|||
+ 'minute to write the reason you are cancelling the appointment:',
|
||||
dialogButtons);
|
||||
|
||||
$('#message_box').append('<textarea id="cancel-reason"></textarea>');
|
||||
$('#cancel-reason').css('width', '300px');
|
||||
$('#message_box').append('<textarea id="cancel-reason" rows="3"></textarea>');
|
||||
$('#cancel-reason').css('width', '353px');
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -553,11 +553,15 @@ var FrontendBook = {
|
|||
html = '<strong>' + service.name + '</strong>';
|
||||
|
||||
if (service.description != '' && service.description != null) {
|
||||
html += '<br>' + service.description;
|
||||
html += '<br>' + service.description + '<br>';
|
||||
}
|
||||
|
||||
if (service.duration != '' && service.duration != null) {
|
||||
html += '[Duration ' + service.duration + ' Minutes] ';
|
||||
}
|
||||
|
||||
if (service.price != '' && service.price != null) {
|
||||
html += '<br> [Price ' + service.price + ' ' + service.currency + ']';
|
||||
html += '[Price ' + service.price + ' ' + service.currency + ']';
|
||||
}
|
||||
|
||||
html += '<br>';
|
||||
|
|
|
@ -10,7 +10,7 @@ class SystemConfiguration {
|
|||
public static $db_password = '';
|
||||
|
||||
// Google Calendar API Settings
|
||||
public static $google_sync_feature = FALSE; // Enter TRUE or FALSE;
|
||||
public static $google_sync_feature = TRUE; // Enter TRUE or FALSE;
|
||||
public static $google_product_name = 'Easy!Appointments';
|
||||
public static $google_client_id = '396094740598-l9ohhdgs0hr6qi89628p3chf9lm59mkc.apps.googleusercontent.com';
|
||||
public static $google_client_secret = '3kKEgx3mgxfFInrWf3jTUn4D';
|
||||
|
|
Loading…
Reference in a new issue