Browse Source

- new implementation of the default DisplayDetails of an object: the tabs are now at the top and the ZList supports multiple columns and tabs for the attributes.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@489 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 15 năm trước cách đây
mục cha
commit
729f7d88f5

+ 121 - 48
application/cmdbabstract.class.inc.php

@@ -24,6 +24,8 @@
  * @license     http://www.opensource.org/licenses/gpl-3.0.html LGPL
  */
 
+define('OBJECT_PROPERTIES_TAB', 'ObjectProperties');
+
 require_once('../core/cmdbobject.class.inc.php');
 require_once('../application/utils.inc.php');
 require_once('../application/applicationcontext.class.inc.php');
@@ -101,25 +103,25 @@ abstract class cmdbAbstractObject extends CMDBObject
 	{
 		// Standard Header with name, actions menu and history block
 		//
-		$oPage->add("<div class=\"page_header\">\n");
 
 		// action menu
 		$oSingletonFilter = new DBObjectSearch(get_class($this));
 		$oSingletonFilter->AddCondition('id', array($this->GetKey()));
 		$oBlock = new MenuBlock($oSingletonFilter, 'popup', false);
 		$oBlock->Display($oPage, -1);
+		$oPage->add("<div class=\"page_header\"><h1><img src=\"".$this->GetIcon()."\" style=\"margin-right:10px;margin-top: -16px;vertical-align:middle;\">\n");
+		$oPage->add(MetaModel::GetName(get_class($this)).": <span class=\"hilite\">".$this->GetDisplayName()."</span></h1>\n");
+		$oPage->add("</div>\n");
+	}
 
-		$oPage->add("<h1>".MetaModel::GetName(get_class($this)).": <span class=\"hilite\">".$this->GetDisplayName()."</span></h1>\n");
-
-		// history block (with toggle)
+	function DisplayBareHistory(WebPage $oPage)
+	{
+		// history block (with as a tab)
 		$oHistoryFilter = new DBObjectSearch('CMDBChangeOp');
 		$oHistoryFilter->AddCondition('objkey', $this->GetKey());
 		$oHistoryFilter->AddCondition('objclass', get_class($this));
-		$oBlock = new HistoryBlock($oHistoryFilter, 'toggle', false);
+		$oBlock = new HistoryBlock($oHistoryFilter, 'tab', false);
 		$oBlock->Display($oPage, -1);
-
-		$oPage->add("</div>\n");
-		$oPage->add("<img src=\"".$this->GetIcon()."\" style=\"margin-top:-30px; margin-right:10px; float:right\">\n");
 	}
 
 	function DisplayBareProperties(WebPage $oPage)
@@ -130,8 +132,8 @@ abstract class cmdbAbstractObject extends CMDBObject
 	function DisplayBareRelations(WebPage $oPage)
 	{
 		// Related objects
-		$oPage->AddTabContainer('Related Objects');
-		$oPage->SetCurrentTabContainer('Related Objects');
+		//$oPage->AddTabContainer('Related Objects');
+		//$oPage->SetCurrentTabContainer('Related Objects');
 		foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
 		{
 			if ($oAttDef->IsLinkset())
@@ -189,52 +191,42 @@ abstract class cmdbAbstractObject extends CMDBObject
 		$aDetailsList = MetaModel::GetZListItems($sClass, 'details');
 		$aFullList = MetaModel::ListAttributeDefs($sClass);
 		$aList = $aDetailsList;
+		$aDetailsStruct = self::ProcessZlist($aDetailsList, array('UI:PropertiesTab' => array()), 'UI:PropertiesTab', 'col1', '');
 		// Compute the list of properties to display, first the attributes in the 'details' list, then 
 		// all the remaining attributes that are not external fields
-		foreach($aFullList as $sAttCode => $void)
-		{
-			$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
-			if (!in_array($sAttCode, $aDetailsList) && (!$oAttDef->IsExternalField()))
-			{
-				$aList[] = $sAttCode;
-			}
-		}
-
-		foreach($aList as $sAttCode)
-		{
-			$iFlags = $this->GetAttributeFlags($sAttCode);
-			$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
-			if ( (!$oAttDef->IsLinkSet()) && (($iFlags & OPT_ATT_HIDDEN) == 0) )
-			{
-				// The field is visible in the current state of the object
-				if ($sStateAttCode == $sAttCode)
-				{
-					// Special display for the 'state' attribute itself
-					$sDisplayValue = $this->GetStateLabel();
-				}
-				else
-				{
-					$sDisplayValue = $this->GetAsHTML($sAttCode);
-				}
-				$aDetails[] = array('label' => '<span title="'.MetaModel::GetDescription($sClass, $sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>', 'value' => $sDisplayValue);
-			}
-		}
-		$sHtml .= $oPage->GetDetails($aDetails);
-		// Documents displayed inline (when possible: images, html...)
-		foreach($aList as $sAttCode)
+		$sHtml = '';
+		$aDetails = array();
+		foreach($aDetailsStruct as $sTab => $aCols )
 		{
-			$oAttDef = Metamodel::GetAttributeDef($sClass, $sAttCode);
-			if ( $oAttDef->GetEditClass() == 'Document')
+			$aDetails[$sTab] = array();
+			ksort($aCols);
+			$oPage->SetCurrentTab(Dict::S($sTab));
+			$oPage->add('<table style="vertical-align:top"><tr>');
+			foreach($aCols as $sColIndex => $aFieldsets)
 			{
-				$oDoc = $this->Get($sAttCode);
-				if (is_object($oDoc) && !$oDoc->IsEmpty())
+				$aDetails[$sTab][$sColIndex] = array();
+				foreach($aFieldsets as $sFieldsetName => $aFields)
 				{
-					$sHtml .= "<p>".Dict::Format('UI:Document:OpenInNewWindow:Download', $oDoc->GetDisplayLink($sClass, $this->GetKey(), $sAttCode), $oDoc->GetDownloadLink($sClass, $this->GetKey(), $sAttCode))."</p>\n";
-					$sHtml .= "<div>".$oDoc->GetDisplayInline($sClass, $this->GetKey(), $sAttCode)."</div>\n";
+					//if ($sFieldsetName == '')
+					//{
+						foreach($aFields as $sAttCode)
+						{
+							$val = $this->GetFieldAsHtml($sClass, $sAttCode, $sStateAttCode);
+							if ($val != null)
+							{
+								// The field is visible, add it to the current column
+								$aDetails[$sTab][$sColIndex][] = $val;
+							}				
+						}
+					//}
 				}
+				$oPage->add('<td style="vertical-align:top">');
+				$oPage->Details($aDetails[$sTab][$sColIndex]);
+				$oPage->add('</td>');
 			}
+			$oPage->add('</tr></table>');
 		}
-		return $sHtml;		
+		return $sHtml;
 	}
 
 	
@@ -254,8 +246,13 @@ abstract class cmdbAbstractObject extends CMDBObject
 			// Object's details
 			// template not found display the object using the *old style*
 			$this->DisplayBareHeader($oPage);
+			$oPage->AddTabContainer(OBJECT_PROPERTIES_TAB);
+			$oPage->SetCurrentTabContainer(OBJECT_PROPERTIES_TAB);
+			$oPage->SetCurrentTab(Dict::S('UI:PropertiesTab'));
 			$this->DisplayBareProperties($oPage);
 			$this->DisplayBareRelations($oPage);
+			$oPage->SetCurrentTab(Dict::S('UI:HistoryTab'));
+			$this->DisplayBareHistory($oPage);
 		}
 	}
 	
@@ -1309,5 +1306,81 @@ EOF
 		}
 		return $sCSSClasses;
 	}
+
+	protected static function ProcessZlist($aList, $aDetails, $sCurrentTab, $sCurrentCol, $sCurrentSet)
+	{
+		//echo "<pre>ZList: ";
+		//print_r($aList);
+		//echo "</pre>\n";
+		foreach($aList as $sKey => $value)
+		{
+			if (is_array($value))
+			{
+				if (preg_match('/^(.*):(.*)$/U', $sKey, $aMatches))
+				{
+					$sCode = $aMatches[1];
+					$sName = $aMatches[2];
+					switch($sCode)
+					{
+						case 'tab':
+						//echo "<p>Found a tab:  $sName ($sKey)</p>\n";
+						if(!isset($aDetails[$sName]))
+						{
+							$aDetails[$sName] = array('col1' => array('' => array()));
+						}
+						$aDetails = self::ProcessZlist($value, $aDetails, $sName, 'col1', '');
+						break;
+						
+						case 'fieldset':
+						//echo "<p>Found a fieldset: $sName ($sKey)</p>\n";
+						if(!isset($aDetailsStruct[$sCurrentTab][$sCurrentCol][$sName]))
+						{
+							$aDetails[$sCurrentTab][$sCurrentCol][$sName] = array();
+						}
+						$aDetails = self::ProcessZlist($value, $aDetails, $sCurrentTab, $sCurrentCol, $sName);
+						break;
+
+						default:
+						case 'col':
+						//echo "<p>Found a column: $sName ($sKey)</p>\n";
+						if(!isset($aDetails[$sCurrentTab][$sName]))
+						{
+							$aDetails[$sCurrentTab][$sName] = array('' => array());
+						}
+						$aDetails = self::ProcessZlist($value, $aDetails, $sCurrentTab, $sName, '');
+						break;
+					}
+				}
+			}
+			else
+			{
+				//echo "<p>Scalar value: $value, in [$sCurrentTab][$sCurrentCol][$sCurrentSet][]</p>\n";
+				$aDetails[$sCurrentTab][$sCurrentCol][$sCurrentSet][] = $value;
+			}
+		}
+		return $aDetails;
+	}
+	protected function GetFieldAsHtml($sClass, $sAttCode, $sStateAttCode)
+	{
+		$retVal = null;
+		$iFlags = $this->GetAttributeFlags($sAttCode);
+		$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
+		if ( (!$oAttDef->IsLinkSet()) && (($iFlags & OPT_ATT_HIDDEN) == 0) )
+		{
+			// The field is visible in the current state of the object
+			if ($sStateAttCode == $sAttCode)
+			{
+				// Special display for the 'state' attribute itself
+				$sDisplayValue = $this->GetStateLabel();
+			}
+			else
+			{
+				$sDisplayValue = $this->GetAsHTML($sAttCode);
+			}
+			$retVal = array('label' => '<span title="'.MetaModel::GetDescription($sClass, $sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>', 'value' => $sDisplayValue);
+		}
+		return $retVal;
+	}
+	
 }
 ?>

+ 6 - 6
application/displayblock.class.inc.php

@@ -588,7 +588,7 @@ class DisplayBlock
 			$sHtml .= "<div id=\"my_chart_{$iChartCounter}\">If the chart does not display, <a href=\"http://get.adobe.com/flash/\" target=\"_blank\">install Flash</a></div>\n";
 			$oPage->add_script("function ofc_resize(left, width, top, height) { /* do nothing special */ }");
 			$oPage->add_ready_script("swfobject.embedSWF(\"../images/open-flash-chart.swf\", \"my_chart_{$iChartCounter}\", \"100%\", \"300\",\"9.0.0\", \"expressInstall.swf\",
-			{\"data-file\":\"".urlencode("../pages/ajax.render.php?operation=open_flash_chart&params[group_by]=$sGroupBy&params[chart_type]=$sChartType&params[chart_title]=$sTitle&encoding=oql&filter=".urlencode($sFilter))."\"});\n");
+			{\"data-file\":\"".urlencode("../pages/ajax.render.php?operation=open_flash_chart&params[group_by]=$sGroupBy&params[chart_type]=$sChartType&params[chart_title]=$sTitle&encoding=oql&filter=".urlencode($sFilter))."\"}, {wmode: 'transparent'} );\n");
 			$iChartCounter++;
 			break;
 			
@@ -718,7 +718,7 @@ class HistoryBlock extends DisplayBlock
 		$sHtml .= "<!-- filter: ".($this->m_oFilter->ToOQL())."-->\n";
 		switch($this->m_sStyle)
 		{
-			case 'toggle':
+			default:
 			// First the latest change that the user is allowed to see
 			do
 			{
@@ -734,7 +734,7 @@ class HistoryBlock extends DisplayBlock
 				$oChange = $oContext->GetObject('CMDBChange', $oLatestChangeOp->Get('change'));
 				$sUserInfo = $oChange->GetAsHTML('userinfo');
 				$oSet->Rewind(); // Reset the pointer to the beginning of the set
-				$sHtml .= $oPage->GetStartCollapsibleSection(Dict::Format('UI:History:LastModified_On_By', $sDate, $sUserInfo));
+				//$sHtml .= $oPage->GetStartCollapsibleSection(Dict::Format('UI:History:LastModified_On_By', $sDate, $sUserInfo));
 				//$sHtml .= cmdbAbstractObject::GetDisplaySet($oPage, $oSet);
 				$aChanges = array();
 				while($oChangeOp = $oSet->Fetch())
@@ -763,12 +763,12 @@ class HistoryBlock extends DisplayBlock
 					$aValues[] = array('date' => $aChange['date'], 'userinfo' => $aChange['userinfo'], 'log' => "<ul><li>".implode('</li><li>', $aChange['log'])."</li></ul>");
 				}
 				$sHtml .= $oPage->GetTable($aAttribs, $aValues);		
-				$sHtml .= $oPage->GetEndCollapsibleSection();
+				//$sHtml .= $oPage->GetEndCollapsibleSection();
 			}
 			break;
 						
-			default:
-			$sHtml .= parent::GetRenderContent($oPage, $aExtraParams);
+			///default:
+			//$sHtml .= parent::GetRenderContent($oPage, $aExtraParams);
 		}
 		return $sHtml;
 	}

+ 10 - 1
application/menunode.class.inc.php

@@ -387,10 +387,19 @@ class OQLMenuNode extends MenuNode
 	
 	public function RenderContent(WebPage $oPage, $aExtraParams = array())
 	{
+		try
+		{
+			$oSearch = DBObjectSearch::FromOQL($this->sOQL);
+			$sIcon = MetaModel::GetClassIcon($oSearch->GetClass());
+		}
+		catch(Exception $e)
+		{
+			$sIcon = '';
+		}
 		// The standard template used for all such pages: a (closed) search form at the top and a list of results at the bottom
 		$sTemplate = <<<EOF
 <itopblock BlockClass="DisplayBlock" type="search" asynchronous="false" encoding="text/oql">$this->sOQL</itopblock>
-<p class="page-header"><itopstring>$this->sPageTitle</itopstring></p>
+<p class="page-header"><img src="$sIcon"><itopstring>$this->sPageTitle</itopstring></p>
 <itopblock BlockClass="DisplayBlock" type="list" asynchronous="false" encoding="text/oql">$this->sOQL</itopblock>
 EOF;
 		$oTemplate = new DisplayTemplate($sTemplate);

+ 1 - 0
css/light-grey.css

@@ -407,6 +407,7 @@ div.itop_popup > ul > li {
 	position: absolute;
 	display: none;
 	border-top: 1px solid white;
+	z-index: 999;
 }
 
 .itop_popup li ul li,  #logOffBtn li ul li {

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

@@ -395,6 +395,7 @@ Dict::Add('EN US', 'English', 'English', array(
 	'UI:CountOfObjects' => '%1$d objects matching the criteria.',
 	'UI:NoObject_Class_ToDisplay' => 'No %1$s to display',
 	'UI:History:LastModified_On_By' => 'Last modified on %1$s by %2$s.',
+	'UI:HistoryTab' => 'History',
 	'UI:History:Date' => 'Date',
 	'UI:History:Date+' => 'Date of the change',
 	'UI:History:User' => 'User',
@@ -878,6 +879,7 @@ When associated with a trigger, each action is given an "order" number, specifyi
 
 	'UI:iTopVersion:Short' => 'iTop version %1$s',
 	'UI:iTopVersion:Long' => 'iTop version %1$s-%2$s built on %3$s',
+	'UI:PropertiesTab' => 'Properties',
 ));