From: Chuck Scott Date: Tue, 27 Nov 2018 17:36:15 +0000 (-0500) Subject: Reworked Registration Levels & Charges page including new "Drag to Sort" feature. X-Git-Tag: v1.2.0^2~4^2 X-Git-Url: http://cvs2.gaslightmedia.com/gitweb/?a=commitdiff_plain;h=d020b456d30a682ea9f443bf571c56180f8cf1d2;p=WP-Plugins%2Fglm-member-db-registrations.git Reworked Registration Levels & Charges page including new "Drag to Sort" feature. --- diff --git a/classes/data/dataRegClass.php b/classes/data/dataRegClass.php old mode 100644 new mode 100755 index 164fea0..67b6d87 --- a/classes/data/dataRegClass.php +++ b/classes/data/dataRegClass.php @@ -143,6 +143,14 @@ class GlmDataRegistrationsRegClass extends GlmDataAbstract 'use' => 'a' ), + // Sort Order + 'sort_order' => array ( + 'field' => 'sort_order', + 'type' => 'integer', + 'required' => false, + 'use' => 'a' + ) + ); } diff --git a/classes/data/dataRegEvent.php b/classes/data/dataRegEvent.php index 76448b7..4f6667c 100755 --- a/classes/data/dataRegEvent.php +++ b/classes/data/dataRegEvent.php @@ -927,9 +927,6 @@ class GlmDataRegistrationsRegEvent extends GlmDataAbstract } // each reg_time } // non_time_specific - // Add Recurrence summary to event data -// $this->regEventData['recurrenceSummary'] = $recurrenceSummary; - // If recurrences is not requested - dump them now if (!$withRecurData) { unset($this->regEventData['recurrences']); @@ -938,7 +935,15 @@ class GlmDataRegistrationsRegEvent extends GlmDataAbstract // Restore status of extended data flag $this->postProcAddedEventData = $saveExtended; - // echo "
".print_r($this->regEventData,1)."
"; + // If we have good event data and there's levels listed, sort by specified sort_order + if ($this->regEventData && $this->regEventData['reg_class'] && count($this->regEventData['reg_class']) > 0) { + uasort($this->regEventData['reg_class'], function($a, $b) { + if ($a['sort_order'] == $b['sort_order']) { + return 0; + } + return ($a['sort_order'] < $b['sort_order']) ? -1 : 1; + }); + } return $this->regEventData; diff --git a/css/admin.css b/css/admin.css old mode 100644 new mode 100755 index a61a14d..7eba174 --- a/css/admin.css +++ b/css/admin.css @@ -32,32 +32,65 @@ padding-bottom: .7em; padding-top: 1em; } -.glm-class-label { - height: 1em; +.glm-reg-submit { + padding: 1rem; + position: absolute; + bottom: .3rem; + right: .5rem; +} +.glm-reg-gray { + color: gray; +} + +/* Admin Edit Levels and Charges Page */ +.UNKNOWN-level-edit-form { /* ????? */ + display: none; +} +.reg-level-container { + margin-bottom: 1em; + background-color: white; + padding: .25rem; + border: 1px solid black; + cursor: pointer; } -.glm-class-header { +.reg-level-display-container { + margin-bottom: 1em; +} +.reg-level-header { width: 99%; border-bottom-style: solid; padding-bottom: 1em; padding-top: 1em; } -.glm-reg-submit { - padding: 1rem; - position: absolute; - bottom: .3rem; - right: .5rem; +.reg-level-label { + height: 1em; } -.class-edit-form { +.reg-level-edit-container { display: none; + border: 1px solid black; + padding: 1em; + background-color: #f8ffff; + margin: 1em; } -.class-rate-container { - margin-top: 1em; - margin-left: 2em; +.reg-level-header { } -.glm-reg-gray { - color: gray; +.reg-level-label-container { + padding-bottom: .3em; +} +.reg-level-rates-container { + margin-left: 1em; } +.reg-rate-label-container { + margin-bottom: .5em; +} +.reg-rate-edit-container { + display: none; + border: 1px solid black; + padding: 1em; + background-color: #f8ffff; + margin: 1em; +} /* Styles for cartSummary.html output */ diff --git a/models/admin/ajax/levelsAndRatesEdit.php b/models/admin/ajax/levelsAndRatesEdit.php new file mode 100755 index 0000000..0ebca6f --- /dev/null +++ b/models/admin/ajax/levelsAndRatesEdit.php @@ -0,0 +1,413 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version 0.1 + */ + +// Load Members data abstract +//require_once GLM_MEMBERS_REGISTRATIONS_PLUGIN_CLASS_PATH . '/data/dataAccount.php'; + +/** + * This class performs the work of handling images passed to it via + * an AJAX call that goes through the WorPress AJAX Handler. + * + */ +class GlmMembersAdmin_ajax_levelsAndRatesEdit // extends GlmDataRegistrationsAccount +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + /** + * Plugin Configuration Data + * + * @var $config + * @access public + */ + public $config; + /** + * Required input not provided flag + * + * @var $requiredNotProvided + * @access public + */ + public $requiredNotProvided = false; + + /* + * Constructor + * + * This contructor sets up this model. At this time that only includes + * storing away the WordPress data object. + * + * @return object Class object + * + */ + public function __construct ($wpdb, $config) + { + + // Save WordPress Database object + $this->wpdb = $wpdb; + + // Save plugin configuration object + $this->config = $config; + + // Run constructor for data class +// parent::__construct(false, false); + + } + + /* + * Perform Model Action + * + * This model checks to see if the creditials passed in are correct. + * + * This model action does not return, it simply does it's work then calls die(); + * + * @param $actionData + * + * Echos JSON string as response and does not return + */ + public function modelAction( $actionData = false ) + { + // Setup response array + $response = array( + 'status' => false, + 'msg' => false + ); + + $option = filter_var( $_REQUEST['option'], FILTER_SANITIZE_STRING ); + + switch ( $option ) { + + case 'sortLevels': + + // Fields should be in correct order in the submitted array and keys should be sequential from 0 + foreach ($_REQUEST['sortedIds'] as $sortKey=>$sortVal) { + + // Strip "field_" from field ID number + $fieldId = preg_replace("/[^0-9]/", "", $sortVal); + + // Update the field with the key as the order field + $res = $this->wpdb->update( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_class', + array( 'sort_order' => $sortKey ), + array( 'id' => $fieldId ), + array( '%d' ), + array( '%d' ) + ); + + if ($res !== false) { + $response['status'] = true; + } else { + $response['msg'] = $this->wpdb->last_error; + } + } + + break; + + case 'addLevel': + case 'updateLevel': + + $request = filter_input_array( + INPUT_POST, + array( + 'eventId' => array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 1) + ), + 'levelId' => array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 1) + ), + 'name' => FILTER_SANITIZE_STRING, + 'descr' => FILTER_SANITIZE_STRING, + 'sort_order'=> array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 1) + ) + ) + ); + + $msg = ''; + + if ($option == 'addLevel') { + if ($request['eventId'] === false) {$msg .= "* Required Event ID not a positive integer.
";} + } else { + if ($request['levelId'] === false) {$msg .= "* Required Level ID not a positive integer.
";} + } + + if (trim($request['name']) == '') {$msg .= "* Level Name not provided
";} + if (trim($request['descr']) == '') {$msg .= "* Description not provided
";} + + if ($msg != '') { + $response['msg'] = 'Please check the following...

'.$msg."

"; + } else { + + // If we have good data + if ($request && isset($request['eventId']) && ($request['eventId']-0) > 0) { + + if ($option == 'addLevel') { + + // Add the new level + $res = $this->wpdb->insert( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_class', + array( + 'reg_event' => $request['eventId'], + 'name' => $request['name'], + 'descr' => $request['descr'], + 'sort_order' => $request['sort_order'] + ), + array( + '%d', + '%s', + '%s', + '%d' + ) + ); + + } else { + + // Update level + $res = $this->wpdb->update( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_class', + array( + 'name' => $request['name'], + 'descr' => $request['descr'], + ), + array( 'id' => $request['levelId'] ), + array( + '%s', + '%s' + ), + array( '%d' ) + ); + + } + + // If no error + if ($res !== false) { + $response['status'] = true; + if ($option == 'addLevel') { + $response['levelId'] = $this->wpdb->insert_id; + } + $response = array_merge($request, $response); // Appends or replaces $response values into $request + } else { + $response['msg'] = $this->wpdb->last_error; + } + + } else { + $response['msg'] = 'Add failed. Please check your data and try again.'; + } + + } + + break; + + case 'deleteLevel': + + $levelId = filter_var( $_REQUEST['levelId'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1))); + + if ($levelId && ($levelId-0) > 0 ) { + + // Delete all rates associated with this level + $this->wpdb->delete( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_rate', + array( 'reg_class' => $levelId ) + ); + $res = $this->wpdb->delete( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_class', + array( 'id' => $levelId ) + ); + + // If no error + if ($res) { + $response['status'] = true; + } else { + $response['msg'] = $this->wpdb->last_error; + } + + } + + break; + + case 'addRate': + case 'updateRate': + + $request = filter_input_array( + INPUT_POST, + array( + 'eventId' => array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 1) + ), + 'levelId' => array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 1) + ), + 'rateId' => array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 1) + ), + 'name' => FILTER_SANITIZE_STRING, + 'start_days' => array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 1) + ), + 'end_days' => array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 0) + ), + 'base_rate' => FILTER_VALIDATE_FLOAT, // Note that PHP filters don't validate range for float + 'per_registrant' => FILTER_VALIDATE_FLOAT, + 'registrant_credits'=> array( + 'filter' => FILTER_VALIDATE_INT, + 'options' => array('min_range' => 0) + ) + ) + ); + + // Sanity check all the values + $msg = ''; + + if ($option == 'addRate') { + if ($request['eventId'] === false) {$msg .= "* Required event ID not a positive integer.
";} + if ($request['levelId'] === false) {$msg .= "* Required registraion Level ID not a positive integer.
";} + } else { + if ($request['rateId'] === false) {$msg .= "* Required registraion Rate ID not a positive integer.
";} + } + + if (trim($request['name']) == '') {$msg .= "* Rate Name not provided
";} + if ($request['start_days'] === false) {$msg .= "* Start Days must be greater than 0.
";} + if ($request['end_days'] === false) {$msg .= "* End Days must not be negative.
";} + if ($request['start_days'] < $request['end_days']) {$msg .= "* Start days must be greater (earlier) than end days.
";} + if ($request['base_rate'] < 0) {$msg .= "* Bate Rate must not be negative.
";} + if ($request['per_registrant'] < 0) {$msg .= "* Rate Per Registrant must not be negative.
";} + if ($request['registrant_credits'] === false) {$msg .= "* Required Registrant Credits must not be negative.
";} + + + if ($msg != '') { + $response['msg'] = 'Please check the following...

'.$msg."

"; + } else { + + // If we have good data + if ($request && isset($request['eventId']) && ($request['eventId']-0) > 0) { + + if ($option == 'addRate') { + + // Add the new rate + $res = $this->wpdb->insert( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_rate', + array( + 'reg_event' => $request['eventId'], + 'reg_class' => $request['levelId'], + 'name' => $request['name'], + 'start_days' => $request['start_days'], + 'end_days' => $request['end_days'], + 'base_rate' => $request['base_rate'], + 'per_registrant' => $request['per_registrant'], + 'registrant_credits' => $request['registrant_credits'] + ), + array( + '%d', // Event ID + '%d', // Level ID + '%s', // Name + '%d', // Start Days + '%d', // End Days + '%d', // Base Rate + '%f', // Per Registrant + '%d' // Registrant Credits + ) + ); + + } else { + + // Update rate + $res = $this->wpdb->update( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_rate', + array( + 'name' => $request['name'], + 'start_days' => $request['start_days'], + 'end_days' => $request['end_days'], + 'base_rate' => $request['base_rate'], + 'per_registrant' => $request['per_registrant'], + 'registrant_credits' => $request['registrant_credits'] + ), + array( 'id' => $request['rateId'] ), + array( + '%s', // Name + '%d', // Start Days + '%d', // End Days + '%f', // Base Rate + '%f', // Per Registrant + '%d' // Registrant Credits + ), + array( '%d' ) + ); + + } + + // If no error + if ($res !== false) { + $response['status'] = true; + if ($option == 'addRate') { + $response['rateId'] = $this->wpdb->insert_id; + } + $response = array_merge($request, $response); // Appends or replaces $response values into $request + } else { + $response['msg'] = $this->wpdb->last_error; + } + + } else { + $response['msg'] = 'Add failed. Please check your data and try again.'; + } + + } + + break; + + case 'deleteRate': + + $rateId = filter_var( $_REQUEST['rateId'], FILTER_VALIDATE_INT, array('options' => array('min_range' => 1))); + + if ($rateId && ($rateId-0) > 0 ) { + + // Delete all rates associated with this level + $res = $this->wpdb->delete( + GLM_MEMBERS_REGISTRATIONS_PLUGIN_DB_PREFIX.'reg_rate', + array( 'id' => $rateId ) + ); + + // If no error + if ($res !== false) { + $response['status'] = true; + } else { + $response['msg'] = $this->wpdb->last_error; + } + + } + + break; + + } + + if ($response) { + header('Content-type:application/json;charset=utf-8', true); + echo json_encode( $response ); + } + wp_die(); + } + +} diff --git a/models/admin/registrations/events.php b/models/admin/registrations/events.php old mode 100644 new mode 100755 diff --git a/models/admin/registrations/events_configureEvent.php b/models/admin/registrations/events_configureEvent.php old mode 100644 new mode 100755 index 347fde1..a78e4c6 --- a/models/admin/registrations/events_configureEvent.php +++ b/models/admin/registrations/events_configureEvent.php @@ -14,60 +14,18 @@ */ $regEvent = false; -$regEventJSON = false; -$regClassesJSON = false; -$regTimesJSON = false; $regEventUpdated = false; $regEventUpdateError = false; -$scripts = array( - 'backbone-local' => 'js/lib/backbone.localStorage.min.js', - 'regApp' => 'js/adminRegApp.js', -); -foreach ( $scripts as $scriptName => $scriptPath ) { - wp_register_script( - $scriptName, - GLM_MEMBERS_REGISTRATIONS_PLUGIN_URL . $scriptPath, - array( 'jquery', 'backbone', 'underscore' ), - '1.0', - true - ); -} -wp_enqueue_script( array( 'jquery', 'backbone' ) ); -wp_enqueue_script( array_keys( $scripts ) ); -$regEvent = array(); - -// Get all current registration event data -$regEvent = $this->getEventConfig($regEventID, false, false, true); - -// Make all arrays of arrays non-associative to make Backbone happy -if (is_array($regEvent['reg_class'])) { - foreach ($regEvent['reg_class'] as $k=>$v) { - if (is_array($regEvent['reg_class'][$k]['reg_rate'])) { - $regEvent['reg_class'][$k]['reg_rate'] = array_values($regEvent['reg_class'][$k]['reg_rate']); - } - } +// Get Event ID and if an integer try to get the event data +$regEventId = filter_input(INPUT_GET, 'regEventID', FILTER_VALIDATE_INT); +if ($regEventId) { + $regEvent = $this->getEventConfig($regEventId, false, false, true); } -if (is_array($regEvent['reg_class'])) { - $regEvent['reg_class'] = array_values($regEvent['reg_class']); - $regClassesJSON = json_encode($regEvent['reg_class']); -} -if (is_array($regEvent['reg_time'])) { - $regEvent['reg_time'] = array_values($regEvent['reg_time']); - $regTimesJSON = json_encode($regEvent['reg_time']); -} - -// Get rid of class and time arrays so we just have the event data -unset($regEvent['reg_class']); -unset($regEvent['reg_time']); -$regEventJSON = json_encode($regEvent); - +//echo "
".print_r($regEvent,1)."
";exit; $templateData = array( 'regEvent' => $regEvent, - 'regEventJSON' => $regEventJSON, - 'regClassesJSON' => $regClassesJSON, - 'regTimesJSON' => $regTimesJSON, 'regEventUpdated' => $regEventUpdated, 'regEventUpdateError' => $regEventUpdateError ); diff --git a/models/admin/registrations/events_dashboard.php b/models/admin/registrations/events_dashboard.php index c905d25..5601a7c 100755 --- a/models/admin/registrations/events_dashboard.php +++ b/models/admin/registrations/events_dashboard.php @@ -33,8 +33,6 @@ $alphaWhere = ''; $where = ' TRUE '; $haveRequests = false; - - // If doing alpha list if (isset($_REQUEST['alpha'])) { $actionData['request']['alpha'] = $_REQUEST['alpha']; @@ -58,6 +56,24 @@ if (isset($_REQUEST['text_search']) && trim($_REQUEST['text_search'] != '')) { $textSearch = stripslashes($textSearch); } +// Check if we're doing paging +if ( isset( $_REQUEST['pageSelect'] ) ) { + + // If request is for Next + if ( $_REQUEST['pageSelect'][0] == 'N' ) { + $newStart = $_REQUEST['nextStart'] - 0; + + // Otherwise it must be Previous + } else { + $newStart = $_REQUEST['prevStart'] - 0; + } + + if ($newStart > 0) { + $start = $newStart; + } + +} + // Get full list for all other filters, but not filtered by alpha (that would be silly) $alphaList = $this->getAlphaList(''); diff --git a/setup/validActions.php b/setup/validActions.php old mode 100644 new mode 100755 index 14cae63..88b1646 --- a/setup/validActions.php +++ b/setup/validActions.php @@ -70,7 +70,8 @@ $glmMembersRegistrationsAddOnValidActions = array( 'setupEventRegQueue' => GLM_MEMBERS_REGISTRATIONS_PLUGIN_SLUG, 'runEventRegQueue' => GLM_MEMBERS_REGISTRATIONS_PLUGIN_SLUG, 'getAuthorizeNetSeal' => GLM_MEMBERS_REGISTRATIONS_PLUGIN_SLUG, - 'regPayPal' => GLM_MEMBERS_REGISTRATIONS_PLUGIN_SLUG + 'regPayPal' => GLM_MEMBERS_REGISTRATIONS_PLUGIN_SLUG, + 'levelsAndRatesEdit' => GLM_MEMBERS_REGISTRATIONS_PLUGIN_SLUG ), 'registrations' => array( 'index' => GLM_MEMBERS_REGISTRATIONS_PLUGIN_SLUG, diff --git a/views/admin/registrations/eventEditLevels.html b/views/admin/registrations/eventEditLevels.html index 8bb9699..54966b8 100755 --- a/views/admin/registrations/eventEditLevels.html +++ b/views/admin/registrations/eventEditLevels.html @@ -1,76 +1,73 @@ {include file='admin/registrations/eventHeader.html'} {include file='admin/registrations/eventSubTabs.html'} -

- {if $regEventUpdated}{$terms.reg_term_registration_cap} {$terms.reg_term_event_cap} Updated{/if} - {if $regEventUpdateError}{$terms.reg_term_registration_cap} {$terms.reg_term_event_cap} Update Error{/if} - {if $regEventAdded}{$terms.reg_term_registration_cap} {$terms.reg_term_event_cap} Added{/if} -

- - {* Event Registration App - Backbone.js *} - {* Underscore Templates for the Event Registration App *} - - {literal} - - - - + {$terms.reg_term_level_cap} Name: + + Description: +

Required fields are in red.

+ +
+ {if $level.reg_rate} + {foreach $level.reg_rate as $rate} - +
+ + {/foreach} {* Rate *} + {/if} + - {/literal} + -
+ {/foreach} {* Reg Level *} +{/if} +
+ +
+
+
+
+
+ Edit + Delete + Add Rate +
+
+

{ pendingName }

+
+
+
{ pendingDescr }
+
+
+
+
+ Cancel + Update +
+ {$terms.reg_term_level_cap} Name: +
+ Description: +

Required fields are in red.

+
+
+
- {* Bootstrap the models needed on page load *} - {* Need to have RegEvent model created *} - {* And create the RegClasses collection *} - - + /* + * Operations not using delegated events + */ + + // Level dragable + $('#regLevelsContainer').sortable({ + items: '.reg-level-container', + update: function(event, ui) { + + // Create an array of the fields in the current order by field ID (field_{ id }) + var sortedIds = $(this).sortable('toArray'); + + updatingDialog(); + + // Send new order via AJAX + var formData = { + 'action': 'glm_members_admin_ajax', + 'glm_action': 'levelsAndRatesEdit', + 'option': 'sortLevels', + 'sortedIds': sortedIds + }; + + updatingDialog(); + + $.ajax({ + type: 'POST', + url: '{$ajaxUrl}', + data: formData, + encode: true, + dataType: 'json' + }) + .done( function(data) { + + updatingDialogClose(); + + if (data.status == false) { + var msg = 'An error occurred attempting to save the new level order.'; + if (data.msg) { + msg += data.msg; + } + alert(msg); + } + }) + .fail( function() { + updatingDialogClose(); + alert(failMsg); + }) + } + + }); + + // Add Level + $('.reg-level-add-button').on('click', function() { + + if (!checkEditActive()) { + + levelEditId = 'newId'; + editActive = true; + newEdit = true; + + // Get level template + var levelTemplate = $('#regLevelTemplate').html(); + + // Replace the ID with 'newId' + levelTemplate = levelTemplate.replace(/{ id }/g, 'newId'); + + // Initialize all data fields + levelTemplate = levelTemplate.replace(/{ pendingName }/g, ''); + levelTemplate = levelTemplate.replace(/{ pendingDescr }/g, ''); + + // Append to level + $('#regLevelsContainer').append(levelTemplate); + + $('#regLevelDisplayContainer_newId').hide(); + $('#regLevelEditContainer_newId').show(); + + disableSorting(); + } +// updatingDialogClose(); + }); + + function disableSorting() { + $('#regLevelsContainer').sortable('disable'); + $('.reg-level-container').css('cursor', 'default'); + } + function enableSorting() { + $('#regLevelsContainer').sortable('enable'); + $('.reg-level-container').css('cursor', 'pointer'); + } + + function checkEditActive() { + if (editActive) { + openMsgDialog('Please finish your current edit or update form first.'); + } + return editActive; + } + function openMsgDialog(msg) { + $('#msgDialog').dialog({ + modal: true, + resizable: false, + dragable: false, + closeOnEscape: true, + width: 'auto' + }); + $('#msgDialog').html(msg); + } + function updatingDialog() { + openMsgDialog('UPDATING: Please wait!'); + } + function updatingDialogClose() { + $('#msgDialog').dialog('close'); + } + + }); + {include file='admin/footer.html'} diff --git a/views/admin/registrations/eventsDashboard.html b/views/admin/registrations/eventsDashboard.html index 0bad13f..c8d5d52 100755 --- a/views/admin/registrations/eventsDashboard.html +++ b/views/admin/registrations/eventsDashboard.html @@ -19,7 +19,6 @@ -

Total found: {$regEventsCount}  

@@ -93,9 +92,10 @@ {if $paging} - - + + {/if} +