From 67c92ab94650adeb225a12f08792429617ebb5a1 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Wed, 9 Mar 2016 18:05:14 +0000 Subject: [PATCH] Modified the "List" tab of the Impact Analysis to display only the actually impacted objects. The content of this tab is now refreshed every time the graph is rebuilt to take into account the "context" changes which causes the actual impact to change, or the filtering. SVN:trunk[3941] --- core/displayablegraph.class.inc.php | 38 ++++++++++++++++++++++++++++- js/simple_graph.js | 23 +++++++++++++++++ pages/UI.php | 11 +++++++++ pages/ajax.render.php | 19 ++++++++++++++- 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/core/displayablegraph.class.inc.php b/core/displayablegraph.class.inc.php index 4d80811e8..1d09070f6 100644 --- a/core/displayablegraph.class.inc.php +++ b/core/displayablegraph.class.inc.php @@ -1116,7 +1116,7 @@ class DisplayableGraph extends SimpleGraph { $aContextDefs = static::GetContextDefinitions($sContextKey, false); - $aData = array('nodes' => array(), 'edges' => array(), 'groups' => array()); + $aData = array('nodes' => array(), 'edges' => array(), 'groups' => array(), 'lists' => array()); $iGroupIdx = 0; $oIterator = new RelationTypeIterator($this, 'Node'); foreach($oIterator as $sId => $oNode) @@ -1139,10 +1139,35 @@ class DisplayableGraph extends SimpleGraph $aData['groups'][$iGroupIdx] = array('class' => $sClass, 'keys' => $aKeys); $oNode->SetProperty('group_index', $iGroupIdx); $iGroupIdx++; + + if ($oNode->GetProperty('is_reached')) + { + // Also add the objects from this group into the 'list' tab + if (!array_key_exists($sClass, $aData['lists'])) + { + $aData['lists'][$sClass] = $aKeys; + } + else + { + $aData['lists'][$sClass] = array_merge($aData['lists'][$sClass], $aKeys); + } + + } + } + if (($oNode instanceof DisplayableNode) && $oNode->GetProperty('is_reached') && is_object($oNode->GetProperty('object'))) + { + $sObjClass = get_class($oNode->GetProperty('object')); + if (!array_key_exists($sObjClass, $aData['lists'])) + { + $aData['lists'][$sObjClass] = array(); + } + $aData['lists'][$sObjClass][] = $oNode->GetProperty('object')->GetKey(); } $aData['nodes'][] = $oNode->GetForRaphael($aContextDefs); } + uksort($aData['lists'], array(get_class($this), 'SortOnClassLabel')); // sort on the localized names of the classes to provide a consistent and stable order + $oIterator = new RelationTypeIterator($this, 'Edge'); foreach($oIterator as $sId => $oEdge) { @@ -1158,6 +1183,17 @@ class DisplayableGraph extends SimpleGraph return json_encode($aData); } + /** + * Sort class "codes" based on their localized name + * @param string $sClass1 + * @param string $sClass2 + * @return number -1, 0 or 1 + */ + public static function SortOnClassLabel($sClass1, $sClass2) + { + return strcasecmp(MetaModel::GetName($sClass1), MetaModel::GetName($sClass2)); + } + /** * Renders the graph in a PDF document: centered in the current page * @param PDFPage $oPage The PDFPage representing the PDF document to draw into diff --git a/js/simple_graph.js b/js/simple_graph.js index 15c6915bd..447bf5e9f 100644 --- a/js/simple_graph.js +++ b/js/simple_graph.js @@ -720,6 +720,10 @@ $(function() { this.refresh_groups(oData.groups); } + if (oData.lists) + { + this.refresh_lists(oData.lists); + } if (this.element.is(':visible')) { this._updateBBox(); @@ -754,6 +758,25 @@ $(function() } } }, + refresh_lists: function(aLists) + { + if ($('#impacted_objects_lists').length > 0) + { + // The "Lists" tab is present, refresh it + if (aLists.length == 0) + { + $('#impacted_objects_lists').html(''); + } + else + { + $('#impacted_objects_lists').html(''); + var sUrl = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php'; + $.post(sUrl, { operation: 'relation_lists', lists: aLists }, function(data) { + $('#impacted_objects_lists').html(data); + }); + } + } + }, _reset_pan_and_zoom: function() { this.xPan = 0; diff --git a/pages/UI.php b/pages/UI.php index e0e42b6ef..b224e7251 100644 --- a/pages/UI.php +++ b/pages/UI.php @@ -230,6 +230,11 @@ function DisplayNavigatorListTab($oP, $aResults, $sRelation, $sDirection, $oObj) $sOldRelation = 'depends on'; } $oP->add("

".MetaModel::GetRelationDescription($sOldRelation).' '.$oObj->GetName()."

\n"); + $oP->add("
"); + /* + * Content is rendered asynchronously via pages/ajax.render.php?operation=relation_lists + */ + /* $iBlock = 1; // Zero is not a valid blockid foreach($aResults as $sListClass => $aObjects) { @@ -241,6 +246,8 @@ function DisplayNavigatorListTab($oP, $aResults, $sRelation, $sDirection, $oObj) $oBlock->Display($oP, $iBlock++, array('table_id' => get_class($oObj).'_'.$sRelation.'_'.$sDirection.'_'.$sListClass)); $oP->P(' '); // Some space ? } + */ + $oP->add("
"); $oP->add(""); } @@ -1518,6 +1525,10 @@ EOF } } } + $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/tabularfieldsselector.js'); + $oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.dragtable.js'); + $oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/dragtable.css'); + // Display the tabs if ($sFirstTab == 'list') { diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 5da424c2b..b582cd26a 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -2011,7 +2011,24 @@ EOF $oPage->p(' '); // Some space ? } break; - + + case 'relation_lists': + $aLists = utils::ReadParam('lists'); + $iBlock = 1; // Zero is not a valid blockid + foreach($aLists as $sListClass => $aKeys) + { + $oSearch = new DBObjectSearch($sListClass); + $oSearch->AddCondition('id', $aKeys, 'IN'); + + $oPage->add("
\n"); + $oPage->add("

".MetaModel::GetClassIcon($sListClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aKeys), Metamodel::GetName($sListClass))."

\n"); + $oPage->add("
\n"); + $oBlock = new DisplayBlock($oSearch, 'list'); + $oBlock->Display($oPage, 'list_'.$iBlock++, array('table_id' => 'ImpactAnalysis_'.$sListClass)); + $oPage->p(' '); // Some space ? + } + break; + case 'ticket_impact': require_once(APPROOT.'core/simplegraph.class.inc.php'); require_once(APPROOT.'core/relationgraph.class.inc.php');