From 2b970132908800af247a90180a310f0eb64472c4 Mon Sep 17 00:00:00 2001 From: Laury GvR Date: Wed, 26 Oct 2016 16:14:05 -0400 Subject: [PATCH] BROKEN Work in progress for adding event Amenities Amenities are added to the Edit Event form - but they are not functional. A new amenity can be added successfully but is then not attached to the event. The "Add a new amenity" popup currently has a needless dropdown but needs to optimally be like the "Add an amenity" in the member DB settings. It will in fact -not- be like the category button in that it shall nto have a parent, but needs to show the amenity groups, which are not yet properly handled in the model. Then the corresponding button for adding amenities, along with the one for adding categories, needs to not be displayed if the user lacks admin privileges. --- classes/data/dataAmenities.php | 265 ++++++++++ classes/data/dataCategories.php | 34 +- classes/data/dataEventAmenities.php | 339 +++++++++++++ classes/data/dataEventCategories.php | 2 +- classes/data/dataEventGroups.php | 130 +++++ classes/data/dataEvents.php | 4 +- classes/data/dataLocations.php | 8 +- classes/data/dataManagement.php | 22 +- index.php | 2 +- models/admin/events/index.php | 36 ++ models/admin/events/list.php | 113 ++++- models/admin/settings/eventAmenities.php | 293 +++++++++++ models/admin/settings/eventCategories.php | 2 +- setup/adminTabs.php | 14 + .../create_database_V0.0.22.sql | 200 -------- .../create_database_V0.1.0.sql | 250 ++++++++++ setup/databaseScripts/dbVersions.php | 2 + .../update_database_V0.0.23.sql | 51 ++ .../update_database_V0.1.0.sql | 18 + setup/validActions.php | 3 +- views/admin/events/edit.html | 121 ++++- views/admin/events/editStatus.html | 81 +++- views/admin/management/events.html | 55 ++- views/admin/member/add.html | 168 +++---- views/admin/settings/eventAmenities.html | 456 ++++++++++++++++++ 25 files changed, 2332 insertions(+), 337 deletions(-) create mode 100644 classes/data/dataAmenities.php create mode 100644 classes/data/dataEventAmenities.php create mode 100644 classes/data/dataEventGroups.php create mode 100644 models/admin/settings/eventAmenities.php delete mode 100644 setup/databaseScripts/create_database_V0.0.22.sql create mode 100644 setup/databaseScripts/create_database_V0.1.0.sql create mode 100644 setup/databaseScripts/update_database_V0.0.23.sql create mode 100644 setup/databaseScripts/update_database_V0.1.0.sql create mode 100644 views/admin/settings/eventAmenities.html diff --git a/classes/data/dataAmenities.php b/classes/data/dataAmenities.php new file mode 100644 index 0000000..b21ea3a --- /dev/null +++ b/classes/data/dataAmenities.php @@ -0,0 +1,265 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataEvents.php,v 1.0 2011/01/25 19:31:47 cscott Exp $ + */ + +/** + * GlmDataEventsAmenities class + * + * PHP version 5 + * + * @category Data + * @package GLM Member DB + * @author Chuck Scott + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott + * Exp $ + */ +class GlmDataEventsAmenities extends GlmDataAbstract +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + /** + * Plugin Configuration Data + * + * @var $config + * @access public + */ + public $config; + /** + * Data Table Name + * + * @var $table + * @access public + */ + public $table; + /** + * Field definitions + * + * 'type' is type of field as defined by the application + * text Regular text field + * pointer Pointer to an entry in another table + * 'filters' is the filter name for a particular filter ID in PHP filter + * functions + * See PHP filter_id() + * + * 'use' is when to use the field + * l = List + * g = Get + * n = New + * i = Insert + * e = Edit + * u = Update + * d = Delete + * a = All + * + * @var $ini + * @access public + */ + public $fields = false; + /** + * MemberInfo DB object + * + * @var $MemberInfo + * @access public + */ + public $MemberInfo; + + /** + * Constructor + * + * @param object $d database connection + * @param array $config Configuration array + * @param bool $limitedEdit Flag to say indicate limited edit requested + * + * @return void + * @access public + */ + public function __construct($wpdb, $config, $limitedEdit = false) + { + + // If this class is not being extended along with existing $wpdb and $config + if (!$this->wpdb) { + + // Save WordPress Database object + $this->wpdb = $wpdb; + + // Save plugin configuration object + $this->config = $config; + + } + + /* + * Table Name + */ + $this->table = GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX . 'amenities'; + + /* + * Table Data Fields + */ + $this->fields = array( + + 'id' => array( + 'field' => 'id', + 'type' => 'integer', + 'view_only' => true, + 'use' => 'a', + ), + + // Active Flag + 'active' => array ( + 'field' => 'active', + 'type' => 'checkbox', + 'default' => false, + 'use' => 'a' + ), + + // Name + 'name' => array( + 'field' => 'name', + 'type' => 'text', + 'required' => true, + 'unique' => true, + 'use' => 'a', + ), + + // Description + 'descr' => array( + 'field' => 'descr', + 'type' => 'text', + 'use' => 'a', + ), + + // Short Description + 'short_descr' => array( + 'field' => 'short_descr', + 'type' => 'text', + 'use' => 'a', + ), + + // Uses Value + 'uses_value' => array( + 'field' => 'uses_value', + 'type' => 'checkbox', + 'use' => 'a', + ), + + ); + + } + + /** + * Entry Post Processing Call-Back Method + * + * Perform post-processing for all result entries. + * + * In this case we're using it to append an array of amenity + * data to each member result and also sort by member name. + * + * @param array $r Array of field result data for a single entry + * @param string $a Action being performed (l, i, g, ...) + * + * @return object Class object + * + */ + public function entryPostProcessing($r, $a) + { + return $r; + } + + + /** + * Add a amenity using supplied parameters + * + * @param string $name Amenity Name + * @param mixed $parent Existing Parent ID or name of parent to add + * + * @return integer ID of new amenity or false if failed + * + * @access public + */ + + public function addAmenity($name) { + + $amenityID = false; + + // Filter new amenity name + $name = filter_var($name); + if ($name == false || trim($name) == '') { + return false; + } + + // Check if the new amenity name already exists + $sql = " + SELECT id + FROM ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."amenities + WHERE name = '$name' + ;"; + $existing = $this->wpdb->get_row($sql, ARRAY_A); + + if ($existing['id']) { + + $amenityID = $existing['id']; + + } else { + + // Try to add the new amenity + $sql = " + INSERT INTO ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."amenities + ( name ) + VALUES + ( '".addslashes($name)."' ) + ;"; + $this->wpdb->query($sql); + $amenityID = $this->wpdb->insert_id; + + } + + if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) { + glmMembersAdmin::addNotice("Amenity added: name = $name, ID = $amenityID", 'DataBlock', "addAmenity()"); + } + + return $amenityID; + + } + + /** + * getAmenitiesWithCurrentEvents + * + * Returns a list of amenities ordered by name that have an event with + * current event times. + * + * @access public + * @return void + */ + public function getAmenitiesWithCurrentEvents() + { + $where = " T.id IN ( + SELECT amenity + FROM " . GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX . "amenity_event + WHERE event IN ( + SELECT event + FROM " . GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX . "times + WHERE active + ) + ) "; + $order = "T.name"; + return $this->getList($where, $order); + } + +} diff --git a/classes/data/dataCategories.php b/classes/data/dataCategories.php index 20c4232..2d339e7 100644 --- a/classes/data/dataCategories.php +++ b/classes/data/dataCategories.php @@ -124,31 +124,31 @@ class GlmDataEventsCategories extends GlmDataAbstract // Name 'name' => array( - 'field' => 'name', - 'type' => 'text', - 'required' => true, - 'unique' => true, - 'use' => 'a' + 'field' => 'name', + 'type' => 'text', + 'required' => true, + 'unique' => true, + 'use' => 'a' ), // Description 'descr' => array( - 'field' => 'descr', - 'type' => 'text', - 'use' => 'a' + 'field' => 'descr', + 'type' => 'text', + 'use' => 'a' ), // Parent - for adding, deleting and editing, has selection tabels 'parent' => array( - 'field' => 'parent', - 'type' => 'pointer', - 'p_table' => GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX . 'categories', - 'p_field' => 'name', - 'p_orderby' => 'name', - 'p_blank' => true, - 'force_list' => true, - 'required' => false, - 'use' => 'a' + 'field' => 'parent', + 'type' => 'pointer', + 'p_table' => GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX . 'categories', + 'p_field' => 'name', + 'p_orderby' => 'name', + 'p_blank' => true, + 'force_list' => true, + 'required' => false, + 'use' => 'a' ) ); diff --git a/classes/data/dataEventAmenities.php b/classes/data/dataEventAmenities.php new file mode 100644 index 0000000..b046d8b --- /dev/null +++ b/classes/data/dataEventAmenities.php @@ -0,0 +1,339 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataEvents.php,v 1.0 2011/01/25 19:31:47 cscott Exp $ + */ + +/** + * GlmDataEvent class + * + * PHP version 5 + * + * @category Data + * @package GLM Member DB + * @author Chuck Scott + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott + * Exp $ + */ +class GlmDataEventsEventAmenities extends GlmDataAbstract +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + /** + * Plugin Configuration Data + * + * @var $config + * @access public + */ + public $config; + /** + * Data Table Name + * + * @var $table + * @access public + */ + public $table; + /** + * Field definitions + * + * 'type' is type of field as defined by the application + * text Regular text field + * pointer Pointer to an entry in another table + * 'filters' is the filter name for a particular filter ID in PHP filter + * functions + * See PHP filter_id() + * + * 'use' is when to use the field + * l = List + * g = Get + * n = New + * i = Insert + * e = Edit + * u = Update + * d = Delete + * a = All + * + * @var $ini + * @access public + */ + public $fields = false; + /** + * MemberInfo DB object + * + * @var $MemberInfo + * @access public + */ + public $MemberInfo; + + /** + * Constructor + * + * @param object $d database connection + * @param array $config Configuration array + * @param bool $limitedEdit Flag to say indicate limited edit requested + * + * @return void + * @access public + */ + public function __construct($wpdb, $config, $limitedEdit = false) + { + + // If this class is not being extended along with existing $wpdb and $config + if (!$this->wpdb) { + + // Save WordPress Database object + $this->wpdb = $wpdb; + + // Save plugin configuration object + $this->config = $config; + + } + + /* + * Table Name + */ + $this->table = GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX . 'amenity_event'; + + /* + * Table Data Fields + */ + + $this->fields = array ( + + 'id' => array ( + 'field' => 'id', + 'type' => 'integer', + 'view_only' => true, + 'use' => 'a' + ), + + // Event ID + 'event' => array( + 'field' => 'event', + 'type' => 'integer', + 'required' => true, + 'use' => 'a' + ), + + // Amenity ID + 'amenity' => array( + 'field' => 'amenity', + 'type' => 'integer', + 'required' => true, + 'use' => 'a' + ), + + // Amenity Name - for easy reference + 'amenity_name' => array( + 'field' => 'amenity', + 'as' => 'amenity_name', + 'type' => 'pointer', + 'p_table' => GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX . 'amenities', + 'p_field' => 'name', + 'p_orderby' => 'name', + 'use' => 'gl' + ) + + + ); + + } + + /* + * Entry Post Processing Call-Back Method + * + * Perform post-processing for all result entries. + * + * In this case we're using it to append an array of amenity + * data to each member result and also sort by member name. + * + * @param array $r Array of field result data for a single entry + * @param string $a Action being performed (l, i, g, ...) + * + * @return object Class object + * + */ + public function entryPostProcessing($r, $a) + { + return $r; + } + + /* + * Get list of amenities with parent information + * + * @param integer $eventID Optional event ID to match + * Used to find all amenities for a particular event ID + * + * @param integer $amenity Optional amenity ID to match + * Used to find all event records for a particular amenity + * + * NOTE: Both parameters above can't be used at the same time + * + * @return array List of selected amenities + * + * @access public + */ + + public function getListWithParents($eventID = false, $amenity = false) + { + + $where = ''; + + if ($amenity) { + $where = "WHERE T.amenity = $amenity"; + } elseif ($ventID) { + $where = "WHERE T.event = $eventID"; + } + + $sql = " + SELECT T.amenity, T.event, + ( + SELECT name + FROM ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."amenities + WHERE id = T.amenity + ) AS amenity_name + FROM ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."amenity_event T + $where + ;"; + $list = $this->wpdb->get_results($sql, ARRAY_A); + + if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) { + glmMembersAdmin::addNotice($sql, 'DataBlock', "DataAbstract - getListWithParents() query"); + glmMembersAdmin::addNotice($list, 'DataBlock', 'getListWithParents() data'); + } + + return $list; + + } + + /** + * Use supplied amenity ID list to set selected amenities for this + * event record. Any others that were set will be cleared. + * + * @param integer $eventID Event Record ID + * @param array $selectedAmenities Array of selected amenity IDs (key is also amenity ID) + * + * @return array List of selected amenities + * + * @access public + */ + + public function setEventAmenities($eventID, $selectedAmenities) + { + + // Check supplied data + if (!is_int($eventID) || $eventID <=0 || !is_array($selectedAmenities) || count($selectedAmenities) == 0 ) { + return false; + } + + // Get current list + $current = $this->getList("T.event = $eventID"); + + // If we have any currently selected amenities + if (is_array($current) && count($current) > 0) { + + // For each amenity in the list + foreach ($current as $key => $val) { + + $current[$key]['selected'] = false; + + // Delete existing ones from the supplied selection list and mark selected ones in the current list + if (isset($selectedAmenities[$val['id']])) { + + unset($selectedAmenities[$val['id']]); + + $current[$key]['selected'] = true; + + } + + } + + } + + // For each remaining selected amenity, add the amenity + foreach ($selectedAmenities as $s) { + + // Add the amenity + $sql = " + INSERT INTO ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."amenity_event + ( amenity, event ) + VALUES + ( $s, $eventID ) + ;"; + $this->wpdb->query($sql); + + + } + + // For any existing amenities listed that aren't marked as selected, remove them + if (is_array($current) && count($current) > 0) { + foreach ($current as $key => $val) { + + if (!$val['selected']) { + + // Delete the entry + // Add the amenity + $sql = " + DELETE FROM ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."amenity_event + WHERE event = $eventID + AND id = ".$val['id']." + ;"; + $this->wpdb->query($sql); + + } + } + } + + // Get new list and return it + $current = $this->getList($eventID); + + if (is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) { + glmMembersAdmin::addNotice($current, 'DataBlock', 'Currently Selected Event Amenities'); + } + + return $current; + } + + /** + * Clear all amenities for a specific event record + * + * @param integer $eventID Event Record ID + * + * @return null + * + * @access public + */ + + public function clearEventAmenities($eventID) + { + + $sql = " + DELETE FROM ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."amenity_event + WHERE event = $eventID + ;"; + $this->wpdb->query($sql); + + // Returns false to indicate there are no amenities selected + return false; + + } + + +} + +?> diff --git a/classes/data/dataEventCategories.php b/classes/data/dataEventCategories.php index 7d31bd2..df05b33 100644 --- a/classes/data/dataEventCategories.php +++ b/classes/data/dataEventCategories.php @@ -336,7 +336,7 @@ class GlmDataEventsEventCategories extends GlmDataAbstract { $sql = " - DELETE FROM ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."event_caetgories + DELETE FROM ".GLM_MEMBERS_EVENTS_PLUGIN_DB_PREFIX."event_categories WHERE event = $eventID ;"; $this->wpdb->query($sql); diff --git a/classes/data/dataEventGroups.php b/classes/data/dataEventGroups.php new file mode 100644 index 0000000..5687d65 --- /dev/null +++ b/classes/data/dataEventGroups.php @@ -0,0 +1,130 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataMemberType.php,v 1.0 2011/01/25 19:31:47 cscott Exp $ + */ + +/** + * EventManagementDataGroups class + * + * PHP version 5 + * + * @category Data + * @package EventManagement + * @author Chuck Scott + * @license http://www.gaslightmedia.com Gaslightmedia + * @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott + * Exp $ + */ +class GlmDataEventGroups extends GlmDataAbstract +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + /** + * Plugin Configuration Data + * + * @var $config + * @access public + */ + public $config; + /** + * Field definitions + * + * @var $ini + * @access public + */ + public $table; + + /** + * Field definitions + * + * 'type' is type of field as defined by the application + * text Regular text field + * pointer Pointer to an entry in another table + * 'filters' is the filter name for a particular filter ID in PHP filter + * functions + * See PHP filter_id() + * + * 'use' is when to use the field + * l = List + * g = Get + * n = New + * i = Insert + * e = Edit + * u = Update + * d = Delete + * a = All + * + * @var $ini + * @access public + */ + public $fields = false; + + /** + * Constructor + * + * @param object $d + * database connection + * + * @return void + * @access public + */ + function __construct ( $wpdb, $config ) + { + + // If this class is not being extended along with existing $wpdb and $config + if ( !$this->wpdb ) { + + // Save WordPress Database object + $this->wpdb = $wpdb; + + // Save plugin configuration object + $this->config = $config; + } + + /* + * Table Name + */ + $this->table = GLM_MEMBERS_PLUGIN_DB_PREFIX . 'amenity_groups'; + + /* + * Table Data Fields + */ + $this->fields = array( + 'id' => array( + 'field' => 'id', + 'type' => 'integer', + 'view_only' => true, + 'use' => 'a' + ), + + // Name + 'name' => array( + 'field' => 'name', + 'type' => 'text', + 'required' => true, + 'unique' => true, + 'use' => 'a' + ), + ); + + if ( is_admin() && GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE ) { + glmMembersAdmin::addNotice( $this->fields, 'DataBlock', 'Table Fields: '.$this->table ); + } + } +} diff --git a/classes/data/dataEvents.php b/classes/data/dataEvents.php index 12a445a..abcdd05 100644 --- a/classes/data/dataEvents.php +++ b/classes/data/dataEvents.php @@ -261,7 +261,7 @@ class GlmDataEvents extends GlmDataAbstract 'use' => 'lge' ), -/* Not currently in use + /* Not currently in use // Header 'header' => array ( 'field' => 'header', @@ -269,7 +269,7 @@ class GlmDataEvents extends GlmDataAbstract 'required' => false, 'use' => 'a' ), -*/ + */ // Intro Text 'intro' => array ( diff --git a/classes/data/dataLocations.php b/classes/data/dataLocations.php index d6aac2d..0eb5c4e 100644 --- a/classes/data/dataLocations.php +++ b/classes/data/dataLocations.php @@ -241,18 +241,18 @@ class GlmDataEventsLocations extends GlmDataAbstract ) // Contact Reference Placeholder if no Contacts Add-On (see below) -/* not currently in use + /* not currently in use 'contact_addon_id' => array( 'field' => 'contact_addon_id', 'type' => 'integer', 'use' => 'a' ), -*/ + */ /* * Using first and last name for compatibility with contacts add-on data */ -/* + /* // Contact First Name 'contact_fname' => array ( 'field' => 'contact_fname', @@ -280,7 +280,7 @@ class GlmDataEventsLocations extends GlmDataAbstract 'type' => 'text', 'use' => 'a' ) -*/ + */ ); } diff --git a/classes/data/dataManagement.php b/classes/data/dataManagement.php index 8bcef63..c352e6b 100644 --- a/classes/data/dataManagement.php +++ b/classes/data/dataManagement.php @@ -181,7 +181,27 @@ class GlmDataEventsManagement extends GlmDataAbstract 'type' => 'text', 'required' => false, 'use' => 'a' - ) + ), + // calendar view + 'term_event_amenities_singular' => array( + 'field' => 'term_event_amenities_singular', + 'type' => 'text', + 'require' => false, + 'use' => 'a' + ), + // calendar view + 'term_event_amenities_plural' => array( + 'field' => 'term_event_amenities_plural', + 'type' => 'text', + 'require' => false, + 'use' => 'a' + ), + 'use_event_amenities' => array ( + 'field' => 'use_event_amenities', + 'type' => 'checkbox', + 'default' => false, + 'use' => 'a' + ), ); diff --git a/index.php b/index.php index b60a226..d63eba8 100644 --- a/index.php +++ b/index.php @@ -39,7 +39,7 @@ * version from this plugin. */ define('GLM_MEMBERS_EVENTS_PLUGIN_VERSION', '1.5.0'); -define('GLM_MEMBERS_EVENTS_PLUGIN_DB_VERSION', '0.0.22'); +define('GLM_MEMBERS_EVENTS_PLUGIN_DB_VERSION', '0.1.0'); // This is the minimum version of the GLM Members DB plugin require for this plugin. define('GLM_MEMBERS_EVENTS_PLUGIN_MIN_MEMBERS_REQUIRED_VERSION', '1.0.58'); diff --git a/models/admin/events/index.php b/models/admin/events/index.php index b8014a8..3b67d78 100644 --- a/models/admin/events/index.php +++ b/models/admin/events/index.php @@ -96,6 +96,7 @@ class GlmMembersAdmin_events_index extends GlmDataEvents $numbPending = 0; $namesList = false; $haveCategories = false; +// $haveAmenities = false; // Check if there's a logged in user who is locked to their own entity $lockedToMember = apply_filters('glm_members_locked_to_member_id', false); @@ -114,6 +115,40 @@ class GlmMembersAdmin_events_index extends GlmDataEvents $haveCategories = true; } +// +// +// // Get list of Available Member Amenities to use for picklists +// require_once GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataAmenities.php'; +// $Amenities = new GlmDataAmenities($this->wpdb, $this->config); +// $this->amenities = $Amenities->getList("T.ref_type = ".$this->config['ref_type_numb']['MemberInfo']); +// +// // Get list of Amenities selected for this Member +// $this->memberAmenities = $Amenities->getAmenityRef($this->config['ref_type_numb']['MemberInfo'], $this->memberID); +// +// // Lastly, if we have member info, and if this record is active, we need to check for other active records and other things +// if ($this->haveMemberInfo) { +// +// // Check if the updated info record was set to active +// $activeTest = $this->isActive(); +// +// // If the current record is now active and wasn't before +// if ($activeTest == $this->config['status_numb']['Active'] && !$this->isActive) { +// +// // Change any others for this member to inactive +// $sql = " +// UPDATE ".GLM_MEMBERS_PLUGIN_DB_PREFIX."member_info +// SET status = ".$this->config['status_numb']['Inactive']." +// WHERE member = ".$this->memberID." +// AND status = ".$this->config['status_numb']['Active']." +// AND id != ".$this->memberInfoID." +// ;"; +// $this->wpdb->query($sql); +// +// } +// +// } // Have member info +// + // Get full list of names matching this where clause for search box $namesList = $this->getIdName($lockedWhereT); @@ -143,6 +178,7 @@ class GlmMembersAdmin_events_index extends GlmDataEvents 'namesList' => $namesList, 'numbPending' => $numbPending, 'haveCategories' => $haveCategories +// 'haveAmenities' => $haveAmenities ); // Return status, any suggested view, and any data to controller return array( diff --git a/models/admin/events/list.php b/models/admin/events/list.php index 35e4ed9..48e6a4b 100644 --- a/models/admin/events/list.php +++ b/models/admin/events/list.php @@ -20,6 +20,10 @@ require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH.'/data/dataEvents.php'; require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH.'/data/dataCategories.php'; require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH.'/data/dataEventCategories.php'; + +require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH.'/data/dataAmenities.php'; +require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH.'/data/dataEventAmenities.php'; + class GlmMembersAdmin_events_list extends GlmDataEvents { @@ -191,6 +195,10 @@ class GlmMembersAdmin_events_list extends GlmDataEvents // Get a list of categories $Categories = new GlmDataEventsCategories($this->wpdb, $this->config); $categories = $Categories->getListSortedParentChild(false); + + // Get a list of amenities + $Amenities = new GlmDataEventsAmenities($this->wpdb, $this->config); + $amenities = $Amenities->getList(false); // Load locations data class to get a blank entry for the template require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH.'/data/dataLocations.php'; @@ -239,6 +247,9 @@ class GlmMembersAdmin_events_list extends GlmDataEvents $this->updateCategories(); $categories = $Categories->getListSortedParentChild(false); + + $this->updateAmenities(); + $amenities = $Amenities->getList(false); $event = $this->insertEntry(); @@ -370,6 +381,9 @@ class GlmMembersAdmin_events_list extends GlmDataEvents $this->updateCategories(); $categories = $Categories->getListSortedParentChild(false); + + $this->updateAmenities(); + $amenities = $Amenities->getList(false); // Try to update this event $event = $this->updateEntry($this->eventID); @@ -550,7 +564,7 @@ class GlmMembersAdmin_events_list extends GlmDataEvents while (list($k, $v) = each($categories)) { $categories[$k]['selected'] = false; } - + // Check if there is a category filter (multi-select) if (isset($_REQUEST['filterCategories']) && count($_REQUEST['filterCategories']) > 0) { @@ -682,7 +696,19 @@ class GlmMembersAdmin_events_list extends GlmDataEvents break; } - +// +// echo "EVENT ID " . $this->eventID; +// // Get list of Available Member Amenities to use for picklists +// require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH.'/data/dataEventAmenities.php'; +// echo "Test 1"; +// $Amenities = new GlmDataEventsAmenities($this->wpdb, $this->config); +// +// $this->amenities = $Amenities->getList("T.id = ".$this->eventID); +// echo "
Test 2:" . print_r($this->amenities, true) . " End Test 2
"; +// +// // Get list of Amenities selected for this Event +// $this->eventAmenities = $Amenities->getAmenityRef($this->eventID); +// echo "
Test 3:" . print_r($this->eventAmenities, true) . " End Test 3
"; // If we have an event ID if ($this->eventID) { @@ -737,6 +763,7 @@ class GlmMembersAdmin_events_list extends GlmDataEvents 'eventAddError' => $eventAddError, 'numbEvents' => $numbEvents, 'categories' => $categories, + 'amenities' => $amenities, 'fromDate' => $fromDate, 'toDate' => $toDate, 'filterArchived' => $filterArchived, @@ -767,7 +794,8 @@ class GlmMembersAdmin_events_list extends GlmDataEvents 'start' => $start = 1, 'limit' => $limit, 'namesList' => $namesList, - 'eventDefaultState' => $this->config['settings']['event_default_state'] + 'eventDefaultState' => $this->config['settings']['event_default_state'], + ); // Return status, any suggested view, and any data to controller @@ -867,7 +895,86 @@ class GlmMembersAdmin_events_list extends GlmDataEvents } } + /** + * Update amenities for the current submission + * + * @return void + */ + public function updateAmenities() + { + + // Instatiate the dataAmenities class + $Amenities = new GlmDataEventsAmenities($this->wpdb, $this->config); + + // Instatiate Event/Amenities data class + $EventAmenities = new GlmDataEventsEventAmenities($this->wpdb, $this->config); + + // Get any selected amenities + $selectedAmenities = array(); + $newAmenity = false; + if (isset($_REQUEST['amenity']) && is_array($_REQUEST['amenity']) && count($_REQUEST['amenity']) > 0) { + + /* + * For each selected amenity + * + * Note that amenities are submitted with either a positive key, which indicates + * that it represents an existing amenity, or a negative key, which indicates + * that the user is trying to add it to the list of amenities. + * + */ + foreach ($_REQUEST['amenity'] as $key) { + + // Make sure key is an integer + $key = intval($key -0); + + // If negative, this is a new amenity that needs to be added to the amenity table + if ($key < 0) { + + $newAmenity = true; + // Clean up the amenity name + $amenity = filter_var($_REQUEST['newAmenity'][$key]); + + // Add it to the amenity table and get the new amenity ID + $amenityID = $Amenities->addAmenity($amenity); + + // If we got a new amenity ID, add it to the array of currently selected eventAmenity records + if ($amenityID) { + $selectedAmenities[$amenityID] = $amenityID; + } + + // Otherwise if it's positive, the amenity is an existing one + } else if ($key > 0) { + + $selectedAmenities[$key] = $key; + + } + + // If there's selected amenities + if (count($selectedAmenities) > 0) { + + // Update the selected amenities for this event record, returns new list + $EventAmenities->setEventAmenities($this->eventID, $selectedAmenities); + + } + + // If there's been a new amenity + if ($newAmenity) { + + // Get the full amenity list again + $this->amenities = $Amenities->getList(false); + + } + + } // For each amenity being submitted + + // Otherwise if this is a submission and there's no amenities submitted, so make sure there's none stored + } elseif (isset($_REQUEST['option']) && $_REQUEST['option'] == 'submit') { + $EventAmenities->clearEventAmenities($this->eventID); + } + + } + /* * Check for new Cities being added * diff --git a/models/admin/settings/eventAmenities.php b/models/admin/settings/eventAmenities.php new file mode 100644 index 0000000..ef5bd96 --- /dev/null +++ b/models/admin/settings/eventAmenities.php @@ -0,0 +1,293 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version 0.1 + */ + +// Load Amenities data abstract +require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH . '/data/dataEventAmenities.php'; +require_once GLM_MEMBERS_EVENTS_PLUGIN_CLASS_PATH . '/data/dataEventGroups.php'; + +/* + * This class performs the work for the default action of the "Members" menu + * option, which is to display the members dashboard. + * + */ +class GlmMembersAdmin_settings_eventAmenities extends GlmDataEventsAmenities +{ + + /** + * WordPress Database Object + * + * @var $wpdb + * @access public + */ + public $wpdb; + /** + * Plugin Settings Data + * + * @var $config + * @access public + */ + public $config; + + /* + * 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 members data class + parent::__construct( false, false ); + + } + + /* + * Perform Model Action + * + * This method does the work for this model and returns any resulting data + * + * @return array Status and data array + * + * 'status' + * + * True if successfull and false if there was a fatal failure. + * + * 'menuItemRedirect' + * + * If not false, provides a menu item the controller should + * execute after this one. Normally if this is used, there would also be a + * modelRedirect value supplied as well. + * + * 'modelRedirect' + * + * If not false, provides an action the controller should execute after + * this one. + * + * 'view' + * + * A suggested view name that the contoller should use instead of the + * default view for this model or false to indicate that the default view + * should be used. + * + * 'data' + * + * Data that the model is returning for use in merging with the view to + * produce output. + * + */ + public function modelAction ( $actionData = false ) + { + echo "TEST 1"; + $success = true; + $haveAmenities = false; + $haveGroups = false; + $amenities = false; + $error = false; + $option2 = ''; + $newAmenity = $this->newEntry(); + + // Check if a category ID is supplied + $id = 0; + if ( isset( $_REQUEST['id'] ) ) { + $id = $_REQUEST['id'] - 0; + } + echo "TEST 1.3"; + $groupData = new GlmDataEventGroups( $this->wpdb, $this->config ); + echo "TEST 1.4"; + // If there's an action option + if ( isset( $_REQUEST['option'] ) ) { + switch( $_REQUEST['option'] ) { + case 'addNew': + $return = $this->insertEntry(); + $id = $return['fieldData']['id']; + if ( isset( $_REQUEST['grouped']['group'] ) ) { + foreach ( $_REQUEST['grouped']['group'] as $group_id => $group_value ) { + if ( $group_value == 1 ) { + $this->wpdb->insert( + GLM_MEMBERS_PLUGIN_DB_PREFIX . 'grouped_amenities', + array( + 'group_id' => $group_id, + 'amenity_id' => $id, + 'searchable' => $_REQUEST['grouped']['searchable'][$group_id] + ), + array( + '%d', + '%d', + '%s' + ) + ); + } + } + } + break; + + case 'update': + if ( $id > 0 ) { + $this->updateEntry( $id ); + } + // Delete the current entries for the grouped amenities + $this->wpdb->delete( + GLM_MEMBERS_PLUGIN_DB_PREFIX . 'grouped_amenities', + array( 'amenity_id' => $id ), + array( '%d' ) + ); + if ( isset( $_REQUEST['grouped']['group'] ) ) { + foreach ( $_REQUEST['grouped']['group'] as $group_id => $group_value ) { + if ( $group_value == 1 ) { + $this->wpdb->insert( + GLM_MEMBERS_PLUGIN_DB_PREFIX . 'grouped_amenities', + array( + 'group_id' => $group_id, + 'amenity_id' => $id, + 'searchable' => $_REQUEST['grouped']['searchable'][$group_id] + ), + array( + '%d', + '%d', + '%s' + ) + ); + } + } + } + break; + + case 'delete': + if ( $id > 0 ) { + $this->deleteEntry( $id, true ); + } + break; + + case 'addNewGroup': + $groupData->insertEntry(); + break; + + case 'updateGroup': + if ( $id > 0 ) { + $groupData->updateEntry( $id ); + } + break; + + case 'deleteGroup': + if ( $id > 0 ) { + $groupData->deleteEntry( $id, true ); + + // Delete the current entries for the grouped amenities + $this->wpdb->delete( + GLM_MEMBERS_PLUGIN_DB_PREFIX . 'grouped_amenities', + array( 'group_id' => $id ), + array( '%d' ) + ); + } + break; + + default: + echo "TEST 4"; + $option2 = false; + break; + + } + } + echo "TEST 1.4"; + if ( isset( $_REQUEST['option2'] ) ) { + $option2 = $_REQUEST['option2']; + } + echo "TEST 1.5"; + // Get a current list of amenities + $amenities = $this->getList(); + echo "TEST 2"; + echo '
$amenities: ' . print_r($amenities, true) . '
'; + + if ( GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE ) { + glmMembersAdmin::addNotice( $amenities, 'DataBlock', 'Amenities Data' ); + } + echo "TEST 3"; + // If we have list entries - even if it's an empty list + $success = true; + $haveAmenities = false; + if ( $amenities !== false ) { + + $success = true; + + // If we have any entries + if ( count( $amenities ) > 0 ) { + $haveAmenities = true; + } + } + echo "TEST 4"; + $groups = $groupData->getList(); + echo '
$groups: ' . print_r($groups, true) . '
'; + + if ( GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE ) { + glmMembersAdmin::addNotice( $groups, 'DataBlock', 'Amenity Groups Data' ); + } + + if ( $groups !== false ) { + $success = true; + + // If we have any entries. + if ( count( $groups ) > 0 ) { + $haveGroups = true; + } + } + + // If we had a fatal error, redirect to the error page + if ($error) { + return array( + 'status' => $success, + 'menuItemRedirect' => 'error', + 'modelRedirect' => 'index', + 'view' => 'admin/error/index.html', + 'data' => false, + ); + } + + if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) { + glmMembersAdmin::addNotice( $amenities, 'DataBlock', 'Amenities Data' ); + } + echo "TEST FIN"; + // Compile template data + $templateData = array( + 'haveAmenities' => $haveAmenities, + 'haveGroups' => $haveGroups, + 'amenities' => $amenities, + 'groups' => $groups, + 'option2' => $option2, + 'newAmenity' => $newAmenity, + ); + + // Return status, suggested view, and data to controller + return array( + 'status' => $success, + 'menuItemRedirect' => false, + 'modelRedirect' => false, + 'view' => 'admin/settings/eventAmenities.html', + 'data' => $templateData, + ); + + } + + +} diff --git a/models/admin/settings/eventCategories.php b/models/admin/settings/eventCategories.php index 5397fec..b25e695 100644 --- a/models/admin/settings/eventCategories.php +++ b/models/admin/settings/eventCategories.php @@ -174,7 +174,7 @@ class GlmMembersAdmin_settings_eventCategories extends GlmDataEventsCategories ); } - // Sort results by higherarchy (Parent/Child and Alpha) + // Sort results by hierarchy (Parent/Child and Alpha) $categories = $this->sortParentChild($categories); if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) { diff --git a/setup/adminTabs.php b/setup/adminTabs.php index 3807126..e6865f5 100644 --- a/setup/adminTabs.php +++ b/setup/adminTabs.php @@ -66,7 +66,21 @@ if (current_user_can('glm_members_members')) { return $addOnTabs; } ); + + add_filter('glm-member-db-add-tab-for-settings', + function($addOnTabs) { + $newTabs = array( + array( + 'text' => 'Event Amenities', + 'menu' => 'settings', + 'action' => 'eventAmenities' + ), + ); + $addOnTabs = array_merge($addOnTabs, $newTabs); + return $addOnTabs; + } + ); add_filter('glm-member-db-add-tab-for-events', function($addOnTabs) { diff --git a/setup/databaseScripts/create_database_V0.0.22.sql b/setup/databaseScripts/create_database_V0.0.22.sql deleted file mode 100644 index 50bcc8b..0000000 --- a/setup/databaseScripts/create_database_V0.0.22.sql +++ /dev/null @@ -1,200 +0,0 @@ --- Gaslight Media Members Database - Events Add-On --- File Created: 12/02/15 15:27:15 --- Database Version: 0.0.22 --- Database Creation Script --- --- This file is called to create a new set of tables for this --- add-on for the most recent database version for this add-on. --- --- There should only be one such file in this directory --- --- To permit each query below to be executed separately, --- all queries must be separated by a line with four dashes - --- Categories - Categories for events -CREATE TABLE {prefix}categories ( - id INT NOT NULL AUTO_INCREMENT, - name TINYTEXT NULL, -- Name of event category - descr TINYTEXT NULL, -- Description of this category - parent INT NULL, -- Parent category, null or 0 if this is a top level category - PRIMARY KEY (id), - INDEX(parent) -); - ----- - --- Event-Category - Categories for specific event records -CREATE TABLE {prefix}event_categories ( - id INT NOT NULL AUTO_INCREMENT, - event INT NULL, -- Pointer to the event - category INT NULL, -- Pointer to the category - PRIMARY KEY (id), - INDEX(event), - INDEX(category) -); - ----- - --- Event Recurrence - Defines how an event recurs -CREATE TABLE {prefix}recurrences ( - id INT NOT NULL AUTO_INCREMENT, - event INTEGER NULL, -- Pointer to event - name TINYTEXT NULL, -- Name of this recurrence schedule - used on admin calendar - start_time TIME NULL, -- Start time of day for event - start_time_only BOOLEAN NULL, -- Use end of first occurrence flag - end_time TIME NULL, -- End time of day for event - If less than start time, assume a date boundry - all_day BOOLEAN NULL, -- Flag indicating if this is an all-day event (informational only) - start_date DATE NULL, -- Starting Date (if all_day is selected) Used instead of start_time - from_date DATE NULL, -- From Date for recurrences - to_date DATE NULL, -- To Date for recurrences - recurring BOOLEAN NULL, -- Flag indicating that event recurs on a schedule rather than all dates - month_of_year SMALLINT UNSIGNED NULL, -- Month of year (bitmap) - week_of_month TINYINT UNSIGNED NULL, -- Week of the month (bitmap) - day_of_week TINYINT UNSIGNED NULL, -- Day of the week (bitmap) - by_day_of_month BOOLEAN NULL, -- Flag indicating if selecting by days of the month - day_of_month INTEGER UNSIGNED NULL, -- Day of the month (bitmap) - last_day_of_month BOOLEAN NULL, -- Last day of the month - specific_dates TEXT NULL, -- Serialized array of specific dates added to the recurrence - holiday INT NULL, -- Pointer to holidays list (for future development) - holiday_offset TINYINT, -- Offset from holiday (from -128 to +127 days) - PRIMARY KEY (id), - INDEX(event) -); - ----- - --- Times - List of actual event times for single and recurring events -CREATE TABLE {prefix}times ( - id INT NOT NULL AUTO_INCREMENT, - event INT NULL, -- Pointer to the primary record for the event - custom_event INT NULL, -- Pointer to a customized copy of the event record (if set) - recur_id INT NULL, -- Pointer to recurrence entry - active BOOLEAN NULL, -- Active flag - normally set but used to temporarily disable a specific date - start_time DATETIME NULL, -- Date and time event starts - end_time DATETIME NULL, -- Date and time event ends - all_day BOOLEAN NULL, -- All Day flag - PRIMARY KEY (id), - INDEX(event), - INDEX(start_time), - INDEX(end_time) -); - ----- - --- Locations - Locations for event - If there's no location pointing to an event try to use the referenced entity in events table -CREATE TABLE {prefix}locations ( - id INT NOT NULL AUTO_INCREMENT, - event INT NULL, -- Pointer to the primary or custom event record - name TINYTEXT NULL, -- Name of location - address TINYTEXT NULL, -- Street Address - city INT NULL, -- Pointer to city - references main plugin city table - state TINYTEXT NULL, -- Two character state abbreviation - zip TINYTEXT NULL, -- ZIP/Postal code - country TINYTEXT NULL, -- Country Code - lat FLOAT NULL, -- Latitude of location - lon FLOAT NULL, -- Longitude of location - region INT NULL, -- Pointer to Region - references main plugin region table - phone TINYTEXT NULL, -- Location Phone # - url TINYTEXT NULL, -- Location URL - email TINYTEXT NULL, -- Location E-Mail Address - contact_addon_id INT NULL, -- ID of Contact from contact add-on (optional and if available) - contact_fname TINYTEXT NULL, -- Contact first name for this location (optional) - contact_lname TINYTEXT NULL, -- Contact last name for this location (optional) - contact_phone TINYTEXT NULL, -- Contact phone for this location (optional) - contact_email TINYTEXT NULL, -- Contact E-Mail address (optional) - PRIMARY KEY (id) -); - ----- - --- Events - Base event information - May also be entries here referenced by the "times" table for a custom date. -CREATE TABLE {prefix}events ( - id INT NOT NULL AUTO_INCREMENT, - status INT NULL, -- Status for this event, see config['status'] - custom_time INT NULL, -- If this is a custom record for a specific instance (date) this points to that times table entry - root_event INT NULL, -- Root event pointer if this is a custom record for a specific instance (date) (if custom_time is set) - created DATETIME NULL, -- Date/Time event was created or date custom event record was created if custom record - updated DATETIME NULL, -- Date/Time this event record was last updated - approved DATETIME NULL, -- Date/Ttime this event record was approved - ref_type INT NULL, -- Type of entity this contact is associated with - See config['ref_type'] - ref_dest INT NULL, -- Pointer to the specific entity of ref_type this contact is associated with - hide_address BOOLEAN NULL, -- Option to hide address on front-end - featured BOOLEAN NULL, -- Option to mark as featured event - slideshow BOOLEAN NULL, -- Option to mark for use in slide show - major BOOLEAN NULL, -- Option to mark as a major event - name TINYTEXT NULL, -- Name of this event - name_slug TINYTEXT NULL, -- Slug for this event - header TINYTEXT NULL, -- Header text for front-end display - NOT CURRENTLY USED - intro TINYTEXT NULL, -- Intro text for front-end display - descr TEXT NULL, -- Full description text - image TINYTEXT NULL, -- Image file name - file1 TINYTEXT NULL, -- File name for a single uploaded file #1 - file1_descr TINYTEXT NULL, -- Description for file uploaded in field "file" #1 - file2 TINYTEXT NULL, -- File name for a single uploaded file #2 - file2_descr TINYTEXT NULL, -- Description for file uploaded in field "file" #2 - file3 TINYTEXT NULL, -- File name for a single uploaded file #3 - file3_descr TINYTEXT NULL, -- Description for file uploaded in field "file" #3 - url TINYTEXT NULL, -- Event URL - ticket_url TINYTEXT NULL, -- Ticket URL - cost TINYTEXT NULL, -- Description of event cost - admin_ref_type INT NULL, -- Type of admin contact if using a member contact - admin_ref_dest INT NULL, -- Pointer to admin contact record if using a member contact - admin_name TINYTEXT NULL, -- Admin Contact Name if not using a member contact - admin_org TINYTEXT NULL, -- Admin Contact Organization if not using a member contact - admin_email TINYTEXT NULL, -- Admin Contact E-Mail if not using a member contact - admin_phone TINYTEXT NULL, -- Admin Contact Phone if not using a member contact - free BOOLEAN NULL, -- Event is Free - contact_email TINYTEXT NULL, -- Contact E-mail address - contact_name TINYTEXT NULL, -- Contact name - contact_phone TINYTEXT NULL, -- Event Phone - use_member_location BOOLEAN NULL, -- Use location of the member (if provided) rather than location table data - old_event_id INT NULL, -- ID of event from old site for reference - ical_uid TINYTEXT NULL, -- The ical UID for this event. - notes TEXT NULL, -- Internal notes for this event - PRIMARY KEY (id), - INDEX(custom_time), - INDEX(root_event), - INDEX(ref_type), - INDEX(ref_dest), - INDEX(featured), - INDEX(slideshow), - INDEX(major) -); - ----- - --- Event Management Settings -CREATE TABLE {prefix}management ( - id INT NOT NULL AUTO_INCREMENT, - canonical_event_page TINYTEXT NULL, -- Canonical page slug for event detail - pdf_logo TINYTEXT NULL, -- Image for the Top of the PDF - footer_text TINYTEXT NULL, -- Image for the Top of the PDF - to_email TINYTEXT NULL, -- Email address of the recipient - from_email TINYTEXT NULL, -- Email address of the sender - email_notification TEXT NULL, -- Email notification message - calendar_view TINYTEXT NULL, -- Default calendar view - event_default_state TINYTEXT NULL, -- Default calendar view - PRIMARY KEY (id) -); - ----- - --- Set default event management entry -INSERT INTO {prefix}management - ( id, canonical_event_page ) - VALUES - ( 1, 'event-detail' ) -; - ----- - --- Event iCal Feed imports -CREATE TABLE {prefix}feed_import ( - id INT NOT NULL AUTO_INCREMENT, - feed_url TEXT NOT NULL, -- The ical feed url to import - created DATETIME NULL, -- The date this feed was created - updated DATETIME NULL, -- Last time this feed was updated - duration INT NULL, -- The time it took to fetch the feed - events INT NULL, -- The number of events last fetched - PRIMARY KEY (id) -); diff --git a/setup/databaseScripts/create_database_V0.1.0.sql b/setup/databaseScripts/create_database_V0.1.0.sql new file mode 100644 index 0000000..e269bce --- /dev/null +++ b/setup/databaseScripts/create_database_V0.1.0.sql @@ -0,0 +1,250 @@ +-- Gaslight Media Members Database - Events Add-On +-- File Created: 12/02/15 15:27:15 +-- Database Version: 0.1.0 +-- Database Creation Script +-- +-- This file is called to create a new set of tables for this +-- add-on for the most recent database version for this add-on. +-- +-- There should only be one such file in this directory +-- +-- To permit each query below to be executed separately, +-- all queries must be separated by a line with four dashes + + +-- Amenities +CREATE TABLE {prefix}amenities ( + id INT NOT NULL AUTO_INCREMENT, + active TINYINT(1) NULL, -- Amenity is active flag + name TINYTEXT NULL, -- Name of amenity + descr TEXT NULL, -- Description of amenity + short_descr TINYTEXT NULL, -- Short description of amenity + uses_value BOOLEAN NULL, -- Flag indicating whether the amenity requires a quantity number + PRIMARY KEY (id), + INDEX(name(20)) +); + +---- + +-- Amenity Reference - Links a specific amenity to a specific entity of type ref_type +CREATE TABLE {prefix}amenity_event ( + id INT NOT NULL AUTO_INCREMENT, + amenity INT NULL, + event INT NULL, + PRIMARY KEY (id), + INDEX(event) +); + +---- + +-- groups +CREATE TABLE {prefix}amenity_groups ( + id INT NOT NULL AUTO_INCREMENT, + name TINYTEXT NULL, -- Name of the Group + PRIMARY KEY (id), + INDEX(name(20)) +); + +---- + +-- Amenity Group - Links a specific amenity to groups +CREATE TABLE {prefix}grouped_amenities ( + id INT NOT NULL AUTO_INCREMENT, + group_id INT, -- Pointer to the group + amenity_id INT, -- Pointer to the Amenity + searchable BOOLEAN DEFAULT '0', -- Flag indicating whether the amenity group will show in the search form + PRIMARY KEY (id) +); + +---- + +-- Categories - Categories for events +CREATE TABLE {prefix}categories ( + id INT NOT NULL AUTO_INCREMENT, + name TINYTEXT NULL, -- Name of event category + descr TINYTEXT NULL, -- Description of this category + parent INT NULL, -- Parent category, null or 0 if this is a top level category + PRIMARY KEY (id), + INDEX(parent) +); + +---- + +-- Event-Category - Categories for specific event records +CREATE TABLE {prefix}event_categories ( + id INT NOT NULL AUTO_INCREMENT, + event INT NULL, -- Pointer to the event + category INT NULL, -- Pointer to the category + PRIMARY KEY (id), + INDEX(event), + INDEX(category) +); + +---- + +-- Event Recurrence - Defines how an event recurs +CREATE TABLE {prefix}recurrences ( + id INT NOT NULL AUTO_INCREMENT, + event INTEGER NULL, -- Pointer to event + name TINYTEXT NULL, -- Name of this recurrence schedule - used on admin calendar + start_time TIME NULL, -- Start time of day for event + start_time_only BOOLEAN NULL, -- Use end of first occurrence flag + end_time TIME NULL, -- End time of day for event - If less than start time, assume a date boundry + all_day BOOLEAN NULL, -- Flag indicating if this is an all-day event (informational only) + start_date DATE NULL, -- Starting Date (if all_day is selected) Used instead of start_time + from_date DATE NULL, -- From Date for recurrences + to_date DATE NULL, -- To Date for recurrences + recurring BOOLEAN NULL, -- Flag indicating that event recurs on a schedule rather than all dates + month_of_year SMALLINT UNSIGNED NULL, -- Month of year (bitmap) + week_of_month TINYINT UNSIGNED NULL, -- Week of the month (bitmap) + day_of_week TINYINT UNSIGNED NULL, -- Day of the week (bitmap) + by_day_of_month BOOLEAN NULL, -- Flag indicating if selecting by days of the month + day_of_month INTEGER UNSIGNED NULL, -- Day of the month (bitmap) + last_day_of_month BOOLEAN NULL, -- Last day of the month + specific_dates TEXT NULL, -- Serialized array of specific dates added to the recurrence + holiday INT NULL, -- Pointer to holidays list (for future development) + holiday_offset TINYINT, -- Offset from holiday (from -128 to +127 days) + PRIMARY KEY (id), + INDEX(event) +); + +---- + +-- Times - List of actual event times for single and recurring events +CREATE TABLE {prefix}times ( + id INT NOT NULL AUTO_INCREMENT, + event INT NULL, -- Pointer to the primary record for the event + custom_event INT NULL, -- Pointer to a customized copy of the event record (if set) + recur_id INT NULL, -- Pointer to recurrence entry + active BOOLEAN NULL, -- Active flag - normally set but used to temporarily disable a specific date + start_time DATETIME NULL, -- Date and time event starts + end_time DATETIME NULL, -- Date and time event ends + all_day BOOLEAN NULL, -- All Day flag + PRIMARY KEY (id), + INDEX(event), + INDEX(start_time), + INDEX(end_time) +); + +---- + +-- Locations - Locations for event - If there's no location pointing to an event try to use the referenced entity in events table +CREATE TABLE {prefix}locations ( + id INT NOT NULL AUTO_INCREMENT, + event INT NULL, -- Pointer to the primary or custom event record + name TINYTEXT NULL, -- Name of location + address TINYTEXT NULL, -- Street Address + city INT NULL, -- Pointer to city - references main plugin city table + state TINYTEXT NULL, -- Two character state abbreviation + zip TINYTEXT NULL, -- ZIP/Postal code + country TINYTEXT NULL, -- Country Code + lat FLOAT NULL, -- Latitude of location + lon FLOAT NULL, -- Longitude of location + region INT NULL, -- Pointer to Region - references main plugin region table + phone TINYTEXT NULL, -- Location Phone # + url TINYTEXT NULL, -- Location URL + email TINYTEXT NULL, -- Location E-Mail Address + contact_addon_id INT NULL, -- ID of Contact from contact add-on (optional and if available) + contact_fname TINYTEXT NULL, -- Contact first name for this location (optional) + contact_lname TINYTEXT NULL, -- Contact last name for this location (optional) + contact_phone TINYTEXT NULL, -- Contact phone for this location (optional) + contact_email TINYTEXT NULL, -- Contact E-Mail address (optional) + PRIMARY KEY (id) +); + +---- + +-- Events - Base event information - May also be entries here referenced by the "times" table for a custom date. +CREATE TABLE {prefix}events ( + id INT NOT NULL AUTO_INCREMENT, + status INT NULL, -- Status for this event, see config['status'] + custom_time INT NULL, -- If this is a custom record for a specific instance (date) this points to that times table entry + root_event INT NULL, -- Root event pointer if this is a custom record for a specific instance (date) (if custom_time is set) + created DATETIME NULL, -- Date/Time event was created or date custom event record was created if custom record + updated DATETIME NULL, -- Date/Time this event record was last updated + approved DATETIME NULL, -- Date/Ttime this event record was approved + ref_type INT NULL, -- Type of entity this contact is associated with - See config['ref_type'] + ref_dest INT NULL, -- Pointer to the specific entity of ref_type this contact is associated with + hide_address BOOLEAN NULL, -- Option to hide address on front-end + featured BOOLEAN NULL, -- Option to mark as featured event + slideshow BOOLEAN NULL, -- Option to mark for use in slide show + major BOOLEAN NULL, -- Option to mark as a major event + name TINYTEXT NULL, -- Name of this event + name_slug TINYTEXT NULL, -- Slug for this event + header TINYTEXT NULL, -- Header text for front-end display - NOT CURRENTLY USED + intro TINYTEXT NULL, -- Intro text for front-end display + descr TEXT NULL, -- Full description text + image TINYTEXT NULL, -- Image file name + file1 TINYTEXT NULL, -- File name for a single uploaded file #1 + file1_descr TINYTEXT NULL, -- Description for file uploaded in field "file" #1 + file2 TINYTEXT NULL, -- File name for a single uploaded file #2 + file2_descr TINYTEXT NULL, -- Description for file uploaded in field "file" #2 + file3 TINYTEXT NULL, -- File name for a single uploaded file #3 + file3_descr TINYTEXT NULL, -- Description for file uploaded in field "file" #3 + url TINYTEXT NULL, -- Event URL + ticket_url TINYTEXT NULL, -- Ticket URL + cost TINYTEXT NULL, -- Description of event cost + admin_ref_type INT NULL, -- Type of admin contact if using a member contact + admin_ref_dest INT NULL, -- Pointer to admin contact record if using a member contact + admin_name TINYTEXT NULL, -- Admin Contact Name if not using a member contact + admin_org TINYTEXT NULL, -- Admin Contact Organization if not using a member contact + admin_email TINYTEXT NULL, -- Admin Contact E-Mail if not using a member contact + admin_phone TINYTEXT NULL, -- Admin Contact Phone if not using a member contact + free BOOLEAN NULL, -- Event is Free + contact_email TINYTEXT NULL, -- Contact E-mail address + contact_name TINYTEXT NULL, -- Contact name + contact_phone TINYTEXT NULL, -- Event Phone + use_member_location BOOLEAN NULL, -- Use location of the member (if provided) rather than location table data + old_event_id INT NULL, -- ID of event from old site for reference + ical_uid TINYTEXT NULL, -- The ical UID for this event. + notes TEXT NULL, -- Internal notes for this event + PRIMARY KEY (id), + INDEX(custom_time), + INDEX(root_event), + INDEX(ref_type), + INDEX(ref_dest), + INDEX(featured), + INDEX(slideshow), + INDEX(major) +); + +---- + +-- Event Management Settings +CREATE TABLE {prefix}management ( + id INT NOT NULL AUTO_INCREMENT, + canonical_event_page TINYTEXT NULL, -- Canonical page slug for event detail + pdf_logo TINYTEXT NULL, -- Image for the Top of the PDF + footer_text TINYTEXT NULL, -- Image for the Top of the PDF + to_email TINYTEXT NULL, -- Email address of the recipient + from_email TINYTEXT NULL, -- Email address of the sender + email_notification TEXT NULL, -- Email notification message + calendar_view TINYTEXT NULL, -- Default calendar view + event_default_state TINYTEXT NULL, -- Default calendar view + term_event_amenities_singular TINYTEXT NULL, -- Singular term to use for event amenities + term_event_amenities_plural TINYTEXT NULL, -- Plural term to use for event amenities + use_event_amenities BOOLEAN NULL, -- Whether amenities are used at all for events + PRIMARY KEY (id) +); + +---- + +-- Set default event management entry +INSERT INTO {prefix}management + ( id, canonical_event_page ) + VALUES + ( 1, 'event-detail' ) +; + +---- + +-- Event iCal Feed imports +CREATE TABLE {prefix}feed_import ( + id INT NOT NULL AUTO_INCREMENT, + feed_url TEXT NOT NULL, -- The ical feed url to import + created DATETIME NULL, -- The date this feed was created + updated DATETIME NULL, -- Last time this feed was updated + duration INT NULL, -- The time it took to fetch the feed + events INT NULL, -- The number of events last fetched + PRIMARY KEY (id) +); diff --git a/setup/databaseScripts/dbVersions.php b/setup/databaseScripts/dbVersions.php index b32cae7..bf3b33f 100644 --- a/setup/databaseScripts/dbVersions.php +++ b/setup/databaseScripts/dbVersions.php @@ -34,5 +34,7 @@ $glmMembersEventsDbVersions = array( '0.0.20' => array('version' => '0.0.20', 'tables' => 8, 'date' => '8/12/2016'), '0.0.21' => array('version' => '0.0.21', 'tables' => 8, 'date' => '8/25/2016'), '0.0.22' => array('version' => '0.0.22', 'tables' => 8, 'date' => '8/30/2016'), + '0.0.23' => array('version' => '0.0.23', 'tables' => 12, 'date' => '10/20/2016'), + '0.1.0' => array('version' => '0.1.0', 'tables' => 12, 'date' => '10/20/2016'), ); diff --git a/setup/databaseScripts/update_database_V0.0.23.sql b/setup/databaseScripts/update_database_V0.0.23.sql new file mode 100644 index 0000000..1b96dc2 --- /dev/null +++ b/setup/databaseScripts/update_database_V0.0.23.sql @@ -0,0 +1,51 @@ +-- Gaslight Media Members Database - Events Add-On +-- File Created: 08/30/16 09:47:15 +-- Database Version: 0.0.23 +-- Database Update From Previous Version Script +-- +-- To permit each query below to be executed separately, +-- all queries must be separated by a line with four dashes + +-- Amenities +CREATE TABLE {prefix}amenities ( + id INT NOT NULL AUTO_INCREMENT, + active TINYINT(1) NULL, -- Amenity is active flag + name TINYTEXT NULL, -- Name of amenity + descr TEXT NULL, -- Description of amenity + short_descr TINYTEXT NULL, -- Short description of amenity + uses_value BOOLEAN NULL, -- Flag indicating whether the amenity requires a quantity number + PRIMARY KEY (id), + INDEX(name(20)) +); + +---- + +-- Amenity Reference - Links a specific amenity to a specific entity of type ref_type +CREATE TABLE {prefix}amenity_event ( + id INT NOT NULL AUTO_INCREMENT, + amenity INT NULL, + event INT NULL, + PRIMARY KEY (id), + INDEX(event) +); + +---- + +-- groups +CREATE TABLE {prefix}amenity_groups ( + id INT NOT NULL AUTO_INCREMENT, + name TINYTEXT NULL, -- Name of the Group + PRIMARY KEY (id), + INDEX(name(20)) +); + +---- + +-- Amenity Group - Links a specific amenity to groups +CREATE TABLE {prefix}grouped_amenities ( + id INT NOT NULL AUTO_INCREMENT, + group_id INT, -- Pointer to the group + amenity_id INT, -- Pointer to the Amenity + searchable BOOLEAN DEFAULT '0', -- Flag indicating whether the amenity group will show in the search form + PRIMARY KEY (id) +); diff --git a/setup/databaseScripts/update_database_V0.1.0.sql b/setup/databaseScripts/update_database_V0.1.0.sql new file mode 100644 index 0000000..999d876 --- /dev/null +++ b/setup/databaseScripts/update_database_V0.1.0.sql @@ -0,0 +1,18 @@ +-- Gaslight Media Members Database - Events Add-On +-- File Created: 08/30/16 09:47:15 +-- Database Version: 0.1.0 +-- Database Update From Previous Version Script +-- +-- To permit each query below to be executed separately, +-- all queries must be separated by a line with four dashes + +-- Amenities +ALTER TABLE {prefix}management ADD COLUMN term_event_amenities_singular TINYTEXT NULL; -- Singular term to use for event amenities + +---- + +ALTER TABLE {prefix}management ADD COLUMN term_event_amenities_plural TINYTEXT NULL; -- Plural term to use for event amenities + +---- + +ALTER TABLE {prefix}management ADD COLUMN use_event_amenities BOOLEAN NULL; -- Whether amenities are used at all for events \ No newline at end of file diff --git a/setup/validActions.php b/setup/validActions.php index 6154de8..c86818c 100644 --- a/setup/validActions.php +++ b/setup/validActions.php @@ -51,7 +51,8 @@ $glmMembersEventsAddOnValidActions = array( 'list' => GLM_MEMBERS_EVENTS_PLUGIN_SLUG, ), 'settings' => array( - 'eventCategories' => GLM_MEMBERS_EVENTS_PLUGIN_SLUG + 'eventCategories' => GLM_MEMBERS_EVENTS_PLUGIN_SLUG, + 'eventAmenities' => GLM_MEMBERS_EVENTS_PLUGIN_SLUG, ), 'management' => array( 'events' => GLM_MEMBERS_EVENTS_PLUGIN_SLUG diff --git a/views/admin/events/edit.html b/views/admin/events/edit.html index f7d1c55..4ded1b6 100644 --- a/views/admin/events/edit.html +++ b/views/admin/events/edit.html @@ -785,7 +785,7 @@ // If there's no name, tell the user we need one. if (newCatName == '') { $('#newCatNameTD').addClass('glm-form-bad-input'); - $('#newCatNameRequired').text('A catogory name is required!'); + $('#newCatNameRequired').text('A category name is required!'); return false; } @@ -825,6 +825,125 @@ minWidth: 400, dialogClass: "glm-dialog-no-close" }); + + /* + * Amenity Selection + */ + + // Action to select a amenity + $('#amenitySelect').change( function() { + + // Get the ID, name, and parent of the amenity + var amenityValue = $('#amenitySelect').val(); + var amenityName = $('#amenitySelect').find(':selected').text(); + var amenityParent = $('#amenitySelect').find(':selected').attr('data-parent'); + + // Check if the amenity has already been added + var found = false; + $(".glm-events-amenity").each( function() { + var id = $(this).attr('data-id'); + if (id == amenityValue) { + found = true; + } + }); + + // Check if there's a parent + parentName = ''; + if (amenityParent != '') { + parentName = amenityParent + ': '; + } + + // If not found, Add the amenity + if (!found) { + $('#activeAmenities').append('
' + + parentName + amenityName.trim() + ' X' + + '
'); + } + + // Reset picklist + $('#amenitySelect').val(''); + + }); + + // Action to de-select a amenity + $('.amenityDelete').live('click', function() { + $(this).parent().remove(); + }); + + /* + * New amenity Dialog + */ + + var newAmenity = 0; // Used for new amenity numbering (new amenitys are negative numbers) + + // Setup dialog box for adding a new amenity + $("#newAmenityDialog").dialog({ + autoOpen: false, + minWidth: 400, + dialogClass: "glm-dialog-no-close" + }); + + // Ad a new amenity button action - pop-up dialog + $('#newAmenityButton').click( function() { + $("#newAmenityDialog").dialog("open"); + }); + + // Submit new amenity + $('#newAmenitySubmit').click( function() { + + // Assign new amenity number + newAmenity--; + + // Get new amenity information + var newAmenityName = $('#newAmenityName').val(); + var newAmenityParent = $('#newAmenityParent').val(); + var amenityParent = $('#newAmenityParent').find(':selected').attr('data-parent'); + var newAmenityParentName = $('#newAmenityParentName').val(); + + // If there's no name, tell the user we need one. + if (newAmenityName == '') { + $('#newAmenityNameTD').addClass('glm-form-bad-input'); + $('#newAmenityNameRequired').text('An amenity name is required!'); + return false; + } + + // Check if there's a parent, get the name - new parent name overrides selected parent + parentName = ''; + if (newAmenityParentName && newAmenityParentName != '') { + parentName = newAmenityParentName + ': '; + } else if (amenityParent && amenityParent != '') { + parentName = amenityParent + ': '; + } + + // Add the new amenity to the active amenities list + $('#activeAmenities').append('
' + + parentName + newAmenityName.trim() + ' X' + + '' + + '' + + '' + + '' + + '
'); + + // Clear the dialog input fields + $('#newAmenityName').val(''); + $('#newAmenityParent').val(''); + $('#newAmenityParentName').val(''); + + $("#newAmenityDialog").dialog("close"); + + }); + $('#newAmenityCancel').click( function() { + $("#newAmenityDialog").dialog("close"); + }); + + // Setup dialog box for adding a new amenity + $("#newAmenityDialog").dialog({ + autoOpen: false, + minWidth: 400, + dialogClass: "glm-dialog-no-close" + }); /* * Check for bad input or input changes diff --git a/views/admin/events/editStatus.html b/views/admin/events/editStatus.html index 14f7008..d4a4ec7 100644 --- a/views/admin/events/editStatus.html +++ b/views/admin/events/editStatus.html @@ -129,28 +129,91 @@    Select a category to add to box below.
- {if isset($event.fieldData.categories) && $event.fieldData.categories} - {foreach $event.fieldData.categories as $c} + {if isset($event.fieldData.categories) && $event.fieldData.categories} + {foreach $event.fieldData.categories as $c}
{if $c.parent_name != ''}{$c.parent_name}: {/if}{$c.name} X
- {/foreach} - {/if} + {/foreach} + {/if} +
+ + + + Amenities + + + + +
Add a new Amenity
+
+ + + + + + + + +
Amenity Name: + +
+
+ +
+

* Required

+ Cancel + +
+ + + +    Select a amenity to add to box below.
+
+ + {if isset($event.fieldData.amenities) && $event.fieldData.amenities} + {foreach $event.fieldData.amenities as $amenity} +
+ {$amenity.name} + X + +
+ {/foreach} + {/if}
diff --git a/views/admin/management/events.html b/views/admin/management/events.html index f34bd8c..ec0c46d 100644 --- a/views/admin/management/events.html +++ b/views/admin/management/events.html @@ -69,25 +69,66 @@ - Front-End Calendar View + Front-End Calendar View - - + + +
-
- - - + + + + Activate Event Amenities

+ + + + Event Amenities Terms: + + + + + + + + + + +
Amenities Singular: + + {if $eventsSettings.fieldFail.term_event_amenities_singular}

{$eventsSettings.fieldFail.term_event_amenities_singular}

{/if} +
Amenities Plural: + + {if $eventsSettings.fieldFail.term_event_amenities_plural}

{$eventsSettings.fieldFail.term_event_amenities_plural}

{/if} +
+ + + + + +
+ +
+ + + + + +
+ +
+ + +

E-Mail Notification Settings

diff --git a/views/admin/member/add.html b/views/admin/member/add.html index f755ca9..6177d5a 100644 --- a/views/admin/member/add.html +++ b/views/admin/member/add.html @@ -1,92 +1,82 @@ {include file='admin/member/header.html'} - - Event Details -
-
-

Event Name

- - -

All Day

- -

Active?

- - -

Start Date

- -

End Date

- -

Start Time

- -

End Time

- -

Recurring

- - -
- Location Details -
- -

Hide Event Address

- -

Place

- -

Address

- -

City

- -

State

- -

ZIP Code

- - - -
- Cost and tickets -
- -

Cost

- -

Free Event

- -

Website

- - -
- Event Contact Information -
- -

Contact Name

- -

Contact Phone

- -

Contact Email

- - -
- Event Admin Information -
- -

Contact Name Submitting Event

- -

Organization Name Submitting Event

- -

Contact Phone

- -

Contact Email

- -

Notes

- - - -
- - - - + + Event Details +
+
+

Event Name

+ + +

All Day

+ +

Active?

+ + +

Start Date

+ +

End Date

+ +

Start Time

+ +

End Time

+ +

Recurring

+ +
+ Location Details +
+

Hide Event Address

+ +

Place

+ +

Address

+ +

City

+ +

State

+ +

ZIP Code

+ +
+ Cost and tickets +
+

Cost

+ +

Free Event

+ +

Website

+ +
+ Event Contact Information +
+

Contact Name

+ +

Contact Phone

+ +

Contact Email

+ +
+ Event Admin Information +
+

Contact Name Submitting Event

+ +

Organization Name Submitting Event

+ +

Contact Phone

+ +

Contact Email

+ +

Notes

+ +
+ + +
diff --git a/views/admin/settings/eventAmenities.html b/views/admin/settings/eventAmenities.html new file mode 100644 index 0000000..f33b021 --- /dev/null +++ b/views/admin/settings/eventAmenities.html @@ -0,0 +1,456 @@ +{include file='admin/settings/header.html'} + + + + + +
+ +
Add an Amenity
+
+
+ + + + + + + + + + + + + + + +
Amenity Name: + +
+ + + + + + + {if $haveGroups} + {foreach $groups as $group} + + + + + {/foreach} + {/if} +
Groups
+ + + +
+
+

* Required

+ Cancel + + +
+
+ + +
+
+

Are you sure you want to delete this amenity?

+

Yes, delete this amenity

+

Cancel

+
+
+ + +
+
+ + + + + + + + + + + + + + + + +
Amenity Name: + +
+ + + + + + + {if $haveGroups} + {foreach $groups as $group} + + + + + {/foreach} + {/if} +
Groups
+ + + +
+
+

* Required

+ Cancel + + +
+
+ + +

Event Amenities

+ + + + + + + + + + + + + {if $haveAmenities} + {assign var="i" value="0"} + {foreach $amenities as $t} + {if $i++ is odd by 1} + + {else} + + {/if} + + + + + + + {/foreach} + {else} + + {/if} + +
AmenityUsed WithGroups 
+ {$t.name} + + {$t.ref_type.name} + + {foreach $t.groups as $group} + {$groups[$group.group_id].name} + {/foreach} + +
Delete
+
(no amenities listed)
+
+ + + + +
+ +
Add a Group
+
+
+ + + + + + + + + + + + +
Group Name: + +
+

* Required

+ Cancel + + +
+
+ + +
+
+

Are you sure you want to delete this group?

+

Yes, delete this group

+

Cancel

+
+
+ + +
+
+ + + + + + + + + + + + + +
Group Name: + +
+

* Required

+ Cancel + + +
+
+ +

Groups

+ + + + + + + + + {if $haveGroups} + {assign var="i" value="0"} + {foreach $groups as $t} + {if $i++ is odd by 1} + + {else} + + {/if} + + + + {/foreach} + {else} + + {/if} + +
Group 
+ {$t.name} + +
Delete
+
(no groups listed)
+ +
+ + + +{include file='admin/footer.html'} -- 2.17.1