/** * 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', /** * Use this WorkingPlan class instance to perform actions on the page's working plan * tables. */ wp: {}, /** * 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 setting values from database. $.each(GlobalVariables.settings.system, function(index, setting) { $('input[data-field="' + setting.name + '"]').val(setting.value); }); var workingPlan = {}; $.each(GlobalVariables.settings.system, function(index, setting) { if (setting.name == 'company_working_plan') { workingPlan = $.parseJSON(setting.value); return false; } }); BackendSettings.wp = new WorkingPlan(); BackendSettings.wp.setup(workingPlan); BackendSettings.wp.timepickers(false); // Book Advance Timeout Spinner $('#book-advance-timeout').spinner({ 'min': 0 }); // Load user settings into form $('#user-id').val(GlobalVariables.settings.user.id); $('#first-name').val(GlobalVariables.settings.user.first_name); $('#last-name').val(GlobalVariables.settings.user.last_name); $('#email').val(GlobalVariables.settings.user.email); $('#mobile-number').val(GlobalVariables.settings.user.mobile_number); $('#phone-number').val(GlobalVariables.settings.user.phone_number); $('#address').val(GlobalVariables.settings.user.address); $('#city').val(GlobalVariables.settings.user.city); $('#state').val(GlobalVariables.settings.user.state); $('#zip-code').val(GlobalVariables.settings.user.zip_code); $('#notes').val(GlobalVariables.settings.user.notes); $('#username').val(GlobalVariables.settings.user.settings.username); $('#password, #retype-password').val(''); if (GlobalVariables.settings.user.settings.notifications == true) { $('#user-notifications').addClass('active'); } else { $('#user-notifications').removeClass('active'); } // Set default settings helper. BackendSettings.settings = new SystemSettings(); if (bindEventHandlers) { BackendSettings.bindEventHandlers(); $('#settings-page .nav li').first().addClass('active'); $('#settings-page .nav li').first().find('a').trigger('click'); } // Apply Privileges if (GlobalVariables.user.privileges.system_settings.edit == false) { $('#general, #business-logic').find('select, input, textarea').prop('readonly', true); $('#general, #business-logic').find('button').prop('disabled', true); } if (GlobalVariables.user.privileges.user_settings.edit == false) { $('#user').find('select, input, textarea').prop('readonly', true); $('#user').find('button').prop('disabled', true); } Backend.placeFooterToBottom(); }, /** * Bind the backend/settings default event handlers. This method depends on the * backend/settings html, so do not use this method on a different page. */ bindEventHandlers: function() { BackendSettings.wp.bindEventHandlers(); /** * Event: Tab "Click" * * Change the visible tab contents. */ $('.tab').click(function() { // Bootstrap has a bug with toggle buttons. Their toggle state is lost when the // button is hidden or shown. Show before anything else we need to store the toggle // and apply it whenever the user tab is clicked.. var areNotificationsActive = $('#user-notifications').hasClass('active'); $(this).parent().find('.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(); // Apply toggle state to user notifications button. if (areNotificationsActive) { $('#user-notifications').addClass('active'); } else { $('#user-notifications').removeClass('active'); } } Backend.placeFooterToBottom(); }); /** * Event: Save Settings Button "Click" * * Store the setting changes into the database. */ $('.save-settings').click(function() { var settings = BackendSettings.settings.get(); BackendSettings.settings.save(settings); ////////////////////////////////////////////// //console.log('Settings To Save: ', settings); ////////////////////////////////////////////// }); /** * Event: Username "Focusout" * * When the user leaves the username input field we will need to check if the username * is not taken by another record in the system. Usernames must be unique. */ $('#username').focusout(function() { var $input = $(this); if ($input.prop('readonly') == true || $input.val() == '') return; var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_validate_username'; var postData = { 'username': $input.val(), 'record_exists': ($input.parents().eq(2).find('#user-id').val() != '') ? true : false }; $.post(postUrl, postData, function(response) { /////////////////////////////////////////////////////// //console.log('Validate Username Response:', response); /////////////////////////////////////////////////////// if (!GeneralFunctions.handleAjaxExceptions(response)) return; if (response == false) { $input.css('border', '2px solid red'); Backend.displayNotification('Username already exists.'); } else { $input.css('border', ''); } }, 'json'); }); } }; /** * "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 (!GeneralFunctions.handleAjaxExceptions(response)) return; Backend.displayNotification('Settings saved successfully!'); // Update the logo title on the header. $('#header-logo span').text($('#company-name').val()); // We need to refresh the working plan. var workingPlan = BackendSettings.wp.get(); $('.breaks').empty(); BackendSettings.wp.setup(workingPlan); BackendSettings.wp.timepickers(false); }, '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 = []; // General Settings Tab $('#general input').each(function() { settings.push({ 'name': $(this).attr('data-field'), 'value': $(this).val() }); }); // Business Logic Tab settings.push({ 'name': 'company_working_plan', 'value': JSON.stringify(BackendSettings.wp.get()) }); settings.push({ 'name': 'book_advance_timeout', 'value': $('#book-advance-timeout').val() }); return settings; }; /** * Validate the settings data. If the validation fails then display a * message to the user. * * @returns {bool} Returns the validation result. */ SystemSettings.prototype.validate = function() { $('#general .required').css('border', ''); try { // Validate required fields. var missingRequired = false; $('#general .required').each(function() { if ($(this).val() == '' || $(this).val() == undefined) { $(this).css('border', '2px solid red'); missingRequired = true; } }); if (missingRequired) { throw 'Fields with * are required.'; } // Validate company email address. if (!GeneralFunctions.validateEmail($('#company-email').val())) { $('#company-email').css('border', '2px solid red'); throw 'Invalid email address!'; } return true; } catch(exc) { Backend.displayNotification(exc); return false; } }; /** * "User Settings" Tab Helper * @class UserSettings */ var UserSettings = function() {}; /** * Get the settings data for the user settings. * * @returns {object} Returns the user settings array. */ UserSettings.prototype.get = function() { var user = { 'id': $('#user-id').val(), 'first_name': $('#first-name').val(), 'last_name': $('#last-name').val(), 'email': $('#email').val(), 'mobile_number': $('#mobile-number').val(), 'phone_number': $('#phone-number').val(), 'address': $('#address').val(), 'city': $('#city').val(), 'state': $('#state').val(), 'zip_code': $('#zip-code').val(), 'notes': $('#notes').val(), 'settings': { 'username': $('#username').val(), 'notifications': $('#user-notifications').hasClass('active') } }; if ($('#password').val() != '') { user.settings.password = $('#password').val(); } return user; }; /** * Store the user settings into the database. * * @param {array} settings Contains the user settings. */ UserSettings.prototype.save = function(settings) { if (!BackendSettings.settings.validate(settings)) { Backend.displayNotification('User settings are invalid! Please review your settings ' + 'and try again.'); return; // Validation failed, do not procceed. } var postUrl = GlobalVariables.baseUrl + 'backend_api/ajax_save_settings'; var postData = { 'type': BackendSettings.SETTINGS_USER, 'settings': JSON.stringify(settings) }; $.post(postUrl, postData, function(response) { ////////////////////////////////////////////////////////// console.log('Save User Settings Response: ', response); ////////////////////////////////////////////////////////// if (!GeneralFunctions.handleAjaxExceptions(response)) return; Backend.displayNotification('Settings saved successfully!'); // Update footer greetings. $('#footer-user-display-name').text('Hello, ' + $('#first-name').val() + ' ' + $('#last-name').val()); }, 'json'); }; /** * Validate the settings data. If the validation fails then display a * message to the user. * * @returns {bool} Returns the validation result. */ UserSettings.prototype.validate = function() { $('#user .required').css('border', ''); $('#user').find('#password, #retype-password').css('border', ''); try { // Validate required fields. var missingRequired = false; $('#user .required').each(function() { if ($(this).val() == '' || $(this).val() == undefined) { $(this).css('border', '2px solid red'); missingRequired = true; } }); if (missingRequired) { throw 'Fields with * are required.'; } // Validate passwords (if provided). if ($('#password').val() != $('#retype-password').val()) { $('#password, #retype-password').css('border', '2px solid red'); throw 'Passwords mismatch!'; } // Validate user email. if (!GeneralFunctions.validateEmail($('#email').val())) { $('#email').css('border', '2px solid red'); throw 'Invalid email address!'; } return true; } catch(exc) { Backend.displayNotification(exc); return false; } };