diff --git a/app_controller.php b/app_controller.php index 9ad388d..5da2ece 100644 --- a/app_controller.php +++ b/app_controller.php @@ -63,11 +63,11 @@ class AppController extends Controller { * - called by function to create an index listing */ - function jqGridView($action, $title) { + function jqGridView($title, $action = null) { $this->set('title', $title); // The resulting page will contain a jqGrid, which will // use ajax to obtain the actual data for this action - $this->set('action', $action); + $this->set('action', $action ? $action : $this->params['action']); $this->render('/elements/' . $this->params['controller']); } @@ -103,13 +103,13 @@ class AppController extends Controller { $total = ($count < 0) ? 0 : ceil($count/$limit); $page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']); $start = $limit*$page - $limit; - $sidx = isset($params['sidx']) ? $params['sidx'] : ''; - $sord = isset($params['sord']) ? ' ' . $params['sord'] : ''; // Grab the actual records taking pagination into account $query['group'] = $model->alias . '.id'; - $query['order'] = $sidx ? $sidx . $sord : null; - $query['limit'] = $start . ', ' . $limit; + $query['order'] = $this->jqGridDataOrder($params, + isset($params['sidx']) ? $params['sidx'] : null, + isset($params['sord']) ? $params['sord'] : null); + $query['limit'] = $this->jqGridDataLimit($params, $start, $limit); $query['fields'] = $this->jqGridDataFields($params); $results = $this->jqGridDataRecords($params, $model, $query); @@ -229,6 +229,17 @@ class AppController extends Controller { return null; } + function jqGridDataOrder(&$params, $index, $direction) { + if ($direction) + $direction = ' ' . $direction; + + return $index ? $index . $direction : null; + } + + function jqGridDataLimit(&$params, $start, $limit) { + return $start . ', ' . $limit; + } + function jqGridDataRecordCount(&$params, $model, $query) { return $model->find('count', $query); } diff --git a/controllers/customers_controller.php b/controllers/customers_controller.php index 65b7fd5..e8d5af1 100644 --- a/controllers/customers_controller.php +++ b/controllers/customers_controller.php @@ -30,9 +30,9 @@ class CustomersController extends AppController { */ function index() { $this->current(); } - function current() { $this->jqGridView('current', 'Current Tenants'); } - function past() { $this->jqGridView('past', 'Past Tenants'); } - function all() { $this->jqGridView('all', 'All Tenants'); } + function current() { $this->jqGridView('Current Tenants'); } + function past() { $this->jqGridView('Past Tenants'); } + function all() { $this->jqGridView('All Tenants', 'all'); } /************************************************************************** diff --git a/controllers/leases_controller.php b/controllers/leases_controller.php index ecc593a..13ca357 100644 --- a/controllers/leases_controller.php +++ b/controllers/leases_controller.php @@ -1,10 +1,6 @@ 100, - 'group' => 'Lease.id', - 'order' => array('Lease.movein_date' => 'DESC')); var $sidemenu_links = array(array('name' => 'Leases', 'header' => true), @@ -28,24 +24,52 @@ class LeasesController extends AppController { /************************************************************************** ************************************************************************** ************************************************************************** - * action: index - * - Lists current leases + * action: index / active / closed / all + * - Generate a listing of leases */ - function index() { - $this->active(); - } + function index() { $this->all(); } + function active() { $this->jqGridView('Active Leases'); } + function closed() { $this->jqGridView('Closed Leases'); } + function all() { $this->jqGridView('All Leases'); } /************************************************************************** ************************************************************************** ************************************************************************** - * action: active - * - Lists all active leases + * virtuals: jqGridData + * - With the application controller handling the jqGridData action, + * these virutal functions ensure that the correct data is passed + * to jqGrid. */ - function active() { - $leases = $this->paginate(array('Lease.close_date IS NULL')); + function jqGridDataSetup(&$params) { + parent::jqGridDataSetup($params); + if (!isset($params['action'])) + $params['action'] = 'all'; + } + + function jqGridDataTables(&$params) { + return array + ('link' => array('Unit' => array('fields' => array('Unit.name')), + 'Customer' => array('fields' => array('Customer.name')))); + } + + function jqGridDataConditions(&$params) { + $conditions = parent::jqGridDataConditions($params); + + if ($params['action'] === 'active') { + $conditions[] = 'Lease.close_date IS NULL'; + } + elseif ($params['action'] === 'closed') { + $conditions[] = 'Lease.close_date IS NOT NULL'; + } + + return $conditions; + } + + function jqGridDataRecords(&$params, $model, $query) { + $leases = parent::jqGridDataRecords($params, $model, $query); // Get the balance on each lease. foreach ($leases AS &$lease) { @@ -53,56 +77,7 @@ class LeasesController extends AppController { $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; } - $title = 'Active Leases'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('leases', $leases); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: closed - * - Lists all closed (inactive) leases - */ - - function closed() { - $leases = $this->paginate(array('Lease.close_date IS NOT NULL')); - - // Get the balance on each lease. - foreach ($leases AS &$lease) { - $stats = $this->Lease->stats($lease['Lease']['id']); - $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; - } - - $title = 'Past Leases'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('leases', $leases); - $this->render('index'); - } - - - /************************************************************************** - ************************************************************************** - ************************************************************************** - * action: all - * - Lists all leases - */ - - function all() { - $leases = $this->paginate(); - - // Get the balance on each lease. - foreach ($leases AS &$lease) { - $stats = $this->Lease->stats($lease['Lease']['id']); - $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; - } - - $title = 'All Leases'; - $this->set('title', $title); $this->set('heading', $title); - $this->set('leases', $leases); - $this->render('index'); + return $leases; } diff --git a/controllers/units_controller.php b/controllers/units_controller.php index 86153fd..9fec73c 100644 --- a/controllers/units_controller.php +++ b/controllers/units_controller.php @@ -1,9 +1,6 @@ 100, - 'group' => 'Unit.id', - 'order' => array('Unit.sort_order' => 'ASC')); var $sidemenu_links = array(array('name' => 'Units', 'header' => true), @@ -28,15 +25,15 @@ class UnitsController extends AppController { /************************************************************************** ************************************************************************** ************************************************************************** - * action: index / current / past / all - * - Creates a list of tenants + * action: index / unavailable / vacant / occupied / all + * - Generate a listing of units */ function index() { $this->all(); } - function unavailable() { $this->jqGridView('unavailable', 'Unavailable Units'); } - function vacant() { $this->jqGridView('vacant', 'Vacant Units'); } - function occupied() { $this->jqGridView('occupied', 'Occupied Units'); } - function all() { $this->jqGridView('all', 'All Units'); } + function unavailable() { $this->jqGridView('Unavailable Units'); } + function vacant() { $this->jqGridView('Vacant Units'); } + function occupied() { $this->jqGridView('Occupied Units'); } + function all() { $this->jqGridView('All Units', 'all'); } /************************************************************************** @@ -89,40 +86,13 @@ class UnitsController extends AppController { return $conditions; } - function zzjqGridDataRecordCount(&$params, $model, $query) { - - // We don't have a good way to use the query to obtain - // our count. The problem is that we're relying on the - // group by for the query, which will destroy the count, - // whether we omit the group by or leave it in. - // So, build a fresh query for counting. - - $query['conditions'] = parent::jqGridDataConditions($params); - - $count = $model->find('count', - array_merge(array('link' => array_diff_key($query['link'], - array('CurrentLease'=>1))), - array_diff_key($query, array('link'=>1)))); - - if ($params['action'] === 'all') - return $count; - - $query['conditions'][] = 'CurrentLease.id IS NULL'; - $count_past = $model->find('count', $query); - - // Since we can't easily count 'current' directly, we - // can quickly derive it since 'current' customers - // are mutually exclusive to 'past' customers. - if ($params['action'] == 'current') - $count = $count - $count_past; - elseif ($params['action'] == 'past') { - $count = $count_past; + function jqGridDataOrder(&$params, $index, $direction) { + if ($index === 'Unit.name') { + $index = 'Unit.sort_order'; } - - return $count; + return parent::jqGridDataOrder($params, $index, $direction); } - /************************************************************************** ************************************************************************** ************************************************************************** diff --git a/views/elements/customers.ctp b/views/elements/customers.ctp index faeb05a..d779a70 100644 --- a/views/elements/customers.ctp +++ b/views/elements/customers.ctp @@ -2,22 +2,14 @@ // Define the table columns $cols = array(); -$cols['ID'] = array('index' => 'Customer.id', 'width' => '30', 'align' => 'center'); -if (isset($customers[0]['ContactsCustomer'])) - $cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'width' => '75', 'align' => 'left'); -$cols['Name'] = array('index' => 'Customer.name', 'width' => '150', 'align' => 'left'); -$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100', 'align' => 'left'); -$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100', 'align' => 'left'); -$cols['Leases'] = array('index' => 'lease_count', 'width' => '60', 'align' => 'center'); -$cols['Comment'] = array('index' => 'Customer.comment', 'width' => '300', 'align' => 'left'); - -// Some of the columns should not be sortable -foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v) - $cols[$k]['sortable'] = false; - -// Some of the columns should be searchable -foreach (array_intersect_key($cols, array('Last Name'=>1, 'First Name'=>1)) AS $k => $v) - $cols[$k]['search'] = true; +$cols['ID'] = array('index' => 'Customer.id', 'formatter' => 'id'); +if (0) // REVISIT: Need to figure out how to put this in play + $cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'width' => '75'); +$cols['Name'] = array('index' => 'Customer.name', 'width' => '150'); +$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100'); +$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100'); +$cols['Leases'] = array('index' => 'lease_count', 'width' => '60'); +$cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment'); echo $this->element('jqGrid', array('jqGridColumns' => $cols)); diff --git a/views/elements/jqGrid.ctp b/views/elements/jqGrid.ctp index bc3e9a9..477970c 100644 --- a/views/elements/jqGrid.ctp +++ b/views/elements/jqGrid.ctp @@ -23,22 +23,75 @@ $javascript->link('jqGrid/jquery.jqGrid.js', false); $javascript->link('jqGrid/js/jqModal', false); $javascript->link('jqGrid/js/jqDnR', false); -// Create the javascript code for jqGrid to create each table column -$colModels = array(); -foreach ($jqGridColumns AS $col) { - $col['name'] = $col['index']; - $colModels[] = - '{ ' . implode(", ", - array_map(create_function - ('$k, $v', - 'return "$k:".($v===false?"false":($v===true?"true":"\'$v\'"));'), - array_keys($col), - array_values($col))) . - '}'; +// Helper function to convert PHP vars to javascript +function phpVarToJavascript($var, $name = '', $depth='', $special = false) { + + // Establish a prefix to use before printing $var + $prefix = $depth; + + // If given a name, set it up JS style + if ($name) + $prefix .= $name . ": "; + + if (!isset($var)) + return $prefix . 'null'; + + if (is_bool($var)) + return $prefix . ($var ? "true" : "false"); + + if (is_numeric($var)) + return $prefix . $var; + + if (is_string($var)) { + // Check to see if this is a special + if ($special) + return $prefix . $var; + + // OK, must just be a string after all + return $prefix . "'$var'"; + } + + // The only thing left that we know how to dump + // is an array. Die if we have anything else. + if (!is_array($var)) { + die; + return null; + } + + // Keep a lookout for special cases, flagged by '--special' + + // eg: array('name' => array('--special' => array('a' => 'one', 'b' => 'two'))) + // GIVES: name: [ 'one', 'two' ] + // NOT: name: { --special: { a: 'one', b: 'two' } } + + // eg: array('name' => array('--special' => 'varname')) + // GIVES: name: varname + // NOT: name: { --special: 'varname' } + + if (isset($var['--special']) && count($var) == 1) + return phpVarToJavascript($var['--special'], $name, $depth, true); + + // PHP array indices can be a mix of integer and string based. + // Just guess here, unless flagged as a special case. + if (isset($var[0]) || $special) + return ($prefix . "[\n" + . implode(",\n", + array_map('phpVarToJavascript', + array_values($var), + array(), + array_fill(0, count($var), $depth.' ') + )) + . "\n$depth]"); + + return ($prefix . "{\n" + . implode(",\n", + array_map('phpVarToJavascript', + array_values($var), array_keys($var), + array_fill(0, count($var), $depth.' ') + )) + . "\n$depth}"); } -// Save just the column indices (fields) -$colFields= array_map(create_function('$col', 'return $col["index"];'), $jqGridColumns); // Define the URL to fetch data from. // To prevent having to keep the controller and the view @@ -51,6 +104,57 @@ $url = $html->url(array('action' => 'jqGridData', 'debug' => 0, )); +// Create extra parameters that jqGrid will pass to our +// controller whenever data is requested. 'action' will +// ensure that the controller provides the correct subset +// of data, and 'fields' will allow it to return only the +// requested fields, and in the right order. Since fields +// is a complex structure (an array), we'll need to +// serialize it first for transport over HTTP. +$postData = array('action' => $action, + 'fields' => serialize(array_map(create_function('$col', + 'return $col["index"];'), + $jqGridColumns))); + + +// Perform column customizations. +// This will largely be based off of the 'formatter' parameter, +// but could be on any pertinent condition. +foreach ($jqGridColumns AS &$col) { + $default = array(); + + // Make sure every column has a name + $default['name'] = $col['index']; + + // Perform customization based on formatter + if (isset($col['formatter'])) { + if ($col['formatter'] === 'id') { + // Switch currency over to our own custom formatting + $col['formatter'] = array('--special' => 'idFormatter'); + $default['width'] = 50; + $default['align'] = 'center'; + } + elseif ($col['formatter'] === 'currency') { + // Switch currency over to our own custom formatting + $col['formatter'] = array('--special' => 'currencyFormatter'); + $default['width'] = 80; + $default['align'] = 'right'; + } + elseif ($col['formatter'] === 'date') { + $default['formatoptions'] = array('newformat' => 'm/d/Y'); + $default['width'] = 90; + $default['align'] = 'center'; + } + elseif ($col['formatter'] === 'comment') { + $default['width'] = 300; + $default['sortable'] = false; + } + } + + $col = array_merge($default, $col); +} + + // OK, now that everything is in place, get out of PHP mode, // and add the javascript code (along with a touch of HTML) // to kick this thing off. @@ -59,25 +163,34 @@ $url = $html->url(array('action' => 'jqGridData',