浏览代码

Allow to filter which class(es) of objects are displayed in the graphical impact analysis view

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1741 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 13 年之前
父节点
当前提交
aaf4dbd6c9
共有 7 个文件被更改,包括 173 次插入33 次删除
  1. 1 0
      dictionaries/dictionary.itop.ui.php
  2. 1 1
      dictionaries/fr.dictionary.itop.ui.php
  3. 60 9
      navigator/iTop/Navigator.as
  4. 二进制
      navigator/navigator.fla
  5. 二进制
      navigator/navigator.swf
  6. 81 5
      pages/UI.php
  7. 30 18
      pages/xml.navigator.php

+ 1 - 0
dictionaries/dictionary.itop.ui.php

@@ -886,6 +886,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
 	'UI:RelationshipGraph' => 'Graphical view',
 	'UI:RelationshipList' => 'List',
 	'UI:OperationCancelled' => 'Operation Cancelled',
+	'UI:ElementsDisplayed' => 'Filtering',
 
 	'Portal:Title' => 'iTop user portal',
 	'Portal:Refresh' => 'Refresh',

+ 1 - 1
dictionaries/fr.dictionary.itop.ui.php

@@ -730,7 +730,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
 	'UI:DisplayThisMessageAtStartup' => 'Afficher ce message au démarrage',
 	'UI:RelationshipGraph' => 'Vue graphique',
 	'UI:RelationshipList' => 'Liste',
-	'UI:ElementsDisplayed' => 'Eléments Affichés',
+	'UI:ElementsDisplayed' => 'Filtrage',
 	'UI:OperationCancelled' => 'Opération Annulée',
 	'Portal:Title' => 'Portail utilisateur iTop',
 	'Portal:Refresh' => 'Rafraîchir',

+ 60 - 9
navigator/iTop/Navigator.as

@@ -8,6 +8,8 @@
 	import fl.controls.Slider; 
 	import fl.events.SliderEvent; 
 	import fl.controls.Label; 
+	// For callbacks from Javascript
+	import flash.external.ExternalInterface;
 
 	// The main canvas
 	public class Navigator extends MovieClip
@@ -26,6 +28,7 @@
 		protected var m_sRelation:String;
 		protected var m_sObjClass:String;
 		protected var m_sObjId:String;
+		protected var m_sExclude:String;
 		
 		// Constants
 		protected var m_RADIUS = 150;
@@ -43,14 +46,60 @@
 		{
 			m_aLinks = new Array();
 			m_aNodes = new Array();
+			m_sExclude = '';
 			m_fZoom = 1;
 			initParameters();
-			doLoadData();
+			var success = true;
+			if (ExternalInterface.available) 
+			{
+				//Security.allowDomain(loader.contentLoaderInfo.url);
+				//the addCallback registers a function to be called from javascript, and this is what you wanted to do:
+				try
+				{
+					ExternalInterface.addCallback("Filter", DoFilter);
+				}
+				catch(err)
+				{
+					m_sTitle.text = 'E: '+err.description;
+					success = false
+				}
+			}
+			
+			if (success)
+			{
+				//m_sTitle.text = 'Ok...';
+				doLoadData();
+			}
+			else
+			{
+				m_sTitle.text = 'Failed to addCallback';
+			}
+			
 			addEventListener(Event.ENTER_FRAME, initGraphics);
 			//Stop scaling the flash content
 			stage.scaleMode = StageScaleMode.NO_SCALE;
 		}
 		
+		function Reset()
+		{
+			m_aLinks = new Array();
+			for (var i:String in m_aNodes)
+			{
+				m_oCanvas.removeChild(m_aNodes[i]);
+			}
+			m_aNodes = new Array();
+			removeEventListener(Event.ENTER_FRAME, drawLines);
+			stage.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDown)  
+			stage.removeEventListener(MouseEvent.MOUSE_UP, mouseReleased);
+		}
+		
+		function DoFilter(sExcludeList:String):void
+		{
+			//do something
+			m_sExclude = sExcludeList;
+			doLoadData();
+		}
+
 		protected function initParameters():void
 		{
 			
@@ -70,6 +119,8 @@
 			m_oCanvas.scaleY = m_fZoom;
 			// Handle listeners...
 			removeEventListener(Event.ENTER_FRAME,initGraphics);
+			m_oZoomSlider.value = 100;
+			m_oZoomSlider.addEventListener(SliderEvent.CHANGE, onZoomChange);
 		}
 		function mouseDown(event:MouseEvent):void 
 		{ 
@@ -99,19 +150,22 @@
 			m_oCanvas.scaleX = m_fZoom;
 			m_oCanvas.scaleY = m_fZoom;
 		}
-		function GetZommLevel()
+		function GetZoomLevel()
 		{
 			return m_fZoom;
 		}
 		
 		function doLoadData()
 		{
+			m_sTitle.text = "Loading...";
+			m_oPreloader.visible = true;
+			m_oZoomSlider.enabled = true;
 			var sSeparator:String = '?';
 			if (m_sDataUrl.indexOf(sSeparator) != -1)
 			{
 				sSeparator = '&';
 			}
-			var myString:String = m_sDataUrl+sSeparator+'relation='+m_sRelation+'&class='+m_sObjClass+'&id='+m_sObjId;
+			var myString:String = m_sDataUrl+sSeparator+'relation='+m_sRelation+'&class='+m_sObjClass+'&id='+m_sObjId+'&exclude='+m_sExclude;
 			trace("Requesting:"+myString);
 			var myXMLURL:URLRequest = new URLRequest(myString);
 			m_oLoader = new URLLoader();
@@ -125,6 +179,7 @@
 		{
 			try
 			{
+				Reset();
 				var myXML:XML = XML(m_oLoader.data);
 				//trace("Data loaded." + myXML);
 				//trace("===========================");
@@ -132,8 +187,6 @@
 				m_sTitle.text = decodeEntities(myXML.attribute("title").toString());
 				m_oZoomSlider.enabled = true;
 				addEventListener(Event.ENTER_FRAME, drawLines);
-				m_oZoomSlider.value = 100;
-				m_oZoomSlider.addEventListener(SliderEvent.CHANGE, onZoomChange);
 				stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown)  
 				stage.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
 				//trace('======= Initial Posistions =========');
@@ -155,8 +208,7 @@
 			{
 				if (m_oPreloader != null)
 				{
-					removeChild(m_oPreloader);
-					m_oPreloader = null;
+					m_oPreloader.visible = false;
 				}
 			}
 		}
@@ -165,8 +217,7 @@
 		{
 				if (m_oPreloader != null)
 				{
-					removeChild(m_oPreloader);
-					m_oPreloader = null;
+					m_oPreloader.visible = false;
 				}
 				m_sTitle.text = "I/O Error: unable to load the graph data ("+event+")";
 		}

二进制
navigator/navigator.fla


二进制
navigator/navigator.swf


+ 81 - 5
pages/UI.php

@@ -2029,25 +2029,101 @@ EOF
 		$oP->AddTabContainer('Navigator');
 		$oP->SetCurrentTabContainer('Navigator');
 		$oP->SetCurrentTab(Dict::S('UI:RelationshipGraph'));
+
+		$oP->add("<div id=\"ds_flash\" class=\"SearchDrawer\">\n");
+		$oP->add_ready_script(
+<<<EOF
+	$("#dh_flash").click( function() {
+		$("#ds_flash").slideToggle('normal', function() { $("#ds_flash").parent().resize(); } );
+		$("#dh_flash").toggleClass('open');
+	});
+EOF
+		);
+ 		$aElements = MetaModel::GetSubclasses('FunctionalCI');
+		$aResults = array();
+		$aSortedElements = array();
+		$oObj = MetaModel::GetObject($sClass, $id);
+		$oObj->GetRelatedObjects($sRelation, 20 /* iMaxDepth */, $aResults);
+		foreach($aResults as $sClassIdx => $aObjects)
+		{
+			foreach($aObjects as $oCurrObj)
+			{
+				$sSubClass = get_class($oCurrObj);
+				$aSortedElements[$sSubClass] = MetaModel::GetName($sSubClass);
+			}
+		}
+		
+		asort($aSortedElements);
+		$idx = 0;
+		foreach($aSortedElements as $sSubClass => $sClassName)
+		{
+			$oP->add("<span style=\"padding-right:2em; white-space:nowrap;\"><input type=\"checkbox\" id=\"exclude_$idx\" name=\"excluded[]\" value=\"$sSubClass\" checked onChange=\"DoReload()\"><label for=\"exclude_$idx\">&nbsp;".MetaModel::GetClassIcon($sSubClass)."&nbsp;$sClassName</label></span> ");
+			$idx++;	
+		}
+ 		$oP->add("</div>\n");
+ 		$oP->add("<div class=\"HRDrawer\"></div>\n");
+ 		$oP->add("<div id=\"dh_flash\" class=\"DrawerHandle\">".Dict::S('UI:ElementsDisplayed')."</div>\n");
+		
 		$width = 1000;
 		$height = 700;
 		$sDrillUrl = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&'.$oAppContext->GetForLink();
 		$sParams = "pWidth=$width&pHeight=$height&drillUrl=".urlencode($sDrillUrl)."&displayController=false&xmlUrl=".urlencode("./xml.navigator.php")."&obj_class=$sClass&obj_id=$id&relation=$sRelation";
 		
-		$oP->add("<div style=\"z-index:1;background:white\"><object style=\"z-index:2\" classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0\" width=\"$width\" height=\"$height\" id=\"navigator\" align=\"middle\">
-		<param name=\"allowScriptAccess\" value=\"sameDomain\" />
+		$oP->add("<div style=\"z-index:1;background:white;width:100%;height:{$height}px\"><object style=\"z-index:2\" classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0\" width=\"100%\" height=\"$height\" id=\"navigator\" align=\"middle\">
+		<param name=\"allowScriptAccess\" value=\"always\" />
 		<param name=\"allowFullScreen\" value=\"false\" />
 		<param name=\"FlashVars\" value=\"$sParams\" />
 		<param name=\"wmode\" value=\"transparent\"> 
 		<param name=\"movie\" value=\"../navigator/navigator.swf\" /><param name=\"quality\" value=\"high\" /><param name=\"bgcolor\" value=\"#ffffff\" />
-		<embed src=\"../navigator/navigator.swf\" wmode=\"transparent\" flashVars=\"$sParams\" quality=\"high\" bgcolor=\"#ffffff\" width=\"$width\" height=\"$height\" name=\"navigator\" align=\"middle\" allowScriptAccess=\"sameDomain\" allowFullScreen=\"false\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.adobe.com/go/getflashplayer\" />
+		<embed src=\"../navigator/navigator.swf\" wmode=\"transparent\" flashVars=\"$sParams\" quality=\"high\" bgcolor=\"#ffffff\" width=\"100%\" height=\"$height\" name=\"navigator\" align=\"middle\" swliveconnect=\"true\" allowScriptAccess=\"always\" allowFullScreen=\"false\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.adobe.com/go/getflashplayer\" />
 		</object></div>\n");
 		$oP->SetCurrentTab(Dict::S('UI:RelationshipList'));
 		$oP->add("<div id=\"impacted_objects\" style=\"width:100%;background-color:#fff;padding:10px;\"><p style=\"height:150px;\">&nbsp;</p></div>");
+		$oP->add_script(
+<<<EOF
+function getFlashMovieObject(movieName)
+{
+  if (window.document[movieName]) 
+  {
+      return window.document[movieName];
+  }
+  if (navigator.appName.indexOf("Microsoft Internet")==-1)
+  {
+    if (document.embeds && document.embeds[movieName])
+      return document.embeds[movieName]; 
+  }
+  else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
+  {
+    return document.getElementById(movieName);
+  }
+}
+
+	function DoReload()
+	{
+		var oMovie = getFlashMovieObject('navigator');
+		try
+		{
+			var aExcluded = [];
+			$('input[name^=excluded]').each( function() {
+				if (!$(this).attr('checked'))
+				{
+					aExcluded.push($(this).val());
+				}
+			} );
+			oMovie.Filter(aExcluded.join(','));
+		//oMovie.SetVariable("/:message", "foo");
+		}
+		catch(err)
+		{
+			alert(err);
+		}
+	}
+EOF
+);
 		$oP->add_ready_script(
 <<<EOF
 	var ajax_request = null;
-	
+
 	function UpdateImpactedObjects(sClass, iId, sRelation)
 	{
 		var class_name = sClass; //$('select[name=class_name]').val();
@@ -2185,4 +2261,4 @@ catch(Exception $e)
 		IssueLog::Error($e->getMessage());
 	}
 }
-?>
+?>

+ 30 - 18
pages/xml.navigator.php

@@ -59,9 +59,10 @@ function AddNodeDetails(&$oNode, $oObj)
  * @param DBObject $oObj The current object
  * @param string $sRelation The name of the relation to search with
  */
-function GetRelatedObjectsAsXml(DBObject $oObj, $sRelationName, &$oLinks, &$oXmlDoc, &$oXmlNode, $iDepth = 0)
+function GetRelatedObjectsAsXml(DBObject $oObj, $sRelationName, &$oLinks, &$oXmlDoc, &$oXmlNode, $iDepth = 0, $aExcludedClasses)
 {
 	$aResults = array();
+	$bAddLinks = false;
 	$oObj->GetRelatedObjects($sRelationName, 1 /* iMaxDepth */, $aResults);
 	if ($iDepth > MAX_RECURSION_DEPTH) return;
 	
@@ -71,25 +72,33 @@ function GetRelatedObjectsAsXml(DBObject $oObj, $sRelationName, &$oLinks, &$oXml
 		{
 			if (is_object($oTargetObj))
 			{
-				$oLinkingNode =   $oXmlDoc->CreateElement('link');
-				$oLinkingNode->SetAttribute('relation', $sRelationName);
-				$oLinkingNode->SetAttribute('arrow', 1); // Such relations have a direction, display an arrow
-				$oLinkedNode = $oXmlDoc->CreateElement('node');
-				$oLinkedNode->SetAttribute('id', $oTargetObj->GetKey());
-				$oLinkedNode->SetAttribute('obj_class', get_class($oTargetObj));
-				$oLinkedNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oTargetObj))));
-				$oLinkedNode->SetAttribute('name', htmlspecialchars($oTargetObj->GetRawName())); // htmlentities is too much for XML
-				$oLinkedNode->SetAttribute('icon', BuildIconPath($oTargetObj->GetIcon(false /* No IMG tag */)));
-				AddNodeDetails($oLinkedNode, $oTargetObj);
-				$oSubLinks = $oXmlDoc->CreateElement('links');
-				// Recurse
-				GetRelatedObjectsAsXml($oTargetObj, $sRelationName, $oSubLinks, $oXmlDoc, $oLinkedNode, $iDepth++);
-				$oLinkingNode->AppendChild($oLinkedNode);
-				$oLinks->AppendChild($oLinkingNode);
+				if (in_array(get_class($oTargetObj), $aExcludedClasses))
+				{
+					GetRelatedObjectsAsXml($oTargetObj, $sRelationName, $oLinks, $oXmlDoc, $oXmlNode, $iDepth++, $aExcludedClasses);
+				}
+				else
+				{
+					$oLinkingNode =   $oXmlDoc->CreateElement('link');
+					$oLinkingNode->SetAttribute('relation', $sRelationName);
+					$oLinkingNode->SetAttribute('arrow', 1); // Such relations have a direction, display an arrow
+					$oLinkedNode = $oXmlDoc->CreateElement('node');
+					$oLinkedNode->SetAttribute('id', $oTargetObj->GetKey());
+					$oLinkedNode->SetAttribute('obj_class', get_class($oTargetObj));
+					$oLinkedNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oTargetObj))));
+					$oLinkedNode->SetAttribute('name', htmlspecialchars($oTargetObj->GetRawName())); // htmlentities is too much for XML
+					$oLinkedNode->SetAttribute('icon', BuildIconPath($oTargetObj->GetIcon(false /* No IMG tag */)));
+					AddNodeDetails($oLinkedNode, $oTargetObj);
+					$oSubLinks = $oXmlDoc->CreateElement('links');
+					// Recurse
+					GetRelatedObjectsAsXml($oTargetObj, $sRelationName, $oSubLinks, $oXmlDoc, $oLinkedNode, $iDepth++, $aExcludedClasses);
+					$oLinkingNode->AppendChild($oLinkedNode);
+					$oLinks->AppendChild($oLinkingNode);
+					$bAddLinks = true;
+				}
 			}
 		}
 	}
-	if (count($aResults) > 0)
+	if ($bAddLinks)
 	{
 		$oXmlNode->AppendChild($oLinks);
 	}
@@ -117,6 +126,9 @@ $id = utils::ReadParam('id', 1);
 $sRelation = utils::ReadParam('relation', 'impacts');
 $aValidRelations = MetaModel::EnumRelations();
 $sFormat = utils::ReadParam('format', 'xml');
+$sExcludedClasses = utils::ReadParam('exclude', '', false, 'raw_data');
+$aExcludedClasses = explode(',', $sExcludedClasses);
+
 
 if (!in_array($sRelation, $aValidRelations))
 {
@@ -167,7 +179,7 @@ try
 		
 			$oXmlRoot->SetAttribute('position', 'left');
 			$oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation).' '. htmlspecialchars($oObj->GetRawName()));
-			GetRelatedObjectsAsXml($oObj, $sRelation, $oLinks, $oXmlDoc, $oXmlNode);
+			GetRelatedObjectsAsXml($oObj, $sRelation, $oLinks, $oXmlDoc, $oXmlNode, 0, $aExcludedClasses);
 			
 			$oXmlRoot->AppendChild($oXmlNode);
 			$oXmlDoc->AppendChild($oXmlRoot);