* Added "Forgot Password" procedure.

* Started working on the installation page.
* Fixed minor bugs in backend pages.
This commit is contained in:
alextselegidis@gmail.com 2013-10-11 15:58:46 +00:00
parent 538c34ecd4
commit a5ef8fb491
25 changed files with 780 additions and 35 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

View file

@ -12,6 +12,8 @@ class Appointments extends CI_Controller {
* record.
*/
public function index($appointment_hash = '') {
if (!$this->check_installation()) return;
$this->load->model('appointments_model');
$this->load->model('providers_model');
$this->load->model('services_model');
@ -602,6 +604,41 @@ class Appointments extends CI_Controller {
return $available_periods_with_appointments;
}
/**
* This method checks whether the application is installed.
*
* This method resides in this controller because the "index()" function will
* be the first to be launched after the files are on the server. NOTE that the
* "configuration.php" file must be already set because we won't be able to
* connect to the database otherwise.
*/
public function check_installation() {
try {
if (!$this->db->table_exists('ea_users')) {
// This is the first time the website is launched an the user needs to set
// the basic settings.
// We will use mysqli to create the database structure from the "structure.sql" file.
require_once dirname(dirname(dirname(__FILE__))) . '/configuration.php';
$mysqli = new mysqli(SystemConfiguration::$db_host, SystemConfiguration::$db_username,
SystemConfiguration::$db_password, SystemConfiguration::$db_name);
$structure = file_get_contents($this->config->item('base_url') . 'assets/sql/structure.sql');
$mysqli->multi_query($structure);
$mysqli->close();
// Display the installation view page.
$view['base_url'] = $this->config->item('base_url');
$this->load->view('general/installation', $view);
return FALSE; // Do not display the book appointment view file.
} else {
return TRUE;
}
} catch(Exception $exc) {
echo $exc->getTrace();
}
}
}
/* End of file appointments.php */

View file

@ -174,7 +174,7 @@ class Backend extends CI_Controller {
$user_id = $this->session->userdata('user_id');
$view['base_url'] = $this->config->item('base_url');
$view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id'));
$view['user_display_name'] = $this->user_model->get_user_display_name($user_id);
$view['active_menu'] = PRIV_SYSTEM_SETTINGS;
$view['company_name'] = $this->settings_model->get_setting('company_name');
$view['role_slug'] = $this->session->userdata('role_slug');

View file

@ -29,12 +29,12 @@ class User extends CI_Controller {
$this->session->unset_userdata('dest_url');
$view['base_url'] = $this->config->item('base_url');
$this->load->view('user/logout', $view);
}
public function forgot_password() {
$view['base_url'] = $this->config->item('base_url');
$this->load->view('user/forgot_password', $view);
}
public function no_privileges() {
@ -73,6 +73,43 @@ class User extends CI_Controller {
));
}
}
/**
* Regenerate a new password for the current user, only if the username and
* email address given corresond to an existing user in db.
*
* @param string $_POST['username']
* @param string $_POST['email']
*/
public function ajax_forgot_password() {
try {
if (!isset($_POST['username']) || !isset($_POST['email'])) {
throw new Exception('You must enter a valid username and email address in '
. 'order to get a new password!');
}
$this->load->model('user_model');
$this->load->model('settings_model');
$new_password = $this->user_model->regenerate_password($_POST['username'], $_POST['email']);
if ($new_password != FALSE) {
$this->load->library('notifications');
$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')
);
$this->notifications->send_password($new_password, $_POST['email'], $company_settings);
}
echo ($new_password != FALSE) ? json_encode(AJAX_SUCCESS) : json_encode(AJAX_FAILURE);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavaScript($exc))
));
}
}
}
/* End of file user.php */

View file

@ -61,5 +61,21 @@ function generate_salt() {
return substr($salt, 0, $max_length);
}
/**
* This method generates a random string.
*
* @param int $length (OPTIONAL = 10) The length of the generated string.
* @return string Returns the randomly generated string.
* @link http://stackoverflow.com/a/4356295/1718162
*/
function generate_random_string($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$random_string = '';
for ($i = 0; $i < $length; $i++) {
$random_string .= $characters[rand(0, strlen($characters) - 1)];
}
return $random_string;
}
/* End of file general_helper.php */
/* Location: ./application/helpers/general_helper.php */

View file

@ -164,6 +164,45 @@ class Notifications {
return TRUE;
}
/**
* This method sends an email with the new password of a user.
*
* @param string $password Contains the new password.
* @param string $email The receiver's email address.
*/
public function send_password($password, $email, $company_settings) {
$replace_array = array(
'$email_title' => 'New Account Password',
'$email_message' => 'Your new account password is <strong>' . $password . '</strong>. '
. 'Please store this email to be able to retrieve your password if necessary. '
. 'You can also change this password with a new one in the settings page.',
'$company_name' => $company_settings['company_name'],
'$company_email' => $company_settings['company_email'],
'$company_link' => $company_settings['company_link']
);
$email_html = file_get_contents(dirname(dirname(__FILE__))
. '/views/emails/new_password.php');
$email_html = $this->replace_template_variables($replace_array, $email_html);
// :: SETUP EMAIL OBJECT AND SEND NOTIFICATION
$mail = new PHPMailer();
$mail->From = $company_settings['company_email'];
$mail->FromName = $company_settings['company_name'];
$mail->AddAddress($email); // "Name" argument crushes the phpmailer class.
$mail->IsHTML(true);
$mail->CharSet = 'UTF-8';
$mail->Subject = 'New Account Password';
$mail->Body = $email_html;
if (!$mail->Send()) {
throw new Exception('Email could not been sent. '
. 'Mailer Error (Line ' . __LINE__ . '): ' . $mail->ErrorInfo);
}
return TRUE;
}
}
/* End of file notifications.php */

View file

@ -102,6 +102,38 @@ class User_Model extends CI_Model {
$user = $this->db->get_where('ea_users', array('id' => $user_id))->row_array();
return $user['first_name'] . ' ' . $user['last_name'];
}
/**
* If the given arguments correspond to an existing user record, generate a new
* password and send it with an email.
*
* @param string $username
* @param string $email
* @return string|bool Returns the new password on success or FALSE on failure.
*/
public function regenerate_password($username, $email) {
$this->load->helper('general');
$result = $this->db
->select('ea_users.id')
->from('ea_users')
->join('ea_user_settings', 'ea_user_settings.id_users = ea_users.id', 'inner')
->where('ea_users.email', $email)
->where('ea_user_settings.username', $username)
->get();
if ($result->num_rows() == 0) return FALSE;
$user_id = $result->row()->id;
// Create a new password and send it with an email to the given email address.
$new_password = generate_random_string();
$salt = $this->db->get_where('ea_user_settings', array('id_users' => $user_id))->row()->salt;
$hash_password = hash_password($salt, $new_password);
$this->db->update('ea_user_settings', array('password' => $hash_password), array('id_users' => $user_id));
return $new_password;
}
}
/* End of file user_model.php */

View file

@ -346,7 +346,7 @@
// ------------------------------------------------------ ?>
<div id="frame-footer">
Powered By
<a href="https://code.google.com/p/easy-appointments/">
<a href="http://easyappointments.org" target="_blank">
Easy!Appointments
</a>
</div>

View file

@ -41,7 +41,8 @@
<div id="calendar-actions">
<div class="btn-group">
<?php if ($privileges[PRIV_USERS]['edit'] == TRUE) { ?>
<?php //if ($privileges[PRIV_USERS]['edit'] == TRUE) { ?>
<?php if ($role_slug == DB_SLUG_ADMIN || $role_slug == DB_SLUG_PROVIDER) { ?>
<button id="google-sync" class="btn btn-primary"
title="Trigger the Google Calendar synchronization process.">
<i class="icon-refresh icon-white"></i>

View file

@ -62,27 +62,27 @@
</legend>
<label for="company-name">Company Name *</label>
<input type="text" id="company-name" data-field="company_name">
<input type="text" id="company-name" data-field="company_name" class="required">
<span class="help-block">Company name will be displayed everywhere on the system
(required).</span>
<br>
<label for="company-email">Company Email *</label>
<input type="text" id="company-email" data-field="company_email">
<input type="text" id="company-email" data-field="company_email" class="required">
<span class="help-block">This will be the company email address. It will be used
as the sender and the reply address of the system emails (required).</span>
<br>
<label for="company-link">Company Link</label>
<input type="text" id="company-link" data-field="company_link">
<label for="company-link">Company Link *</label>
<input type="text" id="company-link" data-field="company_link" class="required">
<span class="help-block">Company link should point to the official website of
the company (optional).</span>
<br>
<a href="<?php echo $this->config->base_url(); ?>" target="blank" class="btn btn-primary">
<a href="<?php echo $this->config->base_url(); ?>" target="_blank" class="btn btn-primary">
<i class="icon-calendar icon-white"></i>
Go To Booking Page
</a>

View file

@ -0,0 +1,24 @@
<html>
<head>
<title>New Account Password</title>
</head>
<body style="font: 13px arial, helvetica, tahoma;">
<div class="email-container" style="width: 650px;border: 1px solid #eee;">
<div id="header" style="background-color: #3DD481; border-bottom: 4px solid #1A865F;
height: 40px;padding: 10px 15px;">
<strong id="logo" style="color: white; font-size: 31px;
text-shadow: 1px 1px 1px #8F8888;">$company_name</strong>
</div>
<div id="content" style="padding: 10px 15px;">
<h2>$email_title</h2>
<p>$email_message</p>
</div>
<div id="footer" style="padding: 10px; text-align: center;
border-top: 1px solid #EEE;background: #FAFAFA;">
<a href="$company_link">$company_name</a> | Powered by Easy!Appointments
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,215 @@
<!DOCTYPE html>
<html>
<head>
<?php // PAGE META ?>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Easy!Appointments - Installation</title>
<?php // INCLUDE CSS ?>
<link
rel="stylesheet"
type="text/css"
href="<?php echo $base_url; ?>assets/css/libs/bootstrap/bootstrap.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $base_url; ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<?php // SET FAVICON FOR PAGE ?>
<link
rel="icon"
type="image/x-icon"
href="<?php echo $base_url(); ?>assets/images/favicon.ico">
<?php // INCLUDE SCRIPTS ?>
<script
type="text/javascript"
src="<?php echo $base_url; ?>assets/js/libs/jquery/jquery.min.js"></script>
<script
type="text/javascript"
src="<?php echo $base_url; ?>assets/js/libs/bootstrap/bootstrap.min.js"></script>
<script
type="text/javascript"
src="<?php echo $base_url; ?>assets/js/libs/date.js"></script>
<script
type="text/javascript"
src="<?php echo $base_url; ?>assets/js/general_functions.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var GlobalVariables = {
'baseUrl': <?php echo '"' . $base_url . '"'; ?>
};
/**
* Event: Install System "Click"
*/
$('#install').click(function() {
if (!validate()) return;
var postUrl = GlobalVariables.baseUrl + 'ajax_install';
var postData = {
'admin': getAdminData(),
'company': getCompanyDate()
};
$.post(postUrl, postData, function(response) {
});
});
/**
* Validates the user input. Use this before executing the installation procedure.
*
* @returns {bool} Returns the validation result.
*/
function validate() {
try {
$('.alert').fadeOut();
$('input[type="text"]').css('border', '');
// Check for empty fields.
var missingRequired = false;
$('input[type="text"]').each(function() {
if ($(this).val() == '') {
$(this).css('border', '2px solid red');
missingRequired = true;
}
});
if (missingRequired)
throw 'All the page fields are required.';
// Validate Passwords
if ($('#password').val() != $('#retype-password').val()) {
$('#password').css('border', '2px solid red');
$('#retype-password').css('border', '2px solid red');
throw 'Passwords do not match!';
}
// Validate Email
if (!GeneralFunctions.validateEmail($('#email').val())) {
$('#email').css('border', '2px solid red');
throw 'The email addres is invalid!';
}
return true;
} catch(exc) {
$('.alert').txt(exc);
$('.alert').fadeIn();
return false;
}
}
/**
* Get the admin data as an object.
*
* @returns {object}
*/
function getAdminData() {
var admin = {
'first_name': $('#first-name').val(),
'last_name': $('#last-name').val(),
'email': $('#email').val(),
'phone_number': $('#phone-number').val(),
'username': $('#username').val(),
'password': $('#password').val()
};
return admin;
}
/**
* Get the company data as an object.
*
* @returns {object}
*/
function getCompanyData() {
}
});
</script>
</head>
<body>
<header>
<a href="http://easyappointments.org" target="_blank">
<img src="<?php echo $base_url; ?>assets/images/installation-banner.png" alt="Easy!Appointents Installation Banner">
</a>
</header>
<div class="content">
<div class="welcome">
<h2>Welcome To The Easy!Appointments Installation Page</h2>
<p>
This page will help you set the main settings of your Easy!Appointments installation.
You will be able to edit these settings and many more in the backend session of your
system. Remember to use the <span class="label label-info"><?php echo $base_url; ?>
backend</span> url to connect to the backend section of Easy!Appointments.
If you face any problems during the usage of Easy!Appointments you can always check
the official <a href="https://code.google.com/p/easy-appointments/w/list">Wiki Pages</a>
and the <a href="http://groups.google.com/group/easy-appointments">Support Group</a>
for getting help. You may also submit new issues on the
<a href="https://code.google.com/p/easy-appointments/issues/list">Google Code Issues</a>
page, in order to help our development process.
</p>
</div>
<hr>
<div class="alert" style="display: none"></div>
<div class="admin-settings">
<h2>Administrator Settings</h2>
<label for="first-name">First Name</label>
<input type="text" id="first-name" />
<label for="last-name">Last Name</label>
<input type="text" id="last-name" />
<label for="email">Email</label>
<input type="text" id="email" />
<label for="phone-number">Phone Number</label>
<input type="text" id="phone-number" />
<label for="username">Username</label>
<input type="text" id="username" />
<label for="password">Password</label>
<input type="password" id="password" />
<label for="retype-password">Retype Password</label>
<input type="password" id="retype-password" />
</div>
<hr>
<div class="company-settings">
<h2>Company Settings</h2>
<label for="company-name">Company Name</label>
<input type="text" id="company-name">
<label for="company-email">Company Email</label>
<input type="text" id="company-email">
<label for="company-link">Company Link</label>
<input type="text" id="company-link">
<div class="alert alert-info">
You will be able to set your business logic in the backend settings page after
the installation is complete.
</div>
</div>
<center>
<button type="button" id="install" class="btn btn-success btn-large">
<i class="icon-white icon-ok"></i>
Install</button>
</center>
</div>
<footer>
Powered by <a href="http://easyappointments.org">Easy!Appointments</a>
</footer>
</body>
</html>

View file

@ -1,7 +1,124 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<?php // INCLUDE JS FILES ?>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/jquery/jquery.min.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/bootstrap/bootstrap.min.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/libs/date.js"></script>
<script
type="text/javascript"
src="<?php echo $this->config->base_url(); ?>assets/js/general_functions.js"></script>
<?php // INCLUDE CSS FILES ?>
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap.css">
<link
rel="stylesheet"
type="text/css"
href="<?php echo $this->config->base_url(); ?>assets/css/libs/bootstrap/bootstrap-responsive.css">
<?php // SET FAVICON FOR PAGE ?>
<link
rel="icon"
type="image/x-icon"
href="<?php echo $this->config->base_url(); ?>assets/images/favicon.ico">
<style>
body {
background-color: #CAEDF3;
}
#forgot-password-frame {
width: 630px;
margin: 150px auto 0 auto;
background: #FFF;
border: 1px solid #DDDADA;
padding: 70px;
}
label {
font-weight: bold;
}
.user-login{
margin-left: 20px;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
var GlobalVariables = {
'baseUrl': <?php echo '"' . $base_url . '"'; ?>,
'AJAX_SUCCESS': 'SUCCESS',
'AJAX_FAILURE': 'FAILURE'
};
/**
* Event: Login Button "Click"
*
* Make an ajax call to the server and check whether the user's credentials are right.
* If yes then redirect him to his desired page, otherwise display a message.
*/
$('form').submit(function() {
event.preventDefault();
var postUrl = GlobalVariables.baseUrl + 'user/ajax_forgot_password';
var postData = {
'username': $('#username').val(),
'email': $('#email').val()
};
$('.alert').addClass('hidden');
$.post(postUrl, postData, function(response) {
//////////////////////////////////////////////////////////
console.log('Regenerate Password Response: ', response);
//////////////////////////////////////////////////////////
if (!GeneralFunctions.handleAjaxExceptions(response)) return;
if (response == GlobalVariables.AJAX_SUCCESS) {
$('.alert').addClass('alert-success');
$('.alert').text('Your new password has been sent to you with an email.');
} else {
$('.alert').text('The operation failed! Please enter a valid username '
+ 'and email address in order to get a new password.');
}
$('.alert').removeClass('hidden');
}, 'json');
});
});
</script>
</head>
<body>
<div id="forgot-password-frame" class="frame-container">
<h2>Forgot Your Password?</h2>
<p>Type your username and your email address to get your new password.</p>
<hr>
<div class="alert hidden"></div>
<form>
<label for="username">Username</label>
<input type="text" id="username" placeholder="Enter your username here ..." />
<label for="email">Email</label>
<input type="text" id="email" placeholder="Enter your email here ..." />
<br><br>
<button type="submit" id="get-new-password" class="btn btn-primary btn-large">Regenerate Password</button>
<a href="<?php echo $base_url; ?>user/login" class="user-login">Go Back To Login Page</a>
</form>
</div>
</body>
</html>

View file

@ -70,7 +70,7 @@
</a>
<a href="<?php echo $this->config->base_url(); ?>backend" class="btn btn-danger btn-large">
<i class="icon-wrench icon-white"></i>
<i class="icon-home icon-white"></i>
Backend Section
</a>
</div>

View file

@ -53,12 +53,13 @@ root {
font-size: 16px;
}
#header #header-menu .menu-item:hover {
#header #header-menu .menu-item:hover:not(.active) {
background-color: #247A4B;
}
#header #header-menu .active {
color: #D6FF80;
color: #E7FFB3;
text-shadow: 1px 1px 0px #57814D;
}
#footer {

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -342,7 +342,7 @@ CustomersHelper.prototype.display = function(customer) {
'</div>';
$('#customer-appointments').append(html);
});
$('#customer-appointments').jScrollPane();
$('#customer-appointments').jScrollPane({ mouseWheelSpeed: 70 });
};
/**
@ -375,8 +375,7 @@ CustomersHelper.prototype.filter = function(key, selectId, display) {
var html = BackendCustomers.helper.getFilterHtml(customer);
$('#filter-customers .results').append(html);
});
$('#filter-customers .results').jScrollPane();
$('#filter-customers .results').jScrollPane({ mouseWheelSpeed: 70 });
if (response.length == 0) {
$('#filter-customers .results').html('<em>No records found...</em>');

View file

@ -54,7 +54,7 @@ var BackendServices = {
* Changes the displayed tab.
*/
$('.tab').click(function() {
$('.active').removeClass('active');
$(this).parent().find('.active').removeClass('active');
$(this).addClass('active');
$('.tab-content').hide();
@ -389,7 +389,7 @@ ServicesHelper.prototype.filter = function(key, selectId, display) {
var html = ServicesHelper.prototype.getFilterHtml(service);
$('#filter-services .results').append(html);
});
$('#filter-services .results').jScrollPane();
$('#filter-services .results').jScrollPane({ mouseWheelSpeed: 70 });
if (response.length == 0) {
$('#filter-services .result').html('<em>No results found ...</em>');
@ -613,7 +613,7 @@ CategoriesHelper.prototype.filter = function(key, selectId, display) {
var html = BackendServices.helper.getFilterHtml(category);
$('#filter-categories .results').append(html);
});
$('#filter-categories .results').jScrollPane();
$('#filter-categories .results').jScrollPane({ mouseWheelSpeed: 70 });
if (response.length == 0) {
$('#filter-categories .results').html('<em>No records found...</em>');

View file

@ -116,7 +116,7 @@ var BackendSettings = {
// and apply it whenever the user tab is clicked..
var areNotificationsActive = $('#user-notifications').hasClass('active');
$('.active').removeClass('active');
$(this).parent().find('.active').removeClass('active');
$(this).addClass('active');
$('.tab-content').hide();

View file

@ -49,14 +49,14 @@ var BackendUsers = {
+ service.name + '</label>';
$('#provider-services').append(html);
});
$('#provider-services').jScrollPane();
$('#provider-services').jScrollPane({ mouseWheelSpeed: 70 });
$.each(GlobalVariables.providers, function(index, provider) {
var html = '<label class="checkbox"><input type="checkbox" data-id="' + provider.id + '" />'
+ provider.first_name + ' ' + provider.last_name + '</label>';
$('#secretary-providers').append(html);
});
$('#secretary-providers').jScrollPane();
$('#secretary-providers').jScrollPane({ mouseWheelSpeed: 70 });
// Bind event handlers.
if (defaultEventHandlers) BackendUsers.bindEventHandlers();
@ -73,7 +73,7 @@ var BackendUsers = {
* Changes the displayed tab.
*/
$('.tab').click(function() {
$('.active').removeClass('active');
$(this).parent().find('.active').removeClass('active');
$(this).addClass('active');
$('.tab-content').hide();
@ -83,7 +83,7 @@ var BackendUsers = {
} else if ($(this).hasClass('providers-tab')) { // display providers tab
$('#providers').show();
$('#provider-services').data('jsp').destroy();
$('#provider-services').jScrollPane();
$('#provider-services').jScrollPane({ mouseWheelSpeed: 70 });
BackendUsers.helper = new ProvidersHelper();
} else if ($(this).hasClass('secretaries-tab')) { // display secretaries tab
$('#secretaries').show();
@ -109,7 +109,7 @@ var BackendUsers = {
$('#secretary-providers').append(html);
});
$('#secretary-providers input[type="checkbox"]').prop('disabled', true);
$('#secretary-providers').jScrollPane();
$('#secretary-providers').jScrollPane({ mouseWheelSpeed: 70 });
}, 'json');
}

View file

@ -330,7 +330,7 @@ AdminsHelper.prototype.filter = function(key, selectId, display) {
var html = AdminsHelper.prototype.getFilterHtml(admin);
$('#filter-admins .results').append(html);
});
$('#filter-admins .results').jScrollPane();
$('#filter-admins .results').jScrollPane({ mouseWheelSpeed: 70 });
if (response.length == 0) {
$('#filter-admins .results').html('<em>No results found ...</em>')

View file

@ -397,7 +397,7 @@ ProvidersHelper.prototype.filter = function(key, selectId, display) {
var html = ProvidersHelper.prototype.getFilterHtml(provider);
$('#filter-providers .results').append(html);
});
$('#filter-providers .results').jScrollPane();
$('#filter-providers .results').jScrollPane({ mouseWheelSpeed: 70 });
if (response.length == 0) {
$('#filter-providers .results').html('<em>No results found ...</em>')

View file

@ -351,7 +351,7 @@ SecretariesHelper.prototype.filter = function(key, selectId, display) {
var html = SecretariesHelper.prototype.getFilterHtml(secretary);
$('#filter-secretaries .results').append(html);
});
$('#filter-secretaries .results').jScrollPane();
$('#filter-secretaries .results').jScrollPane({ mouseWheelSpeed: 70 });
if (response.length == 0) {
$('#filter-secretaries .results').html('<em>No results found ...</em>')

View file

@ -0,0 +1,227 @@
-- phpMyAdmin SQL Dump
-- version 3.5.1
-- http://www.phpmyadmin.net
--
-- Φιλοξενητής: localhost
-- Χρόνος δημιουργίας: 11 Οκτ 2013 στις 16:58:08
-- Έκδοση διακομιστή: 5.5.24-log
-- Έκδοση PHP: 5.4.3
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
--
-- Βάση: `easy_appointments`
--
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_appointments`
--
CREATE TABLE IF NOT EXISTS `ea_appointments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`book_datetime` datetime DEFAULT NULL,
`start_datetime` datetime DEFAULT NULL,
`end_datetime` datetime DEFAULT NULL,
`notes` text,
`hash` text,
`is_unavailable` tinyint(4) DEFAULT '0',
`id_users_provider` bigint(20) unsigned DEFAULT NULL,
`id_users_customer` bigint(20) unsigned DEFAULT NULL,
`id_services` bigint(20) unsigned DEFAULT NULL,
`id_google_calendar` text,
PRIMARY KEY (`id`),
KEY `id_users_customer` (`id_users_customer`),
KEY `id_services` (`id_services`),
KEY `id_users_provider` (`id_users_provider`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=63 ;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_roles`
--
CREATE TABLE IF NOT EXISTS `ea_roles` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(256) DEFAULT NULL,
`slug` varchar(256) DEFAULT NULL,
`is_admin` tinyint(4) DEFAULT NULL COMMENT '0',
`appointments` int(4) DEFAULT NULL COMMENT '0',
`customers` int(4) DEFAULT NULL COMMENT '0',
`services` int(4) DEFAULT NULL COMMENT '0',
`users` int(4) DEFAULT NULL COMMENT '0',
`system_settings` int(4) DEFAULT NULL COMMENT '0',
`user_settings` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_secretaries_providers`
--
CREATE TABLE IF NOT EXISTS `ea_secretaries_providers` (
`id_users_secretary` bigint(20) unsigned NOT NULL,
`id_users_provider` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id_users_secretary`,`id_users_provider`),
KEY `fk_ea_secretaries_providers_1` (`id_users_secretary`),
KEY `fk_ea_secretaries_providers_2` (`id_users_provider`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_services`
--
CREATE TABLE IF NOT EXISTS `ea_services` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(256) DEFAULT NULL,
`duration` int(11) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
`currency` varchar(32) DEFAULT NULL,
`description` text,
`id_service_categories` bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_service_categories` (`id_service_categories`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=13 ;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_services_providers`
--
CREATE TABLE IF NOT EXISTS `ea_services_providers` (
`id_users` bigint(20) unsigned NOT NULL,
`id_services` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id_users`,`id_services`),
KEY `id_services` (`id_services`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_service_categories`
--
CREATE TABLE IF NOT EXISTS `ea_service_categories` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(256) DEFAULT NULL,
`description` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=24 ;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_settings`
--
CREATE TABLE IF NOT EXISTS `ea_settings` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(512) DEFAULT NULL,
`value` longtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=16 ;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_users`
--
CREATE TABLE IF NOT EXISTS `ea_users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(256) DEFAULT NULL,
`last_name` varchar(512) DEFAULT NULL,
`email` varchar(512) DEFAULT NULL,
`mobile_number` varchar(128) DEFAULT NULL,
`phone_number` varchar(128) DEFAULT NULL,
`address` varchar(256) DEFAULT NULL,
`city` varchar(256) DEFAULT NULL,
`state` varchar(128) DEFAULT NULL,
`zip_code` varchar(64) DEFAULT NULL,
`notes` text,
`id_roles` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `id_roles` (`id_roles`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=84 ;
-- --------------------------------------------------------
--
-- Δομή πίνακα για τον πίνακα `ea_user_settings`
--
CREATE TABLE IF NOT EXISTS `ea_user_settings` (
`id_users` bigint(20) unsigned NOT NULL,
`username` varchar(256) DEFAULT NULL,
`password` varchar(512) DEFAULT NULL,
`salt` varchar(512) DEFAULT NULL,
`working_plan` text,
`notifications` tinyint(4) DEFAULT '0',
`google_sync` tinyint(4) DEFAULT '0',
`google_token` text,
`sync_past_days` int(11) DEFAULT '5',
`sync_future_days` int(11) DEFAULT '5',
PRIMARY KEY (`id_users`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Περιορισμοί για άχρηστους πίνακες
--
--
-- Περιορισμοί για πίνακα `ea_appointments`
--
ALTER TABLE `ea_appointments`
ADD CONSTRAINT `ea_appointments_ibfk_2` FOREIGN KEY (`id_users_customer`) REFERENCES `ea_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `ea_appointments_ibfk_3` FOREIGN KEY (`id_services`) REFERENCES `ea_services` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `ea_appointments_ibfk_4` FOREIGN KEY (`id_users_provider`) REFERENCES `ea_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Περιορισμοί για πίνακα `ea_secretaries_providers`
--
ALTER TABLE `ea_secretaries_providers`
ADD CONSTRAINT `fk_ea_secretaries_providers_1` FOREIGN KEY (`id_users_secretary`) REFERENCES `ea_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `fk_ea_secretaries_providers_2` FOREIGN KEY (`id_users_provider`) REFERENCES `ea_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Περιορισμοί για πίνακα `ea_services`
--
ALTER TABLE `ea_services`
ADD CONSTRAINT `ea_services_ibfk_1` FOREIGN KEY (`id_service_categories`) REFERENCES `ea_service_categories` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
--
-- Περιορισμοί για πίνακα `ea_services_providers`
--
ALTER TABLE `ea_services_providers`
ADD CONSTRAINT `ea_services_providers_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `ea_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `ea_services_providers_ibfk_2` FOREIGN KEY (`id_services`) REFERENCES `ea_services` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Περιορισμοί για πίνακα `ea_users`
--
ALTER TABLE `ea_users`
ADD CONSTRAINT `ea_users_ibfk_1` FOREIGN KEY (`id_roles`) REFERENCES `ea_roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Περιορισμοί για πίνακα `ea_user_settings`
--
ALTER TABLE `ea_user_settings`
ADD CONSTRAINT `ea_user_settings_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `ea_users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;