From 195680e8b35f079d6622c114fb4eb8377d8a2a9a Mon Sep 17 00:00:00 2001 From: Alex Tselegidis Date: Mon, 10 Jan 2022 09:09:49 +0100 Subject: [PATCH] Refactor the services helper JS file so that it becomes a standalone module. --- application/controllers/Services.php | 21 +- application/views/pages/services.php | 28 +- assets/js/http/services_http_client.js | 12 + assets/js/pages/backend_services.js | 91 ------ ...backend_services_helper.js => services.js} | 301 ++++++++---------- 5 files changed, 168 insertions(+), 285 deletions(-) delete mode 100644 assets/js/pages/backend_services.js rename assets/js/pages/{backend_services_helper.js => services.js} (57%) diff --git a/application/controllers/Services.php b/application/controllers/Services.php index f18636f9..b02f7248 100644 --- a/application/controllers/Services.php +++ b/application/controllers/Services.php @@ -36,7 +36,7 @@ class Services extends EA_Controller { /** * Render the backend services page. * - * On this page admin users will be able to manage services, which are eventually selected by customers during the + * On this page admin users will be able to manage services, which are eventually selected by customers during the * booking process. */ public function index() @@ -51,7 +51,12 @@ class Services extends EA_Controller { $user_id = session('user_id'); $role_slug = session('role_slug'); - + + script_vars([ + 'user_id' => $user_id, + 'role_slug' => $role_slug, + ]); + html_vars([ 'page_title' => lang('services'), 'active_menu' => PRIV_SERVICES, @@ -80,7 +85,7 @@ class Services extends EA_Controller { $order_by = 'name ASC'; $limit = request('limit', 1000); - + $offset = 0; $services = $this->services_model->search($keyword, $limit, $offset, $order_by); @@ -100,7 +105,9 @@ class Services extends EA_Controller { { try { - $service = json_decode(request('service'), TRUE); + $service = request('service'); + + $service['id_categories'] = $service['id_categories'] ?: null; if (cannot('add', PRIV_SERVICES)) { @@ -127,13 +134,15 @@ class Services extends EA_Controller { { try { - $service = json_decode(request('service'), TRUE); + $service = request('service'); + + $service['id_categories'] = $service['id_categories'] ?: null; if (cannot('edit', PRIV_SERVICES)) { abort(403, 'Forbidden'); } - + $service_id = $this->services_model->save($service); json_response([ diff --git a/application/views/pages/services.php b/application/views/pages/services.php index 409f662a..796cb491 100755 --- a/application/views/pages/services.php +++ b/application/views/pages/services.php @@ -146,27 +146,11 @@ - - - + + + + + + diff --git a/assets/js/http/services_http_client.js b/assets/js/http/services_http_client.js index edc118b0..e44c2452 100644 --- a/assets/js/http/services_http_client.js +++ b/assets/js/http/services_http_client.js @@ -10,6 +10,17 @@ * ---------------------------------------------------------------------------- */ App.Http.Services = (function () { + /** + * Save (create or update) a service. + * + * @param {Object} service + * + * @return {Object} + */ + function save(service) { + return service.id ? update(service) : create(service); + } + /** * Create an service. * @@ -107,6 +118,7 @@ App.Http.Services = (function () { } return { + save, create, update, destroy, diff --git a/assets/js/pages/backend_services.js b/assets/js/pages/backend_services.js deleted file mode 100644 index 89d9d415..00000000 --- a/assets/js/pages/backend_services.js +++ /dev/null @@ -1,91 +0,0 @@ -/* ---------------------------------------------------------------------------- - * Easy!Appointments - Open Source Web Scheduler - * - * @package EasyAppointments - * @author A.Tselegidis - * @copyright Copyright (c) Alex Tselegidis - * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 - * @link https://easyappointments.org - * @since v1.0.0 - * ---------------------------------------------------------------------------- */ - -window.BackendServices = window.BackendServices || {}; - -/** - * Backend Services - * - * This namespace handles the js functionality of the backend services page. - * - * @module BackendServices - */ -(function (exports) { - 'use strict'; - - /** - * Contains the basic record methods for the page. - * - * @type {ServicesHelper} - */ - var helper; - - var servicesHelper = new ServicesHelper(); - - /** - * Default initialize method of the page. - * - * @param {Boolean} [defaultEventHandlers] Optional (true), determines whether to bind the default event handlers. - */ - exports.initialize = function (defaultEventHandlers) { - defaultEventHandlers = defaultEventHandlers || true; - - // Instantiate helper object (service helper by default). - helper = servicesHelper; - helper.resetForm(); - helper.filter(''); - helper.bindEventHandlers(); - - if (defaultEventHandlers) { - bindEventHandlers(); - } - - BackendServices.updateAvailableCategories(); - - Backend.placeFooterToBottom(); - }; - - /** - * Binds the default event handlers of the backend services page. - * - * Do not use this method if you include the "BackendServices" namespace on another page. - */ - function bindEventHandlers() { - // - } - - /** - * Update the service category list box. - * - * Use this method every time a change is made to the service categories db table. - */ - exports.updateAvailableCategories = function () { - var url = GlobalVariables.baseUrl + '/index.php/categories/search'; - - var data = { - csrf_token: GlobalVariables.csrfToken, - key: '' - }; - - $.post(url, data).done(function (response) { - GlobalVariables.categories = response; - var $select = $('#service-category'); - - $select.empty(); - - response.forEach(function (category) { - $select.append(new Option(category.name, category.id)); - }); - - $select.append(new Option('- ' + App.Lang.no_category + ' -', null)).val('null'); - }); - }; -})(window.BackendServices); diff --git a/assets/js/pages/backend_services_helper.js b/assets/js/pages/services.js similarity index 57% rename from assets/js/pages/backend_services_helper.js rename to assets/js/pages/services.js index dd5f046a..c8a7a4ef 100644 --- a/assets/js/pages/backend_services_helper.js +++ b/assets/js/pages/services.js @@ -9,35 +9,23 @@ * @since v1.0.0 * ---------------------------------------------------------------------------- */ -(function () { - 'use strict'; - - /** - * ServicesHelper - * - * This class contains the methods that will be used by the "Services" tab of the page. - * - * @class ServicesHelper - */ - function ServicesHelper() { - this.filterResults = {}; - this.filterLimit = 20; - } - - ServicesHelper.prototype.bindEventHandlers = function () { - var instance = this; +App.Pages.Services = (function () { + const $services = $('#services'); + let filterResults = {}; + let filterLimit = 20; + function bindEventHandlers() { /** * Event: Filter Services Form "Submit" * * @param {jQuery.Event} event */ - $('#services').on('submit', '#filter-services form', function (event) { + $services.on('submit', '#filter-services form', function (event) { event.preventDefault(); - var key = $('#filter-services .key').val(); + const key = $('#filter-services .key').val(); $('#filter-services .selected').removeClass('selected'); - instance.resetForm(); - instance.filter(key); + resetForm(); + filter(key); }); /** @@ -45,21 +33,22 @@ * * Display the selected service data to the user. */ - $('#services').on('click', '.service-row', function () { + $services.on('click', '.service-row', function () { if ($('#filter-services .filter').prop('disabled')) { $('#filter-services .results').css('color', '#AAA'); return; // exit because we are on edit mode } - var serviceId = $(this).attr('data-id'); + const serviceId = $(this).attr('data-id'); - var service = instance.filterResults.find(function (filterResult) { + const service = filterResults.find(function (filterResult) { return Number(filterResult.id) === Number(serviceId); }); // Add dedicated provider link. - var dedicatedUrl = GlobalVariables.baseUrl + '/index.php?service=' + encodeURIComponent(service.id); - var $link = $('', { + const dedicatedUrl = App.Utils.Url.siteUrl('?service=' + encodeURIComponent(service.id)); + + const $link = $('', { 'href': dedicatedUrl, 'html': [ $('', { @@ -70,7 +59,7 @@ $('#services .record-details h3').find('a').remove().end().append($link); - instance.display(service); + display(service); $('#filter-services .selected').removeClass('selected'); $(this).addClass('selected'); $('#edit-service, #delete-service').prop('disabled', false); @@ -79,8 +68,8 @@ /** * Event: Add New Service Button "Click" */ - $('#services').on('click', '#add-service', function () { - instance.resetForm(); + $services.on('click', '#add-service', function () { + resetForm(); $('#services .add-edit-delete-group').hide(); $('#services .save-cancel-group').show(); $('#services .record-details').find('input, select, textarea').prop('disabled', false); @@ -92,7 +81,7 @@ $('#service-duration').val('30'); $('#service-price').val('0'); $('#service-currency').val(''); - $('#service-category').val('null'); + $('#service-category').val(''); $('#service-availabilities-type').val('flexible'); $('#service-attendants-number').val('1'); }); @@ -102,19 +91,19 @@ * * Cancel add or edit of a service record. */ - $('#services').on('click', '#cancel-service', function () { - var id = $('#service-id').val(); - instance.resetForm(); + $services.on('click', '#cancel-service', function () { + const id = $('#service-id').val(); + resetForm(); if (id !== '') { - instance.select(id, true); + select(id, true); } }); /** * Event: Save Service Button "Click" */ - $('#services').on('click', '#save-service', function () { - var service = { + $services.on('click', '#save-service', function () { + const service = { name: $('#service-name').val(), duration: $('#service-duration').val(), price: $('#service-price').val(), @@ -122,30 +111,25 @@ description: $('#service-description').val(), location: $('#service-location').val(), availabilities_type: $('#service-availabilities-type').val(), - attendants_number: $('#service-attendants-number').val() + attendants_number: $('#service-attendants-number').val(), + id_categories: $('#service-category').val() || null }; - if ($('#service-category').val() !== 'null') { - service.id_categories = $('#service-category').val(); - } else { - service.id_categories = null; - } - if ($('#service-id').val() !== '') { service.id = $('#service-id').val(); } - if (!instance.validate()) { + if (!validate()) { return; } - instance.save(service); + save(service); }); /** * Event: Edit Service Button "Click" */ - $('#services').on('click', '#edit-service', function () { + $services.on('click', '#edit-service', function () { $('#services .add-edit-delete-group').hide(); $('#services .save-cancel-group').show(); $('#services .record-details').find('input, select, textarea').prop('disabled', false); @@ -156,9 +140,9 @@ /** * Event: Delete Service Button "Click" */ - $('#services').on('click', '#delete-service', function () { - var serviceId = $('#service-id').val(); - var buttons = [ + $services.on('click', '#delete-service', function () { + const serviceId = $('#service-id').val(); + const buttons = [ { text: App.Lang.cancel, click: function () { @@ -168,30 +152,15 @@ { text: App.Lang.delete, click: function () { - instance.delete(serviceId); + remove(serviceId); $('#message-box').dialog('close'); } } ]; - GeneralFunctions.displayMessageBox(App.Lang.delete_service, App.Lang.delete_record_prompt, buttons); + App.Utils.Message.show(App.Lang.delete_service, App.Lang.delete_record_prompt, buttons); }); - }; - - /** - * Remove the previously registered event handlers. - */ - ServicesHelper.prototype.unbindEventHandlers = function () { - $('#services') - .off('submit', '#filter-services form') - .off('click', '#filter-services .clear') - .off('click', '.service-row') - .off('click', '#add-service') - .off('click', '#cancel-service') - .off('click', '#save-service') - .off('click', '#edit-service') - .off('click', '#delete-service'); - }; + } /** * Save service record to database. @@ -199,59 +168,40 @@ * @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 url = GlobalVariables.baseUrl + '/index.php/services/' + (service.id ? 'update' : 'create'); - - var data = { - csrf_token: GlobalVariables.csrfToken, - service: JSON.stringify(service) - }; - - $.post(url, data).done( - function (response) { - Backend.displayNotification(App.Lang.service_saved); - this.resetForm(); - $('#filter-services .key').val(''); - this.filter('', response.id, true); - }.bind(this) - ); - }; + function save(service) { + App.Http.Services.save(service).then((response) => { + Backend.displayNotification(App.Lang.service_saved); + resetForm(); + $('#filter-services .key').val(''); + filter('', response.id, true); + }); + } /** * Delete a service record from database. * * @param {Number} id Record ID to be deleted. */ - ServicesHelper.prototype.delete = function (id) { - var url = GlobalVariables.baseUrl + '/index.php/services/destroy'; - - var data = { - csrf_token: GlobalVariables.csrfToken, - service_id: id - }; - - $.post(url, data).done( - function () { - Backend.displayNotification(App.Lang.service_deleted); - - this.resetForm(); - this.filter($('#filter-services .key').val()); - }.bind(this) - ); - }; + function remove(id) { + App.Http.Services.destroy(id).then(() => { + Backend.displayNotification(App.Lang.service_deleted); + resetForm(); + filter($('#filter-services .key').val()); + }); + } /** * Validates a service record. * * @return {Boolean} Returns the validation result. */ - ServicesHelper.prototype.validate = function () { + function validate() { $('#services .is-invalid').removeClass('is-invalid'); $('#services .form-message').removeClass('alert-danger').hide(); try { // Validate required fields. - var missingRequired = false; + let missingRequired = false; $('#services .required').each(function (index, requiredField) { if (!$(requiredField).val()) { @@ -275,12 +225,12 @@ $('#services .form-message').addClass('alert-danger').text(error.message).show(); return false; } - }; + } /** * Resets the service tab form back to its initial state. */ - ServicesHelper.prototype.resetForm = function () { + function resetForm() { $('#filter-services .selected').removeClass('selected'); $('#filter-services button').prop('disabled', false); $('#filter-services .results').css('color', ''); @@ -294,14 +244,14 @@ $('#services .record-details .is-invalid').removeClass('is-invalid'); $('#services .record-details .form-message').hide(); - }; + } /** * Display a service record into the service form. * * @param {Object} service Contains the service record data. */ - ServicesHelper.prototype.display = function (service) { + function display(service) { $('#service-id').val(service.id); $('#service-name').val(service.name); $('#service-duration').val(service.duration); @@ -312,9 +262,9 @@ $('#service-availabilities-type').val(service.availabilities_type); $('#service-attendants-number').val(service.attendants_number); - var categoryId = service.id_categories !== null ? service.id_categories : 'null'; + const categoryId = service.id_categories !== null ? service.id_categories : ''; $('#service-category').val(categoryId); - }; + } /** * Filters service records depending a string keyword. @@ -322,55 +272,41 @@ * @param {String} keyword This is used to filter the service records of the database. * @param {Number} selectId Optional, if set then after the filter operation the record with this * ID will be selected (but not displayed). - * @param {Boolean} display Optional (false), if true then the selected record will be displayed on the form. + * @param {Boolean} show Optional (false), if true then the selected record will be displayed on the form. */ - ServicesHelper.prototype.filter = function (keyword, selectId, display) { - display = display || false; + function filter(keyword, selectId = null, show = false) { + App.Http.Services.search(keyword, filterLimit).then((response) => { + filterResults = response; - var url = GlobalVariables.baseUrl + '/index.php/services/search'; + $('#filter-services .results').empty(); - var data = { - csrf_token: GlobalVariables.csrfToken, - keyword: keyword, - limit: this.filterLimit - }; + response.forEach(function (service, index) { + $('#filter-services .results').append(getFilterHtml(service)).append($('
')); + }); - $.post(url, data).done( - function (response) { - this.filterResults = response; + if (response.length === 0) { + $('#filter-services .results').append( + $('', { + 'text': App.Lang.no_records_found + }) + ); + } else if (response.length === filterLimit) { + $('