* Created the backend/settings page.

* Added basic backend_settings.js code structure.
* Added User Model and new functions to settings_model.php
This commit is contained in:
alextselegidis@gmail.com 2013-09-14 16:10:59 +00:00
parent 6082c66d6e
commit 3eccb66192
13 changed files with 537 additions and 28 deletions

View file

@ -1,12 +1,11 @@
VERSION 0.5 VERSION 0.6
=========== ===========
[Feature] Admin users management. [Feature] System and user settings page.
[Feature] Service provider users management. [Feature] Login process included.
[Feature] Customer users management. [Feature] Applied user privileges through all the system depending their role type.
[Feature] Secretary users management. [Feature] Select existing customer from backend/calendar when trying to add a new appointment.
[Feature] Custom error 404 page. [Fix] Fix backend/calendar service and provider functionality.
[Enhancement] Display selected service description and price at the appointment book wizard.
[Enhancement] Group services by categories at the appointment book wizard.
Official Easy!Appointments Website: Official Easy!Appointments Website:
http://easyappointments.org http://easyappointments.org

View file

@ -1,5 +1,8 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
// Include the external configuration.php
include dirname(dirname(dirname(__FILE__))) . '/configuration.php';
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Base Site URL | Base Site URL
@ -225,7 +228,7 @@ $config['cache_path'] = '';
| MUST set an encryption key. See the user guide for info. | MUST set an encryption key. See the user guide for info.
| |
*/ */
$config['encryption_key'] = ''; $config['encryption_key'] = SystemConfiguration::$base_url;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View file

@ -55,5 +55,8 @@ define('FILTER_TYPE_SERVICE', 'service');
define('AJAX_SUCCESS', 'SUCCESS'); define('AJAX_SUCCESS', 'SUCCESS');
define('AJAX_FAILURE', 'FAILURE'); define('AJAX_FAILURE', 'FAILURE');
define('SETTINGS_SYSTEM', 'SETTINGS_SYSTEM');
define('SETTINGS_USER', 'SETTINGS_USER');
/* End of file constants.php */ /* End of file constants.php */
/* Location: ./application/config/constants.php */ /* Location: ./application/config/constants.php */

View file

@ -128,9 +128,21 @@ class Backend extends CI_Controller {
*/ */
public function settings() { public function settings() {
$this->load->model('settings_model'); $this->load->model('settings_model');
$this->load->model('user_model');
$this->load->library('session');
// @task Apply data for testing this page (this must be done during the login process).
$this->session->set_userdata('user_id', 18);
$this->session->set_userdata('user_slug', DB_SLUG_ADMIN);
$user_id = $this->session->userdata('user_id');
$view['base_url'] = $this->config->item('base_url'); $view['base_url'] = $this->config->item('base_url');
$view['company_name'] = $this->settings_model->get_setting('company_name'); $view['company_name'] = $this->settings_model->get_setting('company_name');
$view['user_slug'] = $this->session->userdata('user_slug');
$view['system_settings'] = $this->settings_model->get_settings();
$view['user_settings'] = $this->user_model->get_settings($user_id);
$this->load->view('backend/header', $view); $this->load->view('backend/header', $view);
$this->load->view('backend/settings', $view); $this->load->view('backend/settings', $view);

View file

@ -793,6 +793,33 @@ class Backend_api extends CI_Controller {
)); ));
} }
} }
/**
* [AJAX] Save a setting or multiple settings in the database.
*
* This method is used to store settings in the database. It can be either system
* or user settings, one or many. Use the $_POST variables accordingly.
*
* @param array $_POST['settings'] Contains an array with settings.
* @param bool $_POST['type'] Determines the settings type, can be either SETTINGS_SYSTEM
* or SETTINGS_USER.
*/
public function ajax_save_settings() {
try {
if ($_POST['type'] == SETTINGS_SYSTEM) {
// @task Implement save settings.
} else if ($_POST['type'] == SETTINGS_USER) {
$this->load->library('session');
$this->load->model('user_model');
$user_id = $this->session->userdata('user_id');
$this->user_model->save_settings($_POST['settings'], $user_id);
}
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavaScript($exc))
));
}
}
} }
/* End of file backend_api.php */ /* End of file backend_api.php */

View file

@ -90,6 +90,40 @@ class Settings_Model extends CI_Model {
return $this->db->delete('ea_settings', array('name' => $name)); return $this->db->delete('ea_settings', array('name' => $name));
} }
/**
* Saves all the system settings into the database.
*
* This method is usefull when trying to save all the system settings at once instead of
* saving them one by one.
*
* @param array $settings Contains all the system settings.
* @return bool Returns the save operation result.
*
* @throws Exception When the update operation won't work for a specific setting.
*/
public function save_settings($settings) {
if (!is_array($settings)) {
throw new Exception('$settings argument is invalid: '. print_r($settings, TRUE));
}
foreach($settings as $name=>$value) {
if (!$this->db->update('ea_settings', array('value' => $value), array('name' => $name))) {
throw new Exception('Could not save setting (' . $name . ' - ' . $value . ')');
}
}
return TRUE;
}
/**
* Returns all the system settings at once.
*
* @return array Array of all the system settings stored in the 'ea_settings' table.
*/
public function get_settings() {
return $this->db->get('ea_settings')->result_array();
}
} }
/* End of file settings_model.php */ /* End of file settings_model.php */

View file

@ -0,0 +1,41 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed.');
/**
* Contains current user's methods.
*/
class User_Model extends CI_Model {
/**
* Class Constructor
*/
public function __construct() {
parent::__construct();
}
/**
* Returns the user settings from the database.
*
* @param numeric $user_id User record id of which the settings will be returned.
* @return array Returns an array with user settings.
*/
public function get_settings($user_id) {
$settings = $this->db->get_where('ea_user_settings', array('id_users' => $user_id))->row_array();
unset($settings['id_users']);
return $settings;
}
/**
* This method saves the user settings into the database.
*
* @param array $settings Contains the current users settings.
* @param numeric $user_id User record id of the settings.
* @return bool Returns the operation result.
*/
public function save_settings($settings, $user_id) {
$settings['id_users'] = $user_id;
$this->db->where('id_users', $user_id);
return $this->db->update('ea_user_settings', $settings);
}
}
/* End of file user_model.php */
/* Location: ./application/models/user_model.php */

View file

@ -1,11 +1,248 @@
<div id="settings-page" style="padding: 20px;"> <script type="text/javascript"
<h1>This page is not implemented yet!</h1> src="<?php echo $base_url; ?>assets/js/backend_settings.js"></script>
<p>
It will be included in the next release of Easy!Appointments (v0.6). <script type="text/javascript">
<br> var GlobalVariables = {
Check the <a href="https://plus.google.com/communities/105333709485142846840">Google+ 'baseUrl': <?php echo '"' . $base_url . '"'; ?>,
Community</a> for development updates or visit the 'userSlug': <?php echo '"' . $user_slug . '"'; ?>,
<a href="http://groups.google.com/group/easy-appointments">Support Group</a> for help. 'settings': {
'system': <?php echo json_encode($system_settings); ?>,
'user': <?php echo json_encode($user_settings); ?>
}
};
$(document).ready(function() {
BackendSettings.initialize(true);
});
</script>
</p> <div id="services-page" class="row-fluid">
<ul class="nav nav-tabs">
<li class="general-tab tab active"><a>General</a></li>
<li class="business-logic-tab tab"><a>Business Logic</a></li>
<li class="user-tab tab"><a>User</a></li>
</ul>
<?php
// --------------------------------------------------------------
//
// GENERAL TAB
//
// --------------------------------------------------------------
?>
<div id="general" class="tab-content">
<form>
<fieldset>
<legend>
General Settings
<button class="save-settings btn btn-primary btn-mini">Save</button>
</legend>
<label for="company-name">Company Name *</label>
<input type="text" id="company-name" data-field="company_name">
<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">
<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">
<span class="help-block">Company link should point to the official website of
the company (optional).</span>
</fieldset>
</form>
</div>
<?php
// --------------------------------------------------------------
//
// BUSINESS LOGIC TAB
//
// --------------------------------------------------------------
?>
<div id="business-logic" class="tab-content" style="display: none;">
<form>
<fieldset>
<legend>
Business Logic
<button class="save-settings btn btn-primary btn-mini">Save</button>
</legend>
<h4>Working Plan</h4>
<span class="help-block">
Mark below the days and hours that your company will accept appointments.
You will be able to adjust appointments in non working hours but the customers
will not be able to book appointments by themselves in non working periods.
<strong>This working plan will be the default for new provider records but
you will be able to change each provider's plan seperatly by editing his
record.</strong>
</span>
<table class="table table-striped">
<thead>
<tr>
<th>Day</th>
<th>Start</th>
<th>End</th>
</tr>
</thead>
<tbody>
<tr>
<td><label class="checkbox"><input type="checkbox" id="monday" />Monday</label></td>
<td><input type="text" id="monday-start" /></td>
<td><input type="text" id="monday-end" /></td>
</tr>
<tr>
<td><label class="checkbox"><input type="checkbox" id="tuesday" />Tuesday</label></td>
<td><input type="text" id="tuesday-start" /></td>
<td><input type="text" id="tuesday-end" /></td>
</tr>
<tr>
<td><label class="checkbox"><input type="checkbox" id="wednesday" />Wednesday</label></td>
<td><input type="text" id="wednesday-start" /></td>
<td><input type="text" id="wednesday-end" /></td>
</tr>
<tr>
<td><label class="checkbox"><input type="checkbox" id="thursday" />Thursday</label></td>
<td><input type="text" id="thursday-start" /></td>
<td><input type="text" id="thursday-end" /></td>
</tr>
<tr>
<td><label class="checkbox"><input type="checkbox" id="friday" />Friday</label></td>
<td><input type="text" id="friday-start" /></td>
<td><input type="text" id="friday-end" /></td>
</tr>
<tr>
<td><label class="checkbox"><input type="checkbox" id="saturday" />Saturday</label></td>
<td><input type="text" id="saturday-start" /></td>
<td><input type="text" id="saturday-end" /></td>
</tr>
<tr>
<td><label class="checkbox"><input type="checkbox" id="sunday" />Sunday</label></td>
<td><input type="text" id="sunday-start" /></td>
<td><input type="text" id="sunday-end" /></td>
</tr>
</tbody>
</table>
<br>
<h4>Breaks</h4>
<span class="help-block">
Add the working breaks during each day. These breaks will be applied for
all new providers.
</span>
<div>
<button type="button" id="add-break" class="btn btn-primary">
<i class="icon-white icon-plus"></i>
Add
</button>
<button type="button" id="edit-break" class="btn">
<i class="icon-edit"></i>
Edit
</button>
<button type="button" id="remove-break" class="btn">
<i class="icon-remove"></i>
Delete
</button>
</div>
<br>
<table id="breaks" class="table table-striped">
<thead>
<tr>
<th>Day</th>
<th>Start</th>
<th>End</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</fieldset>
</form>
</div>
<?php
// --------------------------------------------------------------
//
// USER TAB
//
// --------------------------------------------------------------
?>
<div id="user" class="tab-content" style="display: none;">
<form class="row-fluid">
<fieldset class="span5">
<legend>
Personal Info
<button class="save-settings btn btn-primary btn-mini">Save</button>
</legend>
<input type="hidden" id="user-id" />
<label for="first-name">First Name</label>
<input type="text" id="first-name" class="span9" />
<label for="last-name">Last Name *</label>
<input type="text" id="last-name" class="span9" />
<label for="email">Email *</label>
<input type="text" id="email" class="span9" />
<label for="mobile-number">Mobile Number</label>
<input type="text" id="mobile-number" class="span9" />
<label for="phone-number">Phone Number</label>
<input type="text" id="phone-number" class="span9" />
<label for="address">Address</label>
<input type="text" id="address" class="span9" />
<label for="city">City</label>
<input type="text" id="city" class="span9" />
<label for="state">State</label>
<input type="text" id="state" class="span9" />
<label for="zip-code">Zip Code</label>
<input type="text" id="zip-code" class="span9" />
<label for="notes">Notes</label>
<textarea id="notes" class="span9"></textarea>
</fieldset>
<fieldset class="span5">
<legend>Miscellaneous</legend>
<label for="username">Username *</label>
<input type="text" id="username" />
<label for="password">Password *</label>
<input type="text" id="password" />
<label for="retype-password">Retype Password *</label>
<input type="text" id="retype-password" />
<br>
<button type="button" class="btn" data-toggle="button">
<i class="icon-asterisk"></i>
Receive Email Notifications
</button>
</fieldset>
</form>
</div>
</div> </div>

View file

@ -111,7 +111,7 @@
<button type="button" id="admin-notifications" class="btn" data-toggle="button"> <button type="button" id="admin-notifications" class="btn" data-toggle="button">
<i class="icon-asterisk"></i> <i class="icon-asterisk"></i>
<span>Receive Notifications</span> <span>Receive Email Notifications</span>
</button> </button>
</div> </div>
</div> </div>
@ -205,7 +205,7 @@
<button type="button" id="provider-notifications" class="btn" data-toggle="button"> <button type="button" id="provider-notifications" class="btn" data-toggle="button">
<i class="icon-asterisk"></i> <i class="icon-asterisk"></i>
<span>Receive Notifications</span> <span>Receive Email Notifications</span>
</button> </button>
<br><br> <br><br>

View file

@ -363,9 +363,10 @@ body .modal-header h3 {
#users-page #secretary-providers, #users-page #secretary-providers,
#users-page #provider-services { #users-page #provider-services {
border: 2px solid #ccc; border: 2px solid #ccc;
width: 300px; width: 320px;
height: 100px; height: 140px;
overflow-y: scroll; overflow-y: scroll;
padding: 7px;
} }

View file

@ -29,6 +29,10 @@ var Backend = {
EXCEPTIONS_MESSAGE: 'The operation could not complete due to unexpected issues. ', EXCEPTIONS_MESSAGE: 'The operation could not complete due to unexpected issues. ',
WARNINGS_TITLE: 'Unexpected Warnings', WARNINGS_TITLE: 'Unexpected Warnings',
WARNINGS_MESSAGE: 'The operation completed but some warnings appeared. ', WARNINGS_MESSAGE: 'The operation completed but some warnings appeared. ',
DB_SLUG_ADMIN: 'admin',
DB_SLUG_PROVIDER: 'provider',
DB_SLUG_SECRETARY: 'secretary',
DB_SLUG_CUSTOMER: 'customer',
/** /**
* Place the backend footer always on the bottom of the page. * Place the backend footer always on the bottom of the page.

View file

@ -0,0 +1,148 @@
/**
* Contains the functionality of the backend settings page. Can either work for
* system or user settings, but the actions allowed to the user are restricted to
* his role (only admin has full privileges).
*
* @namespace BackendSettings
*/
var BackendSettings = {
SETTINGS_SYSTEM: 'SETTINGS_SYSTEM',
SETTINGS_USER: 'SETTINGS_USER',
/**
* Tab settings object.
*
* @type {object}
*/
settings: {},
/**
* Initialize Page
*
* @param {bool} bindEventHandlers (OPTIONAL)Determines whether to bind the default event
* handlers (default = true).
* @returns {undefined}
*/
initialize: function(bindEventHandlers) {
if (bindEventHandlers == undefined) bindEventHandlers = true;
// Apply values from database.
$.each(GlobalVariables.settings.system, function(index, setting) {
$('#general input[data-field="' + setting.name + '"]').val(setting.value);
});
if (bindEventHandlers) {
BackendSettings.bindEventHandlers();
}
},
bindEventHandlers: function() {
/**
* Event: Tab "Click"
*
* Change the visible tab contents.
*/
$('.tab').click(function() {
$('.active').removeClass('active');
$(this).addClass('active');
$('.tab-content').hide();
if ($(this).hasClass('general-tab')) {
$('#general').show();
BackendSettings.settings = new SystemSettings();
} else if ($(this).hasClass('business-logic-tab')) {
$('#business-logic').show();
BackendSettings.settings = new SystemSettings();
} else if ($(this).hasClass('user-tab')) {
$('#user').show();
BackendSettings.settings = new UserSettings();
}
});
/**
* Event: Save Settings Button "Click"
*
* Store the setting changes into the database.
*/
$('.save-settings').click(function() {
var settings = BackendSettings.settings.get();
BackendSettings.settings.save();
});
}
};
/**
* "System Settings" Tab Helper
* @class SystemSettings
*/
var SystemSettings = function() {};
/**
* Save the system settings. This method is run after changes are detected on the
* tab input fields.
*
* @param {array} settings Contains the system settings data.
*/
SystemSettings.prototype.save = function(settings) {
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_settings';
var postData = {
'settings': JSON.stringify(settings),
'type': BackendSettings.SETTINGS_SYSTEM
};
$.post(postUrl, postData, function(response) {
///////////////////////////////////////////////////////////
console.log('Save General Settings Response:', response);
///////////////////////////////////////////////////////////
if (!Backend.handleAjaxExceptions(response)) return;
Backend.displayNotification('Settings saved successfully!');
}, 'json');
};
/**
* Prepare the system settings array. This method uses the DOM elements of the
* backend/settings page, so it can't be used in another page.
*
* @returns {array} Returns the system settings array.
*/
SystemSettings.prototype.get = function() {
var settings = []
var tmpSetting = {};
// General Settings Tab
$('#general input').each(function() {
tmpSetting[$(this).attr('data-field')] = $(this).val();
settings.push(tmpSetting);
});
// Business Logic Tab
// @task Get business logic settings.
return settings;
};
/**
* "User Settings" Tab Helper
* @class UserSettings
*/
var UserSettings = function() {};
/**
* Get the settings data for the user settings.
*
* @returns {array} Returns the user settings array.
*/
UserSettings.prototype.get = function() {
}
/**
* Store the user settings into the database.
*
* @param {array} settings Contains the user settings.
*/
UserSettings.prototype.save = function(settings) {
}

View file

@ -28,14 +28,14 @@ var BackendUsers = {
// Fill the services and providers list boxes. // Fill the services and providers list boxes.
$.each(GlobalVariables.services, function(index, service) { $.each(GlobalVariables.services, function(index, service) {
var html = '<input type="checkbox" data-id="' + service.id + '" />' var html = '<label class="checkbox"><input type="checkbox" data-id="' + service.id + '" />'
+ service.name + '<br>'; + service.name + '</label>';
$('#provider-services').append(html); $('#provider-services').append(html);
}); });
$.each(GlobalVariables.providers, function(index, provider) { $.each(GlobalVariables.providers, function(index, provider) {
var html = '<input type="checkbox" data-id="' + provider.id + '" />' var html = '<label class="checkbox"><input type="checkbox" data-id="' + provider.id + '" />'
+ provider.first_name + ' ' + provider.last_name + '<br>'; + provider.first_name + ' ' + provider.last_name + '</label>';
$('#secretary-providers').append(html); $('#secretary-providers').append(html);
}); });
@ -82,8 +82,8 @@ var BackendUsers = {
$('#secretary-providers').html(''); $('#secretary-providers').html('');
$.each(GlobalVariables.providers, function(index, provider) { $.each(GlobalVariables.providers, function(index, provider) {
var html = '<input type="checkbox" data-id="' + provider.id + '" />' var html = '<label class="checkbox"><input type="checkbox" data-id="' + provider.id + '" />'
+ provider.first_name + ' ' + provider.last_name + '<br>'; + provider.first_name + ' ' + provider.last_name + '</label>';
$('#secretary-providers').append(html); $('#secretary-providers').append(html);
}); });
$('#secretary-providers input[type="checkbox"]').prop('disabled', true); $('#secretary-providers input[type="checkbox"]').prop('disabled', true);