From cc4219714ab859f80939cc4a5b45de859ccd359a Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Tue, 29 Dec 2009 14:02:18 +0000 Subject: [PATCH] - completed the fix of the user object history (Trac #48) - completed the implementation of truncated lists (Trac #61) - Fixed the handling of the search form in the details page (Trac #29) SVN:trunk[214] --- application/cmdbabstract.class.inc.php | 41 +++++++++++++++++++++---- application/displayblock.class.inc.php | 9 +++++- application/itopwebpage.class.inc.php | 1 + application/startup.inc.php | 2 ++ application/uilinkswizard.class.inc.php | 7 +++-- css/light-grey.css | 21 +++++++++++++ js/utils.js | 19 ++++++++++++ pages/UI.php | 41 ++++++++++++++++++++++--- pages/UniversalSearch.php | 4 +-- pages/ajax.render.php | 8 ++++- pages/run_query.php | 4 +-- webservices/export.php | 2 +- 12 files changed, 139 insertions(+), 20 deletions(-) create mode 100644 js/utils.js diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 18d2f4a93..c288b7b26 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -131,7 +131,7 @@ abstract class cmdbAbstractObject extends CMDBObject $oPage->add("

".MetaModel::GetName(get_class($this)).": ".$this->GetDisplayName()."

\n"); // history block (with toggle) - $oHistoryFilter = new DBObjectSearch('CMDBChangeOpSetAttribute'); + $oHistoryFilter = new DBObjectSearch('CMDBChangeOp'); $oHistoryFilter->AddCondition('objkey', $this->GetKey()); $oHistoryFilter->AddCondition('objclass', get_class($this)); $oBlock = new HistoryBlock($oHistoryFilter, 'toggle', false); @@ -269,6 +269,8 @@ abstract class cmdbAbstractObject extends CMDBObject //public static function GetDisplaySet(web_page $oPage, CMDBObjectSet $oSet, $sLinkageAttribute = '', $bDisplayMenu = true, $bSelectMode = false) public static function GetDisplaySet(web_page $oPage, CMDBObjectSet $oSet, $aExtraParams = array()) { + global $g_oConfig; + static $iListId = 0; $iListId++; @@ -341,7 +343,16 @@ abstract class cmdbAbstractObject extends CMDBObject } $aValues = array(); $oSet->Seek(0); - while ($oObj = $oSet->Fetch()) + $bDisplayLimit = isset($aExtraParams['display_limit']) ? $aExtraParams['display_limit'] : true; + $iMaxObjects = -1; + if ($bDisplayLimit) + { + if ($oSet->Count() > $g_oConfig->GetMaxDisplayLimit()) + { + $iMaxObjects = $g_oConfig->GetMinDisplayLimit(); + } + } + while (($oObj = $oSet->Fetch()) && ($iMaxObjects != 0)) { $aRow['key'] = $oObj->GetKey(); if ($bSelectMode) @@ -354,6 +365,7 @@ abstract class cmdbAbstractObject extends CMDBObject $aRow[$sAttCode] = $oObj->GetAsHTML($sAttCode); } $aValues[] = $aRow; + $iMaxObjects--; } $oMenuBlock = new MenuBlock($oSet->GetFilter()); $sHtml .= ''; @@ -367,7 +379,22 @@ abstract class cmdbAbstractObject extends CMDBObject //$aMenuExtraParams['linkage'] = $sLinkageAttribute; $aMenuExtraParams = $aExtraParams; } - $sHtml .= ''; } @@ -570,9 +597,11 @@ abstract class cmdbAbstractObject extends CMDBObject $sHtml .= "
 '.$oSet->Count().' object(s)'; + if ($bDisplayLimit && ($oSet->Count() > $g_oConfig->GetMaxDisplayLimit())) + { + // list truncated + $divId = $aExtraParams['block_id']; + $sFilter = $oSet->GetFilter()->serialize(); + $aExtraParams['display_limit'] = false; // To expand the full list + $sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them + $sHtml .= '
'.$g_oConfig->GetMinDisplayLimit().' object(s) displayed out of '.$oSet->Count().'  Display All'; + $oPage->add_ready_script("$('#{$divId} table.listResults').addClass('truncated');"); + $oPage->add_ready_script("$('#{$divId} table.listResults tr:last td').addClass('truncated');"); + } + else + { + // Full list + $sHtml .= '
 '.$oSet->Count().' object(s)'; + } $sHtml .= $oMenuBlock->GetRenderContent($oPage, $aMenuExtraParams); $sHtml .= '
\n"; foreach($aExtraParams as $sName => $sValue) { - $sHtml .= "\n"; + $sHtml .= "\n"; } - $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; + $sHtml .= "\n"; $sHtml .= "\n"; $sHtml .= "\n"; @@ -598,7 +627,7 @@ abstract class cmdbAbstractObject extends CMDBObject { $sHtml .= "\n"; } - $sHtml .= "\n"; + $sHtml .= "\n"; $sHtml .= "\n"; $sHtml .= "\n"; return $sHtml; diff --git a/application/displayblock.class.inc.php b/application/displayblock.class.inc.php index f05b65e6a..c006bd91a 100644 --- a/application/displayblock.class.inc.php +++ b/application/displayblock.class.inc.php @@ -144,7 +144,10 @@ class DisplayBlock public function Display(web_page $oPage, $sId, $aExtraParams = array()) { + $oPage->add($this->GetDisplay($oPage, $sId, $aExtraParams)); + /* $aExtraParams = array_merge($aExtraParams, $this->m_aParams); + $aExtraParams['block_id'] = $sId; if (!$this->m_bAsynchronous) { // render now @@ -171,12 +174,14 @@ class DisplayBlock ); '); // TO DO: add support for $aExtraParams in asynchronous/Ajax mode } + */ } public function GetDisplay(web_page $oPage, $sId, $aExtraParams = array()) { $sHtml = ''; $aExtraParams = array_merge($aExtraParams, $this->m_aParams); + $aExtraParams['block_id'] = $sId; if (!$this->m_bAsynchronous) { // render now @@ -188,17 +193,19 @@ class DisplayBlock { // render it as an Ajax (asynchronous) call $sFilter = $this->m_oFilter->serialize(); + $sExtraParams = addslashes(str_replace('"', "'", json_encode($aExtraParams))); // JSON encode, change the style of the quotes and escape them $sHtml .= "
\n"; $sHtml .= $oPage->GetP(" Loading..."); $sHtml .= "
\n"; $sHtml .= ' '; // TO DO: add support for $aExtraParams in asynchronous/Ajax mode diff --git a/application/itopwebpage.class.inc.php b/application/itopwebpage.class.inc.php index 1b1bca3d8..6f8698deb 100644 --- a/application/itopwebpage.class.inc.php +++ b/application/itopwebpage.class.inc.php @@ -35,6 +35,7 @@ class iTopWebPage extends nice_web_page $this->add_linked_script("../js/date.js"); $this->add_linked_script("../js/jquery.date.picker.js"); $this->add_linked_script("../js/jquery.tablesorter.min.js"); + $this->add_linked_script("../js/utils.js"); //$this->add_linked_script("../js/jquery-ui-personalized-1.5.3.js"); $this->add_linked_script("../js/swfobject.js"); $this->add_linked_stylesheet("../css/jquery.treeview.css"); diff --git a/application/startup.inc.php b/application/startup.inc.php index 7f3448f30..89b091117 100644 --- a/application/startup.inc.php +++ b/application/startup.inc.php @@ -2,6 +2,8 @@ require_once('../application/utils.inc.php'); +$g_oConfig = new Config('../config-itop.php'); + MetaModel::Startup('../config-itop.php'); ?> diff --git a/application/uilinkswizard.class.inc.php b/application/uilinkswizard.class.inc.php index db57e2075..3779efac1 100644 --- a/application/uilinkswizard.class.inc.php +++ b/application/uilinkswizard.class.inc.php @@ -159,6 +159,7 @@ class UILinksWizard { $('#SearchResultsToAdd table.listResults tbody').attr('height', tbodyHeight); $('#SearchResultsToAdd .listResults tbody').css('overflow', 'auto'); + $('#SearchResultsToAdd .listResults').tablesorter( { headers: { 0:{sorter: false }}, widgets: ['zebra']} ); // sortable and zebra tables } } @@ -214,7 +215,7 @@ class UILinksWizard } $('.listResults tbody').append(data); $('.listResults').trigger('update'); - $('.listResults').tablesorter( { headers: { 0:{sorter: false }}, widgets: ['zebra']} ); // sortable and zebra tables + $('.listResults').tablesorter( { headers: { 0:{sorter: false }}, widgets: ['zebra']} ); // sortable and zebra tables }, 'html' ); @@ -362,12 +363,12 @@ class UILinksWizard public function SearchObjectsToAdd(web_page $oP, UserContext $oContext) { - $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sLinkageAttr); + //$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $this->m_sLinkageAttr); $oFilter = $oContext->NewFilter($this->m_sLinkedClass); $oSet = new CMDBObjectSet($oFilter); $oBlock = new DisplayBlock($oFilter, 'list', false); - $oBlock->Display($oP, 'ResultsToAdd', array('menu' => false, 'selection_mode' => true)); // Don't display the 'Actions' menu on the results + $oBlock->Display($oP, 'ResultsToAdd', array('menu' => false, 'selection_mode' => true, 'display_limit' => false)); // Don't display the 'Actions' menu on the results } public function DoAddObjects(web_page $oP, UserContext $oContext, $aLinkedObjectIds = array()) diff --git a/css/light-grey.css b/css/light-grey.css index 994bf7a3b..ac9df52d8 100644 --- a/css/light-grey.css +++ b/css/light-grey.css @@ -663,3 +663,24 @@ div.HRDrawer { .mandatory { border: 1px solid #f00; } +table.listResults tr td.truncated { + background: transparent; +} + +table.listResults tr td.truncated { + background: url(../images/truncated.png) bottom repeat-x; + margin-bottom: -3px; +} + +table.listResults tr.even td.truncated { + background: #f9f9f1 url(../images/truncated.png) bottom repeat-x; +} + +table.listResults tr.even td.truncated.hover { + background: #E8FFD3 url(../images/truncated.png) bottom repeat-x; +} + +table.listResults.truncated { + border-bottom: 0; + padding-bottom: 0; +} diff --git a/js/utils.js b/js/utils.js new file mode 100644 index 000000000..9cdf7f9fd --- /dev/null +++ b/js/utils.js @@ -0,0 +1,19 @@ +// Some general purpose JS functions for the iTop application +/** + * Reload a truncated list + */ +function ReloadTruncatedList(divId, sSerializedFilter, sExtraParams) +{ + $('#'+divId).addClass('loading'); + //$('#'+divId).blockUI(); + $.get('ajax.render.php?filter='+sSerializedFilter+'&style=list', + { operation: 'ajax', extra_params: sExtraParams }, + function(data){ + $('#'+divId).empty(); + $('#'+divId).append(data); + $('#'+divId).removeClass('loading'); + $('#'+divId+' .listResults').tablesorter( { headers: { 0:{sorter: false }}, widgets: ['zebra']} ); // sortable and zebra tables + //$('#'+divId).unblockUI(); + } + ); +} diff --git a/pages/UI.php b/pages/UI.php index b20da6808..aeaf59fde 100644 --- a/pages/UI.php +++ b/pages/UI.php @@ -74,7 +74,7 @@ switch($operation) } break; - case 'search_form': + case 'search_oql': $sOQLClass = utils::ReadParam('oql_class', ''); $sOQLClause = utils::ReadParam('oql_clause', ''); $sFormat = utils::ReadParam('format', ''); @@ -128,7 +128,39 @@ switch($operation) } } break; - + case 'search_form': + $sClass = utils::ReadParam('class', ''); + $sFormat = utils::ReadParam('format', 'html'); + $bSearchForm = utils::ReadParam('search_form', true); + if (empty($sClass)) + { + $oP->set_title("iTop - Error"); + $oP->add("

'class' must be specifed for this operation.

\n"); + } + else + { + $oP->set_title("iTop - Search results"); + $oFilter = $oContext->NewFilter($sClass); + $oSet = new DBObjectSet($oFilter); + if ($bSearchForm) + { + $oBlock = new DisplayBlock($oFilter, 'search', false /* Asynchronous */, array('open' => true)); + $oBlock->Display($oP, 0); + } + if (strtolower($sFormat) == 'csv') + { + $oBlock = new DisplayBlock($oFilter, 'csv', false); + $oBlock->Display($oP, 1); + $oP->add_ready_script(" $('#csv').css('height', '95%');"); // adjust the size of the block + } + else + { + $oBlock = new DisplayBlock($oFilter, 'list', false); + $oBlock->Display($oP, 1); + } + } + break; + case 'search': $sFilter = utils::ReadParam('filter', ''); $sFormat = utils::ReadParam('format', ''); @@ -158,7 +190,7 @@ switch($operation) else { $oBlock = new DisplayBlock($oFilter, 'list', false); - $oBlock->Display($oP, 0); + $oBlock->Display($oP, 1); } } break; @@ -173,6 +205,7 @@ switch($operation) { $oP->p("

Results for '$sFullText':

\n"); $iCount = 0; + $iBlock = 0; // Search in full text mode in all the classes foreach(MetaModel::GetClasses('bizmodel') as $sClassName) { @@ -198,7 +231,7 @@ switch($operation) $oP->add("\n"); $oLeafsFilter->AddCondition('pkey', $aLeafs, 'IN'); $oBlock = new DisplayBlock($oLeafsFilter, 'list', false); - $oBlock->Display($oP, 0); + $oBlock->Display($oP, $iBlock++); } } } diff --git a/pages/UniversalSearch.php b/pages/UniversalSearch.php index 3fe8fe246..05333aa7a 100644 --- a/pages/UniversalSearch.php +++ b/pages/UniversalSearch.php @@ -73,11 +73,11 @@ if ($oFilter != null) { $oSet = new CMDBObjectSet($oFilter); $oBlock = new DisplayBlock($oFilter, 'search', false); - $oBlock->Display($oP, 0); + $oBlock->Display($oP, 0, array('open' => true)); // Search results $oResultBlock = new DisplayBlock($oFilter, 'list', false); - $oResultBlock->RenderContent($oP); + $oResultBlock->Display($oP, 1); // Menu node $sFilter = $oFilter->ToOQL(); diff --git a/pages/ajax.render.php b/pages/ajax.render.php index c3d783340..682e3efca 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -100,6 +100,12 @@ switch($operation) case 'ajax': if ($sFilter != "") { + $sExtraParams = stripslashes(utils::ReadParam('extra_params', '')); + $aExtraParams = array(); + if (!empty($sExtraParams)) + { + $aExtraParams = json_decode(str_replace("'", '"', $sExtraParams), true /* associative array */); + } if ($sEncoding == 'sibusql') { $oFilter = CMDBSearchFilter::FromSibusQL($sFilter); @@ -109,7 +115,7 @@ switch($operation) $oFilter = CMDBSearchFilter::unserialize($sFilter); } $oDisplayBlock = new DisplayBlock($oFilter, $sStyle, false); - $oDisplayBlock->RenderContent($oPage); + $oDisplayBlock->RenderContent($oPage, $aExtraParams); } else { diff --git a/pages/run_query.php b/pages/run_query.php index 8214bd8ed..2457121bf 100644 --- a/pages/run_query.php +++ b/pages/run_query.php @@ -109,8 +109,8 @@ try { $oP->add("

Query results

\n"); - $oSet = new CMDBObjectSet($oFilter); - cmdbAbstractObject::DisplaySet($oP, $oSet); + $oResultBlock = new DisplayBlock($oFilter, 'list', false); + $oResultBlock->Display($oP, 1); $oP->p(''); $oP->StartCollapsibleSection('More info on the query', false); diff --git a/webservices/export.php b/webservices/export.php index 912ddebfa..302b88566 100644 --- a/webservices/export.php +++ b/webservices/export.php @@ -47,7 +47,7 @@ if (!empty($sExpression)) } $sUrl = "$sProtocol://{$sServerName}{$sPort}/pages/"; $oP->set_base($sUrl); - cmdbAbstractObject::DisplaySet($oP, $oSet, array('menu' => false)); + cmdbAbstractObject::DisplaySet($oP, $oSet, array('menu' => false, 'display_limit' => false)); // no menu, no truncated list break; case 'csv':