* Created backend services page view file

* Organized backend_services.js file
This commit is contained in:
alextselegidis@gmail.com 2013-07-17 16:29:51 +00:00
parent f0b8ab45b5
commit 62a667cb9c
9 changed files with 479 additions and 17 deletions

View file

@ -53,5 +53,7 @@ define('DB_SLUG_SECRETARY', 'secretary');
define('FILTER_TYPE_PROVIDER', 'provider');
define('FILTER_TYPE_SERVICE', 'service');
define('AJAX_SUCCESS', 'SUCCESS');
define('AJAX_FAILURE', 'FAILURE');
/* End of file constants.php */
/* Location: ./application/config/constants.php */

View file

@ -66,7 +66,21 @@ class Backend extends CI_Controller {
}
public function services() {
echo '<h1>Not implemented yet.</h1>';
// @task Require user to be logged in the application.
$this->load->model('providers_model');
$this->load->model('customers_model');
$this->load->model('services_model');
$this->load->model('settings_model');
$view['base_url'] = $this->config->item('base_url');
$view['company_name'] = $this->settings_model->get_setting('company_name');
$view['services'] = $this->services_model->get_batch();
$view['categories'] = $this->services_model->get_all_categories();
$this->load->view('backend/header', $view);
$this->load->view('backend/services', $view);
$this->load->view('backend/footer', $view);
}
public function providers() {

View file

@ -180,7 +180,7 @@ class Backend_api extends CI_Controller {
}
if (!isset($warnings)) {
echo json_encode('SUCCESS');
echo json_encode(AJAX_SUCCESS);
} else {
echo json_encode(array(
'warnings' => $warnings
@ -262,7 +262,7 @@ class Backend_api extends CI_Controller {
// :: SEND RESPONSE TO CLIENT BROWSER
if (!isset($warnings)) {
echo json_encode('SUCCESS'); // Everything executed successfully.
echo json_encode(AJAX_SUCCESS); // Everything executed successfully.
} else {
echo json_encode(array(
'warnings' => $warnings // There were warnings during the operation.
@ -294,7 +294,7 @@ class Backend_api extends CI_Controller {
$this->providers_model->set_setting('google_sync', FALSE, $_POST['provider_id']);
$this->providers_model->set_setting('google_token', NULL, $_POST['provider_id']);
echo json_encode('SUCCESS');
echo json_encode(AJAX_SUCCESS);
} catch(Exception $exc) {
echo json_encode(array(
@ -397,7 +397,7 @@ class Backend_api extends CI_Controller {
'warnings' => $warnings
));
} else {
echo json_encode('SUCCESS');
echo json_encode(AJAX_SUCCESS);
}
} catch(Exception $exc) {
@ -441,7 +441,7 @@ class Backend_api extends CI_Controller {
'warnings' => $warnings
));
} else {
echo json_encode('SUCCESS');
echo json_encode(AJAX_SUCCESS);
}
} catch(Exception $exc) {
@ -461,7 +461,7 @@ class Backend_api extends CI_Controller {
$this->load->model('customers_model');
$customer = json_decode($_POST['customer'], true);
$this->customers_model->add($customer);
echo json_encode('SUCCESS');
echo json_encode(AJAX_SUCCESS);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
@ -478,7 +478,7 @@ class Backend_api extends CI_Controller {
try {
$this->load->model('customers_model');
$this->customers_model->delete($_POST['customer_id']);
echo json_encode('SUCCESS');
echo json_encode(AJAX_SUCCESS);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
@ -487,27 +487,84 @@ class Backend_api extends CI_Controller {
}
public function ajax_save_service() {
try {
$this->load->model('services_model');
$service = json_decode($_POST['service'], true);
$this->services_model->add($service);
echo json_encode(AJAX_SUCCESS);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
));
}
}
public function ajax_delete_service() {
try {
$this->load->model('services_model');
$result = $this->services_model->delete($_POST['service_id']);
echo ($result) ? json_encode(AJAX_SUCCESS) : json_encode(AJAX_FAILURE);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
));
}
}
public function ajax_filter_services() {
try {
$this->load->model('services_model');
$key = $_POST['key']; // @task fix sql injection
$where =
'(name LIKE "%' . $key . '%" OR duration LIKE "%' . $key . '%" OR ' .
'price LIKE "%' . $key . '%" OR currency LIKE "%' . $key . '%" OR ' .
'description LIKE "%' . $key . '%")';
$services = $this->services_model->get_batch($where);
echo json_encode($services);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
));
}
}
public function ajax_save_service_category() {
try {
$this->load->model('services_model');
$category = json_decode($_POST['category'], true);
$this->services_model->add_category($category);
echo json_encode(AJAX_SUCCESS);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
));
}
}
public function ajax_delete_service_category() {
try {
$this->load->model('services_model');
$result = $this->services_model->delete($_POST['category_id']);
echo ($result) ? json_encode(AJAX_SUCCESS) : json_encode(AJAX_FAILURE);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
));
}
}
public function ajax_filter_service_categories() {
try {
$this->load->model('services_model');
$key = $_POST['key']; // @task sql injection
$where = '(name LIKE "%' . $key . '%" OR description LIKE "%' . $key . '%")';
$categories = $this->services_model->get_categories($where);
echo json_encode($categories);
} catch(Exception $exc) {
echo json_encode(array(
'exceptions' => array(exceptionToJavascript($exc))
));
}
}
}

View file

@ -185,7 +185,7 @@ class Google extends CI_Controller {
}
}
echo json_encode('SUCCESS');
echo json_encode(AJAX_SUCCESS);
} catch(Exception $exc) {
echo json_encode(array(

View file

@ -324,7 +324,8 @@ class Services_Model extends CI_Model {
*
* @return array Returns an array that contains all the service category records.
*/
public function get_all_categories() {
public function get_all_categories($where = '') {
if ($where !== '') $this->db->where($where);
return $this->db->get('ea_service_categories')->result_array();
}

View file

@ -0,0 +1,129 @@
<script type="text/javascript"
src="<?php echo $base_url; ?>assets/js/backend_services.js"></script>
<script type="text/javascript">
var GlobalVariables = {
'baseUrl': <?php echo '"' . $base_url . '"'; ?>,
'services': <?php echo json_encode($services); ?>,
'categories': <?php echo json_encode($categories); ?>
};
$(document).ready(function() {
BackendServices.initialize(true);
});
</script>
<div id="services-page" class="row-fluid">
<ul class="nav nav-tabs">
<li class="services-tab tab active"><a>Services</a></li>
<li class="categories-tab tab"><a>Categories</a></li>
</ul>
<?php // SERVICES TAB ++++++++++++++++++++++++++++++++ ?>
<div id="services" class="tab-content">
<?php // FILTER SERVICES ?>
<div class="filter span4">
<div class="input-append">
<input class="filter-key span12" type="text" />
<button class="filter-services btn" type="button">Filter</button>
</div>
<h2>Services</h2>
<div class="filter-results"></div>
</div>
<div class="details span7">
<div class="btn-toolbar">
<div class="add-edit-delete-group btn-group">
<button id="add-service" class="btn">
<i class="icon-plus"></i>
Add</button>
<button id="edit-service" class="btn" disabled="disabled">
<i class="icon-pencil"></i>
Edit</button>
<button id="delete-service" class="btn" disabled="disabled">
<i class="icon-remove"></i>
Delete</button>
</div>
<div class="save-cancel-group btn-group" style="display:none;">
<button id="save-service" class="btn">
<i class="icon-ok"></i>
Save</button>
<button id="cancel-service" class="btn">
<i class="icon-ban-circle"></i>
Cancel</button>
</div>
</div>
<h2>Details</h2>
<div class="form-message alert" style="display:none;"></div>
<input type="hidden" id="service-id" />
<label for="service-name">Name *</label>
<input type="text" id="service-name" class="span7 required" />
<label for="service-duration">Duration</label>
<input type="text" id="service-duration" class="span7" />
<label for="service-price">Price</label>
<input type="text" id="service-price" class="span7" />
<label for="service-currency">Currency</label>
<input type="text" id="service-currency" class="span7" />
<label for="service-description">Description</label>
<textarea id="service-description" rows="4" class="span7"></textarea>
<label for="service-category">Category</label>
<select id="service-category" class="span7"></select>
</div>
</div>
<?php // CATEGORIES TAB ++++++++++++++++++++++++++++++++ ?>
<div id="categories" class="tab-content" style="display:none;">
<div class="filter span4">
<div class="input-append">
<input class="span12" type="text" class="filter-key" />
<button type="button" class="btn" class="filter-services">Filter</button>
</div>
<h2>Categories</h2>
<div class="filter-results"></div>
</div>
<div class="details span7">
<div class="btn-toolbar">
<div class="add-edit-delete-group btn-group">
<button id="add-category" class="btn">
<i class="icon-plus"></i>
Add</button>
<button id="edit-category" class="btn" disabled="disabled">
<i class="icon-pencil"></i>
Edit</button>
<button id="delete-category" class="btn" disabled="disabled">
<i class="icon-remove"></i>
Delete</button>
</div>
<div class="save-cancel-group btn-group" style="display:none;">
<button id="save-category" class="btn">
<i class="icon-ok"></i>
Save</button>
<button id="cancel-category" class="btn">
<i class="icon-ban-circle"></i>
Cancel</button>
</div>
</div>
<h2>Details</h2>
<div class="form-message alert" style="display:none;"></div>
<label for="category-name">Name *</label>
<input type="text" id="category-name" class="span7 required" />
<label for="category-description">Description</label>
<textarea id="category-description" rows="4" class="span7"></textarea>
</div>
</div>
</div>

View file

@ -78,7 +78,12 @@ root {
/* BACKEND SERVICES PAGE
-------------------------------------------------------------------- */
#services-page .tab-content { margin: 15px; }
#services-page .nav { margin: 15px; }
#services-page .nav li { cursor: pointer; }
#services-page .service-row { padding: 10px 7px; border-radius: 3px; }
#services-page .service-row:hover { cursor: pointer; background-color: #C6E7D5; }
#services-page .selected-row { background-color: #EFFDF7; }
/* BACKEND PROVIDERS PAGE
-------------------------------------------------------------------- */

View file

@ -87,5 +87,31 @@ var Backend = {
$('#notification').html(notificationHtml);
$('#notification').show('blind');
},
/**
* All backend js code has the same way of dislaying exceptions that are raised on the
* server during an ajax call.
*
* @param {object} response Contains the server response. If exceptions or warnings are
* found, user friendly messages are going to be displayed to the user.
* @returns {bool} Returns whether the the ajax callback should continue the execution or
* stop, due to critical server exceptions.
*/
handleAjaxExceptions: function(response) {
if (response.exceptions) {
response.exceptions = GeneralFunctions.parseExceptions(response.exceptions);
GeneralFunctions.displayMessageBox(Backend.EXCEPTIONS_TITLE, Backend.EXCEPTIONS_MESSAGE);
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.exceptions));
return false;
}
if (response.warnings) {
response.warnings = GeneralFunctions.parseExceptions(response.warnings);
GeneralFunctions.displayMessageBox(Backend.WARNINGS_TITLE, Backend.WARNINGS_MESSAGE);
$('#message_box').append(GeneralFunctions.exceptionsToHtml(response.warnings));
}
return true;
}
};

View file

@ -0,0 +1,228 @@
/**
* This namespace handles the js functionality of the backend services page.
*
* @namespace BackendServices
*/
var BackendServices = {
/**
* Contains the basic record methods for the page.
*
* @type ServicesHelper|CategoriesHelper
*/
helper: {},
/**
* Default initialize method of the page.
*
* @param {bool} bindEventHandlers (OPTIONAL) Determines whether to bind the
* default event handlers (default: true).
*/
initialize: function(bindEventHandlers) {
if (bindEventHandlers === undefined) bindEventHandlers = true;
// Fill available service categories listbox.
$.each(GlobalVariables.categories, function(index, category) {
var option = new Option(category.name, category.value);
$('#service-category').append(option);
});
$('#service-category').append(new Option('- No Category -', null)).val('null');
// Instantiate helper object (service helper by default).
BackendServices.helper = new ServicesHelper();
BackendServices.helper.resetForm();
BackendServices.helper.filter('');
$('#service-duration').spinner({
'min': 0,
'numberFormat': 'n Minutes'
});
if (bindEventHandlers) BackendServices.bindEventHandlers();
},
/**
* Binds the default event handlers of the backend services page. Do not use this method
* if you include the "BackendServices" namespace on another page.
*
* @returns {undefined}
*/
bindEventHandlers: function() {
/**
* Event: Page Tab Button "Click"
*
* Changes the displayed tab.
*/
$('.tab').click(function() {
$('.active').removeClass('active');
$(this).addClass('active');
$('.tab-content').hide();
if ($(this).hasClass('services-tab')) { // display services tab
$('#services').show();
BackendServices.helper = new ServicesHelper();
} else if ($(this).hasClass('categories-tab')) { // display categories tab
$('#categories').show();
BackendServices.helper = new CategoriesHelper();
}
});
/**
* Event: Filter Services Button "Click"
*/
$(' .filter-services').click(function() {
var key = $('#services .filter-key').val();
$('.selected-row').removeClass('selected-row');
BackendServices.helper.resetForm();
BackendServices.helper.filter(key);
});
/**
* Event: Filter Service Row "Click"
*
* Display the selected service data to the user.
*/
$(document).on('click', '.service-row', function() {
var service = { 'id': $(this).attr('data-id') };
$.each(BackendServices.helper.filterResults, function(index, item) {
if (item.id === service.id) {
service = item;
return;
}
});
BackendServices.helper.display(service);
$('.selected-row').removeClass('selected-row');
$(this).addClass('selected-row');
});
}
};
/**
* This class contains the methods that will be used by the "Services" tab of the page.
* @class ServicesHelper
*/
var ServicesHelper = function() {
this.filterResults = {};
};
/**
* Save service record to database.
*
* @param {object} service Contains the service record data. If an 'id' value is provided
* then the update operation is going to be executed.
*/
ServicesHelper.prototype.save = function(service) {
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_service';
var postData = { 'service': JSON.stringify(service) };
$.post(postUrl, postData, function(response) {
console.log('Save Service Response:', response);
if (!Backend.handleAjaxExceptions(response)) return;
$('#services .add-edit-delete-group').show();
$('#services .save-cancel-group').hide();
});
};
/**
* Delete a service records from database.
*
* @param {int} id Record id to be deleted.
*/
ServicesHelper.prototype.delete = function(id) {
};
/**
* Validates a service record.
*
* @param {object} service Contains the service data.
* @returns {bool} Returns the validation result.
*/
ServicesHelper.prototype.validate = function(service) {
};
/**
* Resets the service tab form back to its initial state.
*/
ServicesHelper.prototype.resetForm = function() {
$('#services .details').find('input, textarea').val('');
$('#service-category').val('null');
$('#services .add-edit-delete-group').show();
$('#services .save-cancel-group').hide();
$('#edit-service, #delete-service').prop('disabled', true);
$('#services .details').find('input, textarea').prop('readonly', true);
$('#service-category').prop('disabled', true);
};
/**
* Display a service record into the service form.
*
* @param {object} service Contains the service record data.
*/
ServicesHelper.prototype.display = function(service) {
$('#service-id').val(service.id);
$('#service-name').val(service.name);
$('#service-duration').val(service.duration + ' min');
$('#service-price').val(service.price);
$('#service-currency').val(service.currency);
$('#service-description').val(service.description);
$('#service-category').val(service.id_service_categories);
};
/**
* Filters service records depending a string key.
*
* @param {string} key This is used to filter the service records of the database.
*/
ServicesHelper.prototype.filter = function(key) {
var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_filter_services';
var postData = { 'key': key };
$.post(postUrl, postData, function(response) {
/////////////////////////////////////////////////////
console.log('Filter services response:', response);
/////////////////////////////////////////////////////
if (!Backend.handleAjaxExceptions(response)) return;
BackendServices.helper.filterResults = response;
$('#services .filter-results').html('');
$.each(response, function(index, service) {
var html = ServicesHelper.prototype.getFilterHtml(service);
$('#services .filter-results').append(html);
});
}, 'json');
};
/**
* Get a service row html code that is going to be displayed on the filter results list.
*
* @param {object} service Contains the service record data.
* @returns {string} The html code that represents the record on the filter results list.
*/
ServicesHelper.prototype.getFilterHtml = function(service) {
var html =
'<div class="service-row" data-id="' + service.id + '">' +
'<strong>' + service.name + '</strong><br>' +
service.duration + ' min - ' +
service.price + ' ' + service.currency + '<br>' +
'</div>';
return html;
};
/**
* This class contains the core method implementations that belong to the categories tab
* of the backend services page.
*
* @class CategoriesHelper
*/
var CategoriesHelper = function() {
this.filterResults = {};
};