Merge branch 'develop'

This commit is contained in:
Alex Tselegidis 2015-11-23 23:58:00 +01:00
commit db44e44d3a
35 changed files with 627 additions and 569 deletions

View file

@ -33,7 +33,7 @@ perform the following steps in order to install the system on your server:
* Make sure that your server has Apache, PHP and MySQL installed.
* Create a new database (or use an existing).
* Copy the "easyappointments" source folder on your server.
* Edit the "configuration.php" file and set your server properties.
* Rename the "config-sample.php" file to "config.php" and set your server properties.
* Open your browser on the Easy!Appointments URL and follow the installation guide.
* That's it! You can now use Easy!Appointments at your will.

View file

@ -21,7 +21,8 @@ INSERT INTO `ea_settings` (`id`, `name`, `value`) VALUES
(2, 'book_advance_timeout', '30'),
(3, 'company_name', 'ABC Company'),
(4, 'company_email', 'info@abc-company.ea'),
(5, 'company_link', 'http://www.abc-company.ea');
(5, 'company_link', 'http://www.abc-company.ea'),
(6, 'google_analytics_code', '');
--
-- Dumping data for table `ea_roles`

View file

@ -216,6 +216,40 @@ class Appointments extends CI_Controller {
$this->load->view('appointments/message', $view);
}
/**
* GET an specific appointment book and redirect to the success screen.
*
* @param int $appointment_id Contains the id of the appointment to retrieve.
*/
public function book_success($appointment_id) {
//if the appointment id doesn't exist or zero redirect to index
if(!$appointment_id){
redirect('appointments');
}
$this->load->model('appointments_model');
$this->load->model('providers_model');
$this->load->model('services_model');
$this->load->model('settings_model');
//retrieve the data needed in the view
$appointment = $this->appointments_model->get_row($appointment_id);
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
$service = $this->services_model->get_row($appointment['id_services']);
$company_name = $this->settings_model->get_setting('company_name');
//get the exceptions
$exceptions = $this->session->flashdata('book_success');
// :: LOAD THE BOOK SUCCESS VIEW
$view = array(
'appointment_data' => $appointment,
'provider_data' => $provider,
'service_data' => $service,
'company_name' => $company_name,
);
if($exceptions){
$view['exceptions'] = $exceptions;
}
$this->load->view('appointments/book_success', $view);
}
/**
* [AJAX] Get the available appointment hours for the given date.
*
@ -316,223 +350,6 @@ class Appointments extends CI_Controller {
}
}
/**
* Check whether the provider is still available in the selected appointment date.
*
* It might be times where two or more customers select the same appointment date and time.
* This shouldn't be allowed to happen, so one of the two customers will eventually get the
* prefered date and the other one will have to choose for another date. Use this method
* just before the customer confirms the appointment details. If the selected date was taken
* in the mean time, the customer must be prompted to select another time for his appointment.
*
* @param int $_POST['id_users_provider'] The selected provider's record id.
* @param int $_POST['id_services'] The selected service's record id.
* @param string $_POST['start_datetime'] This is a mysql formed string.
* @return bool Returns whether the selected datetime is still available.
*/
public function ajax_check_datetime_availability() {
try {
$this->load->model('services_model');
$service_duration = $this->services_model->get_value('duration', $_POST['id_services']);
$exclude_appointments = (isset($_POST['exclude_appointment_id']))
? array($_POST['exclude_appointment_id']) : array();
$available_periods = $this->get_provider_available_time_periods(
$_POST['id_users_provider'], $_POST['start_datetime'], $exclude_appointments);
$is_still_available = FALSE;
foreach($available_periods as $period) {
$appt_start = new DateTime($_POST['start_datetime']);
$appt_start = $appt_start->format('H:i');
$appt_end = new DateTime($_POST['start_datetime']);
$appt_end->add(new DateInterval('PT' . $service_duration . 'M'));
$appt_end = $appt_end->format('H:i');
$period_start = date('H:i', strtotime($period['start']));
$period_end = date('H:i', strtotime($period['end']));
if ($period_start <= $appt_start && $period_end >= $appt_end) {
$is_still_available = TRUE;
break;
}
}
echo json_encode($is_still_available);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavaScript($exc))
));
}
}
/**
* Get an array containing the free time periods (start - end) of a selected date.
*
* This method is very important because there are many cases where the system needs to
* know when a provider is avaible for an appointment. This method will return an array
* that belongs to the selected date and contains values that have the start and the end
* time of an available time period.
*
* @param numeric $provider_id The provider's record id.
* @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.
* @return array Returns an array with the available time periods of the provider.
*/
private function get_provider_available_time_periods($provider_id, $selected_date,
$exclude_appointments = array()) {
$this->load->model('appointments_model');
$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);
$where_clause = array(
//'DATE(start_datetime)' => date('Y-m-d', strtotime($selected_date)),
'id_users_provider' => $provider_id
);
$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' available time periods would be without them.
foreach ($exclude_appointments as $excluded_id) {
foreach ($reserved_appointments as $index => $reserved) {
if ($reserved['id'] == $excluded_id) {
unset($reserved_appointments[$index]);
}
}
}
// 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();
if (isset($selected_date_working_plan['breaks'])) {
if (count($selected_date_working_plan['breaks'])) {
foreach($selected_date_working_plan['breaks'] as $index=>$break) {
// Split the working plan to available time periods that do not
// contain the breaks in them.
$last_break_index = $index - 1;
if (count($available_periods_with_breaks) === 0) {
$start_hour = $selected_date_working_plan['start'];
$end_hour = $break['start'];
} else {
$start_hour = $selected_date_working_plan['breaks'][$last_break_index]['end'];
$end_hour = $break['start'];
}
$available_periods_with_breaks[] = array(
'start' => $start_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']
);
} else {
$available_periods_with_breaks[] = array(
'start' => $selected_date_working_plan['start'],
'end' => $selected_date_working_plan['end']
);
}
}
// Break the empty periods with the reserved appointments.
$available_periods_with_appointments = $available_periods_with_breaks;
foreach($reserved_appointments as $appointment) {
foreach($available_periods_with_appointments as $index => &$period) {
$a_start = strtotime($appointment['start_datetime']);
$a_end = strtotime($appointment['end_datetime']);
$p_start = strtotime($selected_date . ' ' . $period['start']);
$p_end = strtotime($selected_date . ' ' .$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'] = date('H:i', $a_end);
} else if ($a_start >= $p_start && $a_end <= $p_end) {
// 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' => date('H:i', $p_start),
'end' => date('H:i', $a_start)
);
$available_periods_with_appointments[] = array(
'start' => date('H:i', $a_end),
'end' => date('H:i', $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'] = date('H:i', $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);
}
/**
* GET an specific appointment book and redirect to the success screen.
*
* @param int $appointment_id Contains the id of the appointment to retrieve.
*/
public function book_success($appointment_id) {
//if the appointment id doesn't exist or zero redirect to index
if(!$appointment_id){
redirect('appointments');
}
$this->load->model('appointments_model');
$this->load->model('providers_model');
$this->load->model('services_model');
$this->load->model('settings_model');
//retrieve the data needed in the view
$appointment = $this->appointments_model->get_row($appointment_id);
$provider = $this->providers_model->get_row($appointment['id_users_provider']);
$service = $this->services_model->get_row($appointment['id_services']);
$company_name = $this->settings_model->get_setting('company_name');
//get the exceptions
$exceptions = $this->session->flashdata('book_success');
// :: LOAD THE BOOK SUCCESS VIEW
$view = array(
'appointment_data' => $appointment,
'provider_data' => $provider,
'service_data' => $service,
'company_name' => $company_name,
);
if($exceptions){
$view['exceptions'] = $exceptions;
}
$this->load->view('appointments/book_success', $view);
}
/**
* [AJAX] Register the appointment to the database.
*/
@ -546,6 +363,11 @@ class Appointments extends CI_Controller {
throw new Exception($this->lang->line('captcha_is_wrong'));
}
// Check appointment availability.
if (!$this->check_datetime_availability()) {
throw new Exception($this->lang->line('requested_hour_is_unavailable'));
}
$appointment = $post_data['appointment'];
$customer = $post_data['customer'];
@ -660,6 +482,183 @@ class Appointments extends CI_Controller {
));
}
}
/**
* Check whether the provider is still available in the selected appointment date.
*
* It might be times where two or more customers select the same appointment date and time.
* This shouldn't be allowed to happen, so one of the two customers will eventually get the
* prefered date and the other one will have to choose for another date. Use this method
* just before the customer confirms the appointment details. If the selected date was taken
* in the mean time, the customer must be prompted to select another time for his appointment.
*
* @return bool Returns whether the selected datetime is still available.
*/
private function check_datetime_availability() {
$this->load->model('services_model');
$appointment = $_POST['post_data']['appointment'];
$service_duration = $this->services_model->get_value('duration', $appointment['id_services']);
$exclude_appointments = (isset($appointment['appointment_id']))
? array($appointment['appointment_id']) : array();
$available_periods = $this->get_provider_available_time_periods(
$appointment['id_users_provider'], date('Y-m-d', strtotime($appointment['start_datetime'])),
$exclude_appointments);
$is_still_available = FALSE;
foreach($available_periods as $period) {
$appt_start = new DateTime($appointment['start_datetime']);
$appt_start = $appt_start->format('H:i');
$appt_end = new DateTime($appointment['start_datetime']);
$appt_end->add(new DateInterval('PT' . $service_duration . 'M'));
$appt_end = $appt_end->format('H:i');
$period_start = date('H:i', strtotime($period['start']));
$period_end = date('H:i', strtotime($period['end']));
if ($period_start <= $appt_start && $period_end >= $appt_end) {
$is_still_available = TRUE;
break;
}
}
return $is_still_available;
}
/**
* Get an array containing the free time periods (start - end) of a selected date.
*
* This method is very important because there are many cases where the system needs to
* know when a provider is avaible for an appointment. This method will return an array
* that belongs to the selected date and contains values that have the start and the end
* time of an available time period.
*
* @param numeric $provider_id The provider's record id.
* @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.
* @return array Returns an array with the available time periods of the provider.
*/
private function get_provider_available_time_periods($provider_id, $selected_date,
$exclude_appointments = array()) {
$this->load->model('appointments_model');
$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);
$where_clause = array(
'DATE(start_datetime)' => date('Y-m-d', strtotime($selected_date)),
'id_users_provider' => $provider_id
);
$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' available time periods would be without them.
foreach ($exclude_appointments as $excluded_id) {
foreach ($reserved_appointments as $index => $reserved) {
if ($reserved['id'] == $excluded_id) {
unset($reserved_appointments[$index]);
}
}
}
// 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();
if (isset($selected_date_working_plan['breaks'])) {
if (count($selected_date_working_plan['breaks'])) {
foreach($selected_date_working_plan['breaks'] as $index=>$break) {
// Split the working plan to available time periods that do not
// contain the breaks in them.
$last_break_index = $index - 1;
if (count($available_periods_with_breaks) === 0) {
$start_hour = $selected_date_working_plan['start'];
$end_hour = $break['start'];
} else {
$start_hour = $selected_date_working_plan['breaks'][$last_break_index]['end'];
$end_hour = $break['start'];
}
$available_periods_with_breaks[] = array(
'start' => $start_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']
);
} else {
$available_periods_with_breaks[] = array(
'start' => $selected_date_working_plan['start'],
'end' => $selected_date_working_plan['end']
);
}
}
// Break the empty periods with the reserved appointments.
$available_periods_with_appointments = $available_periods_with_breaks;
foreach($reserved_appointments as $appointment) {
foreach($available_periods_with_appointments as $index => &$period) {
$a_start = strtotime($appointment['start_datetime']);
$a_end = strtotime($appointment['end_datetime']);
$p_start = strtotime($selected_date . ' ' . $period['start']);
$p_end = strtotime($selected_date . ' ' .$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'] = date('H:i', $a_end);
} else if ($a_start >= $p_start && $a_end <= $p_end) {
// 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' => date('H:i', $p_start),
'end' => date('H:i', $a_start)
);
$available_periods_with_appointments[] = array(
'start' => date('H:i', $a_end),
'end' => date('H:i', $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'] = date('H:i', $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);
}
}
/* End of file appointments.php */

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,15 @@ class Installation extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->helper('installation');
$this->load->library('session');
// Set user's selected language.
if ($this->session->userdata('language')) {
$this->config->set_item('language', $this->session->userdata('language'));
$this->lang->load('translations', $this->session->userdata('language'));
} else {
$this->lang->load('translations', $this->config->item('language')); // default
}
}
@ -57,7 +66,15 @@ class Installation extends CI_Controller {
}
// Create E!A database structure.
$file_contents = file_get_contents(BASEPATH . 'assets/sql/structure.sql');
$file_contents = file_get_contents(dirname(BASEPATH) . '/assets/sql/structure.sql');
$sql_queries = explode(';', $file_contents);
array_pop($sql_queries);
foreach($sql_queries as $query) {
$this->db->query($query);
}
// Insert default E!A entries into the database.
$file_contents = file_get_contents(dirname(BASEPATH) . '/assets/sql/data.sql');
$sql_queries = explode(';', $file_contents);
array_pop($sql_queries);
foreach($sql_queries as $query) {
@ -93,9 +110,6 @@ class Installation extends CI_Controller {
));
}
}
}
/* End of file installation.php */

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = '不好!出了一些问题!';
$lang['could_not_add_to_google_calendar'] = '您的预约不能添加到谷歌日历.';
$lang['ea_update_success'] = '预约系统已经成功更新!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Noget gik galt!';
$lang['could_not_add_to_google_calendar'] = 'Din tid kunne ikke tilføjes din Google kalender konto';
$lang['ea_update_success'] = 'Easy!Appointments er blevet opdateret.';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] ='Oeps! Er is iets misgegaan!';
$lang['could_not_add_to_google_calendar'] ='Uw afspraak kon niet toegevoegd worden aan het Google Agenda-account.';
$lang['ea_update_success'] ='Easy!Appointments is succesvol bijgewerkt!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Something Went Wrong!';
$lang['could_not_add_to_google_calendar'] = 'Your appointment could not be added to your Google Calendar account.';
$lang['ea_update_success'] = 'Easy!Appointments has been successfully updated!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Oho! Jotain meni pieleen!';
$lang['could_not_add_to_google_calendar'] = 'Varaustasi ei pystytty lisäämään Google-kalenteri tiliisi.';
$lang['ea_update_success'] = 'Easy!Appointments päivitettiin onnistuneesti!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Une erreur s\'est produite !';
$lang['could_not_add_to_google_calendar'] = 'Votre rendez-vous ne peux pas être ajoutée à votre compte calendrier Google.';
$lang['ea_update_success'] = 'Easy!Appointments à été mis à jour avec succès !';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Etwas ist schiefgelaufen!';
$lang['could_not_add_to_google_calendar'] = 'Ihr Termin konnte nicht in den Google-Kalender-Konto hinzugefügt werden.';
$lang['ea_update_success'] = 'Easy!Appointments wurde erfolgreich aktualisiert!';
$lang['captcha_is_wrong'] = 'CAPTCHA Überprüfung fehlgeschlagen, bitte versuchen Sie es wieder.';
$lang['any_provider'] = 'Jeder Anbieter';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Ώχ! Κάτι πήγε στραβά!';
$lang['could_not_add_to_google_calendar'] = 'Το ραντεβού σας δεν μπόρεσε να προστεθεί στον λογαριασμό σας στο Google Calendar.';
$lang['ea_update_success'] = 'Το Easy!Appointments ενημερώθηκε με επιτυχία!';
$lang['captcha_is_wrong'] = 'Η επαλήθευση του CAPTCHA απέτυχε, παρακαλώ δοκιμάστε πάλι.';
$lang['any_provider'] = 'Οποιοσδήποτε Πάροχος';
$lang['requested_hour_is_unavailable'] = 'Το απαιτούμενο ραντεβού δεν είναι δυστυχώς διαθέσιμο. Παρακαλώ επιλέξτε κάποια άλλη ώρα για το ραντεβού σας.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Hoppá! Valami balul sült el!';
$lang['could_not_add_to_google_calendar'] = 'Az időpontot nem tudtuk hozzá adni a Google naptáradhoz.';
$lang['ea_update_success'] = 'Foglalj időpontot a ...';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -271,3 +271,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Qualcosa è andato storto!';
$lang['could_not_add_to_google_calendar'] = 'Il tuo appuntamento potrebbe non essere stato aggiunto al tuo account Google Calendar.';
$lang['ea_update_success'] = 'Easy!Appointments è stato aggiornato con successo!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'おっと、なにか が うまく 行っ
$lang['could_not_add_to_google_calendar'] = 'あなたの予約をGoogleカレンダーに 追加することができませんでした。';
$lang['ea_update_success'] = 'Easy!Appointments の アップデートが成功しました。';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Et ass eppes schif gaang!';
$lang['could_not_add_to_google_calendar'] = 'Ären Termäin konnt nët am Google Kalenner bäigesat ginn.';
$lang['ea_update_success'] = 'Easy!Appointments gouf erfollegräich aktualiséiert!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Ojj! Coś poszło nie tak!';
$lang['could_not_add_to_google_calendar'] = 'Nie można dodać wizyty do Twojego Kalendarza Google';
$lang['ea_update_success'] = 'Easy!Appointment zaktualizowany pomyślnie';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Ops! Algo deu errado!';
$lang['could_not_add_to_google_calendar'] = 'Não foi possível adicionar à sua conta do Google Calendar.';
$lang['ea_update_success'] = 'Easy!Appointments foi atualizado com sucesso!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Ops! Algo deu errado!';
$lang['could_not_add_to_google_calendar'] = 'Sua nomeação não pode ser adicionado à sua conta do Google Calendar.';
$lang['ea_update_success'] = 'Nomeações fáceis! Foi atualizado com sucesso!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -271,3 +271,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Ceva nu a funtionat corect!';
$lang['could_not_add_to_google_calendar'] = 'Întâlnirea nu a putut fi adaugata în Calendarul Google.';
$lang['ea_update_success'] = 'Easy!Appointments a fost actualizat!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Сорри! Возникла неопре
$lang['could_not_add_to_google_calendar'] = 'Ваше событие не было добавлено в указанный Google-календарь.';
$lang['ea_update_success'] = 'Готово! Успешно обновлено!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Úups! Niečo sa pokazilo!';
$lang['could_not_add_to_google_calendar'] = 'Vaše rezervácie nemoholi byť pridané do vášho účtu služby Google Kalendár.';
$lang['ea_update_success'] = 'Easy!Appointments bolo úspešne aktualizované!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] ='&#161Ups! &#161Algo ha salido mal!';
$lang['could_not_add_to_google_calendar'] = 'No se ha podido agregar el turno a su cuenta de Google Calendar.';
$lang['ea_update_success'] = 'Easy!Appointments ha sido actualizado exitosamente';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -265,3 +265,5 @@ $lang['oops_something_went_wrong'] = 'Oops! Bir Sorun Oluştu!';
$lang['could_not_add_to_google_calendar'] = 'Randevunuz Google Takvim hesabınıza eklenemedi.';
$lang['ea_update_success'] = 'Easy!Appointments başarı ile güncellendi!';
$lang['captcha_is_wrong'] = 'CAPTCHA verification failed, please try again.';
$lang['any_provider'] = 'Any Provider';
$lang['requested_hour_is_unavailable'] = 'The requested appointment is unfornately not available. Please select a different hour for your appointment.';

View file

@ -406,6 +406,12 @@
<span id="select-language" class="label label-success">
<?php echo ucfirst($this->config->item('language')); ?>
</span>
|
<?php if ($this->session->userdata('user_id')): ?>
<a href="<?php echo $this->config->item('base_url'); ?>/index.php/backend">
<?php echo $this->lang->line('backend_section'); ?>
</a>
<?php endif; ?>
</div>
</div>
</div>
@ -421,7 +427,6 @@
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '<?php echo $google_analytics_code; ?>', 'auto');
ga('send', 'pageview');
</script>

View file

@ -1,31 +1,35 @@
<div id="footer">
<div id="footer-content">
Powered by
<a href="http://easyappointments.org">Easy!Appointments
<?php
echo 'v' . $this->config->item('ea_version');
$release_title = $this->config->item('ea_release_title');
if ($release_title != '') {
echo ' - ' . $release_title;
}
?></a> |
<?php echo $this->lang->line('licensed_under'); ?> GPLv3 |
<span id="select-language" class="label label-success">
<?php echo ucfirst($this->config->item('language')); ?>
</span>
</div>
<div id="footer-user-display-name">
<?php echo $this->lang->line('hello') . ', ' . $user_display_name; ?>!
</div>
</div>
<script
type="text/javascript"
src="<?php echo $base_url; ?>/assets/js/backend.js"></script>
<script
type="text/javascript"
src="<?php echo $base_url; ?>/assets/js/general_functions.js"></script>
</body>
</html>
<div id="footer">
<div id="footer-content">
Powered by
<a href="http://easyappointments.org">Easy!Appointments
<?php
echo 'v' . $this->config->item('ea_version');
$release_title = $this->config->item('ea_release_title');
if ($release_title != '') {
echo ' - ' . $release_title;
}
?></a> |
<?php echo $this->lang->line('licensed_under'); ?> GPLv3 |
<span id="select-language" class="label label-success">
<?php echo ucfirst($this->config->item('language')); ?>
</span>
|
<a href="<?php echo $base_url; ?>/index.php/appointments">
<?php echo $this->lang->line('go_to_booking_page') ?>
</a>
</div>
<div id="footer-user-display-name">
<?php echo $this->lang->line('hello') . ', ' . $user_display_name; ?>!
</div>
</div>
<script
type="text/javascript"
src="<?php echo $base_url; ?>/assets/js/backend.js"></script>
<script
type="text/javascript"
src="<?php echo $base_url; ?>/assets/js/general_functions.js"></script>
</body>
</html>

View file

@ -13,6 +13,9 @@
<link rel="stylesheet" type="text/css"
href="<?php echo $this->config->item('base_url'); ?>/assets/ext/jquery-ui/jquery-ui.min.css">
<link rel="stylesheet" type="text/css"
href="<?php echo $base_url; ?>/assets/css/general.css">
<style>
header {
background: #DAFFEB;

View file

@ -55,13 +55,13 @@ root {
#header #header-menu .menu-item {
float: left;
padding: 18px 18px 19px;
min-width: 100px;
min-width: 130px;
text-align: center;
font-weight: bold;
color: #FFF;
text-decoration: none;
font-size: 16px;
transition: none;
transition: background-color 0.2s;
}
#header #header-menu .menu-item:hover:not(.active) {

View file

@ -187,6 +187,15 @@ body {
margin-top: 7px;
}
#book-appointment-wizard .captcha-title .glyphicon-refresh {
cursor: pointer;
transition: all 0.3s linear;
}
#book-appointment-wizard .captcha-title .glyphicon-refresh:hover {
color: #1A865F;
}
#book-appointment-wizard .captcha-image {
float: right;
margin-bottom: 20px;
@ -353,6 +362,11 @@ body {
float: none !important;
}
#success-frame .btn {
margin-bottom: 10px;
width: 80%;
}
/**
* CANCEL APPOINTMENT
*/

View file

@ -52,6 +52,10 @@ body .ui-dialog .ui-dialog-buttonpane {
border: none;
}
body .ui-dialog #error-technical {
max-width: 500px;
}
body .ui-datepicker {
border: 1px solid #3DD481;
border-radius: 2px;

View file

@ -180,11 +180,17 @@ var BackendUsers = {
return;
}
var userId = $input.parents().eq(2).find('.record-id').val();
if (userId == undefined) {
return;
}
var postUrl = GlobalVariables.baseUrl + '/index.php/backend_api/ajax_validate_username';
var postData = {
'csrfToken': GlobalVariables.csrfToken,
'username': $input.val(),
'user_id': $input.parents().eq(2).find('.record-id').val()
'user_id': userId
};
$.post(postUrl, postData, function(response) {

View file

@ -139,6 +139,12 @@ var FrontendBook = {
});
});
// Add the "Any Provider" entry.
if ($('#select-provider option').length > 1) {
$('#select-provider').append(new Option(EALang['any_provider'] + ' *', 'any-provider'));
}
FrontendBook.getAvailableHours($('#select-date').val());
FrontendBook.updateConfirmFrame();
FrontendBook.updateServiceDescription($('#select-service').val(), $('#service-description'));
@ -255,44 +261,7 @@ var FrontendBook = {
* another customer or event.
*/
$('#book-appointment-submit').click(function(event) {
var formData = jQuery.parseJSON($('input[name="post_data"]').val());
var postData = {
'csrfToken': GlobalVariables.csrfToken,
'id_users_provider': formData['appointment']['id_users_provider'],
'id_services': formData['appointment']['id_services'],
'start_datetime': formData['appointment']['start_datetime'],
};
if (GlobalVariables.manageMode) {
postData.exclude_appointment_id = GlobalVariables.appointmentData.id;
}
var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_check_datetime_availability';
$.post(postUrl, postData, function(response) {
////////////////////////////////////////////////////////////////////////
console.log('Check Date/Time Availability Post Response :', response);
////////////////////////////////////////////////////////////////////////
if (response.exceptions) {
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
GeneralFunctions.displayMessageBox('Unexpected Issues', 'Unfortunately '
+ 'the check appointment time availability could not be completed. '
+ 'The following issues occurred:');
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
return false;
}
if (response === true) {
FrontendBook.registerAppointment();
} else {
GeneralFunctions.displayMessageBox('Appointment Hour Taken', 'Unfortunately '
+ 'the selected appointment hour is not available anymore. Please select '
+ 'another hour.');
FrontendBook.getAvailableHours($('#select-date').val());
}
}, 'json').fail(GeneralFunctions.ajaxFailureHandler);
FrontendBook.registerAppointment();
});
/**
@ -670,12 +639,7 @@ var FrontendBook = {
}
})
.done(function(response) {
if (response.exceptions) {
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
GeneralFunctions.displayMessageBox('Unexpected Issues', 'Unfortunately '
+ 'the check appointment time availability could not be completed. '
+ 'The following issues occurred:');
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
if (!GeneralFunctions.handleAjaxExceptions(response)) {
$('.captcha-title small').trigger('click');
return false;
}

View file

@ -28,7 +28,7 @@ $(document).ready(function() {
$('#install').click(function() {
if (!validate()) return;
var postUrl = GlobalVariables.baseUrl + '/index.php/appointments/ajax_install';
var postUrl = GlobalVariables.baseUrl + '/index.php/installation/ajax_install';
var postData = {
'csrfToken': GlobalVariables.csrfToken,
'admin': JSON.stringify(getAdminData()),
@ -47,14 +47,12 @@ $(document).ready(function() {
if (!GeneralFunctions.handleAjaxExceptions(response)) return;
if (response == AJAX_SUCCESS) {
$('.alert').text('Easy!Appointments has been successfully installed!');
$('.alert').addClass('alert-success');
$('.alert').show();
setTimeout(function() {
window.location.href = GlobalVariables.baseUrl + '/index.php/backend';
}, 1000);
}
$('.alert').text('Easy!Appointments has been successfully installed!');
$('.alert').addClass('alert-success');
$('.alert').show();
setTimeout(function() {
window.location.href = GlobalVariables.baseUrl + '/index.php/backend';
}, 1000);
},
error: function(jqXHR, textStatus, errorThrown) {
// Treat the error the same way as php exceptions.

1
src/assets/sql/data.sql Normal file
View file

@ -0,0 +1 @@
INSERT INTO ea_settings (name, value) VALUES ('google_analytics_code', '');