Made the app controller include the action by default. Added virtual callouts for data order and limit. Changed fields to use formatting, including a custom format for currency and id. Added a function for auto conversion from PHP variables to javascript. Fixed some minor bugs in the controllers already converted to jqGrid. Moved leases onto jqGrid.

git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605/site@118 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-06-14 19:50:09 +00:00
parent 67d640b1a0
commit 92d8387e8c
10 changed files with 260 additions and 254 deletions

View File

@@ -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);
}

View File

@@ -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'); }
/**************************************************************************

View File

@@ -1,10 +1,6 @@
<?php
class LeasesController extends AppController {
var $paginate = array
('limit' => 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;
}

View File

@@ -1,9 +1,6 @@
<?php
class UnitsController extends AppController {
var $paginate = array('limit' => 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);
}
/**************************************************************************
**************************************************************************
**************************************************************************

View File

@@ -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<AP>: 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));

View File

@@ -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',
<script type="text/javascript"><!--
jQuery(document).ready(function(){
jQuery('#<?php echo $gridId; ?>').jqGrid({
url: '<?php echo $url; ?>',
datatype: 'xml',
mtype: 'GET',
postData: { action: '<?php echo $action; ?>',
fields: '<?php echo serialize($colFields); ?>' },
colNames: [ '<?php echo implode("', '", array_keys($jqGridColumns)); ?>' ],
colModel: [ <?php echo "\n " . implode(",\n ", $colModels); ?> ],
pager: jQuery('#<?php echo $gridId; ?>-pager'),
height: '<?php echo $height; ?>',
rowNum: <?php echo $limit; ?>,
rowList: [<?php echo implode(",",$limitOptions); ?>],
/* sortname: 'Customer.id', */
/* sortorder: "ASC", */
viewrecords: true,
imgpath: '<?php echo $imgpath; ?>',
caption: <?php echo $caption ? "'$caption'" : "null"; ?>,
/* toolbar : [true,"bottom"], */
});
currencyFormatter = function(el, cellval, opts) {
$(el).html(fmtCurrency(cellval));
}
idFormatter = function(el, cellval, opts) {
$(el).html('#'+cellval);
}
jQuery('#<?php echo $gridId; ?>').jqGrid(
<?php
echo phpVarToJavascript(array('mtype' => 'GET',
'datatype' => 'xml',
'url' => $url,
'postData' => $postData,
'colNames' => array_keys($jqGridColumns),
'colModel' => array('--special' => $jqGridColumns),
/* 'sortname' => 'id', */
/* 'sortorder' => 'ASC', */
'height' => $height,
'rowNum' => $limit,
'rowList' => $limitOptions,
'caption' => $caption,
'imgpath' => $imgpath,
'viewrecords' => true,
'pager' => array('--special' => "jQuery('#{$gridId}-pager')"),
//'toolbar' => array(true,"bottom"),
)); ?>
);
/* jQuery('#t_<?php echo $gridId; ?>').height(25).hide() */
/* .filterGrid('#<?php echo $gridId; ?>', { */
@@ -112,6 +225,7 @@ jQuery(document).ready(function(){
<table id="<?php echo $gridId; ?>" class="scroll"></table>
<div id="<?php echo $gridId; ?>-pager" class="scroll" style="text-align:center;"></div>
<div id="debug"></div>
<script type="text/javascript"><!--

View File

@@ -1,85 +1,16 @@
<?php /* -*- mode:PHP -*- */
if (isset($heading))
echo $heading;
elseif (!isset($caption))
echo '<h2>'.__('Leases',true).'</h2>';
// Define the table columns
$cols = array();
$cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id');
$cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'center');
$cols['Customer'] = array('index' => 'Customer.name', 'width' => '150');
$cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date');
$cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date');
$cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date');
$cols['Balance'] = array('index' => 'Lease.balance', 'formatter' => 'currency');
$cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment');
$headers = array_merge(array('Lease'),
isset($leases[0]['Unit'])
? array('Unit')
: array('Customer'),
array('Signed', 'Move-In', 'Move-Out', 'Balance', 'Comment'));
$column_class = array();
foreach (array_intersect($headers, array('Lease', 'Unit')) AS $k => $v) {
$column_class[$k] = 'id';
}
foreach (array_intersect($headers, array('Balance')) AS $k => $v) {
$column_class[$k] = 'currency';
}
foreach (array_intersect($headers, array('Comment')) AS $k => $v) {
$column_class[$k] = 'slack';
}
echo $this->element('jqGrid',
array('jqGridColumns' => $cols));
if (isset($paginator)) {
echo $paginator->counter(array('format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true)));
$headers = array_merge(array($paginator->sort('Lease')),
isset($leases[0]['Unit'])
? array($paginator->sort('Unit', 'Unit.id'))
: array($paginator->sort('Customer.id')),
array($paginator->sort('Signed', 'lease_date'),
$paginator->sort('Move-In', 'movein_date'),
$paginator->sort('Move-Out', 'moveout_date'),
$paginator->sort('balance'),
$paginator->sort('comment')));
}
$rows = array();
foreach($leases AS $lease) {
$unit = $customer = null;
if (isset($lease['Unit']))
$unit = $lease['Unit'];
else
$customer = $lease['Customer'];
if (isset($lease['Lease']))
$lease = $lease['Lease'];
$rows[] = array_merge(array($html->link('#'.$lease['number'],
array('controller' => 'leases',
'action' => 'view',
$lease['id']))),
isset($unit)
? array($html->link($unit['name'],
array('controller' => 'units',
'action' => 'view',
$unit['id'])))
: array($html->link($customer['name'],
array('controller' => 'customers',
'action' => 'view',
$customer['id']))),
array(FormatHelper::date($lease['lease_date']),
FormatHelper::date($lease['movein_date']),
FormatHelper::date($lease['moveout_date']),
FormatHelper::currency($lease['balance']),
$lease['comment']));
}
echo $this->element('table',
array('class' => 'item lease list',
'caption' => isset($caption) ? $caption : null,
'headers' => $headers,
'rows' => $rows,
'column_class' => $column_class));
if (isset($paginator)) {
echo('<div class="paging">' . "\n");
echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled'));
echo(' | ');
echo $paginator->numbers();
echo(' | ');
echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled'));
echo('</div>' . "\n");
}

View File

@@ -2,15 +2,11 @@
// Define the table columns
$cols = array();
$cols['ID'] = array('index' => 'Unit.id', 'width' => '30', 'align' => 'center');
$cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'left');
$cols['Size'] = array('index' => 'UnitSize.name', 'width' => '75', 'align' => 'left');
$cols['Status'] = array('index' => 'Unit.status', 'width' => '75', 'align' => 'left');
$cols['Comment'] = array('index' => 'Unit.comment', 'width' => '400', '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;
$cols['ID'] = array('index' => 'Unit.id', 'formatter' => 'id');
$cols['Unit'] = array('index' => 'Unit.name', 'width' => '50');
$cols['Size'] = array('index' => 'UnitSize.name', 'width' => '75');
$cols['Status'] = array('index' => 'Unit.status', 'width' => '75');
$cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment');
echo $this->element('jqGrid',
array('jqGridColumns' => $cols));

View File

@@ -1,3 +0,0 @@
<div class="leases index">
<?php echo $this->element('leases', array('heading' => '<h2>'.$heading.'</h2>')) ?>
</div>

View File

@@ -114,3 +114,23 @@ $("#debug").append(htmlEncode(html));
function removeElement(elem_id) {
$('#'+elem_id).remove();
}
function fmtCurrency(amount) {
if (amount == null || isNaN(amount))
return '-';
// Get rid of any extraneous characters, determine
// the sign, and round to the nearest cent.
amount = amount.toString().replace(/\$|\,/g,'');
sign = (amount == (amount = Math.abs(amount)));
amount = (amount+0.0000000001).toFixed(2);
// Insert thousands separator
while (amount != (amount = amount.replace(/(\d)(\d\d\d[.,])/, "$1,$2")));
// Return formatted amount
return (sign?'$':'($') + amount + (sign?'':')');
}