Browse Source

Search forms enhancement: when a search criteria is an external (foreign) key, use an autocomplete instead of of drop-down list, when the number of different values is too big, as in other forms.

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

+ 17 - 0
application/cmdbabstract.class.inc.php

@@ -106,7 +106,11 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
 			{
 				// Assumption: $aData['datasource'] will not be null because the data source id is always set...
 				$sApplicationURL = $aData['datasource']->GetApplicationUrl($this, $aData['replica']);
+				$sLink = '';
+				if (!empty($sApplicationURL))
+				{
 				$sLink = "<a href=\"$sApplicationURL\" target=\"_blank\">".$aData['datasource']->GetName()."</a>";
+				}
 				if ($aData['replica']->Get('status_dest_creator') == 1)
 				{
 					$sTip .= "<p>The object was <b>created</b> by the external data source $sLink</p>";
@@ -1062,6 +1066,18 @@ EOF
 			$aAllowedValues = MetaModel::GetAllowedValues_flt($sClassName, $sFilterCode, $aExtraParams);
 			if ($aAllowedValues != null)
 			{
+				$oAttDef = MetaModel::GetAttributeDef($sClassName, $sFilterCode);
+
+				if ($oAttDef->IsExternalKey())
+				{
+					$iFieldSize = $oAttDef->GetMaxSize();
+					$iMaxComboLength = $oAttDef->GetMaximumComboLength();
+					$oWidget = new UIExtKeyWidget($sFilterCode, $sClassName, $oAttDef->GetLabel(), $aAllowedValues, $sFilterValue, 'search_'.$sFilterCode, false, '', '', '');
+					$sHtml .= "<label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label>&nbsp;";
+					$sHtml .= $oWidget->Display($oPage, $aExtraParams, true /* bSearchMode */);
+				}
+				else
+				{
 				//Enum field or external key, display a combo
 				$sValue = "<select name=\"$sFilterCode\">\n";
 				$sValue .= "<option value=\"\">".Dict::S('UI:SearchValue:Any')."</option>\n";
@@ -1079,6 +1095,7 @@ EOF
 				}
 				$sValue .= "</select>\n";
 				$sHtml .= "<label>".MetaModel::GetFilterLabel($sClassName, $sFilterCode).":</label>&nbsp;$sValue\n";
+				}				
 				unset($aExtraParams[$sFilterCode]);
 			}
 			else

+ 27 - 8
application/ui.extkeywidget.class.inc.php

@@ -92,12 +92,24 @@ class UIExtKeyWidget
 	 * @param Hash $aArgs Extra context arguments
 	 * @return string The HTML fragment to be inserted into the page
 	 */
-	public function Display(WebPage $oPage, $aArgs = array())
+	public function Display(WebPage $oPage, $aArgs = array(), $bSearchMode = false)
 	{
-		$bCreate = (!MetaModel::IsAbstract($this->sTargetClass)) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $this->oAttDef->AllowTargetCreation());
+		$oPage->add_linked_script('../js/extkeywidget.js');
+		$oPage->add_linked_script('../js/forms-json-utils.js');
+		
+		$bCreate = (!$bSearchMode) && (!MetaModel::IsAbstract($this->sTargetClass)) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $this->oAttDef->AllowTargetCreation());
 		$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
+		$sAttrFieldPrefix = ($bSearchMode) ? '' : 'attr_';
 
 		$sHTMLValue = "<span style=\"white-space:nowrap\">"; // no wrap
+		if($bSearchMode)
+		{
+			$sWizHelper = 'null';
+		} 
+		else
+		{
+			$sWizHelper = 'oWizardHelper'.$this->sFormPrefix;
+		}
 		if (count($this->aAllowedValues) < $this->oAttDef->GetMaximumComboLength())
 		{
 			// Few choices, use a normal 'select'
@@ -106,8 +118,15 @@ class UIExtKeyWidget
 			$sHelpText = $this->oAttDef->GetHelpOnEdition();
 
 			// In case there are no valid values, the select will be empty, thus blocking the user from validating the form
-			$sHTMLValue = "<select title=\"$sHelpText\" name=\"attr_{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" id=\"$this->iId\">\n";
-			$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
+			$sHTMLValue = "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" id=\"$this->iId\">\n";
+			if ($bSearchMode)
+			{
+				$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SearchValue:Any')."</option>\n";			
+			}
+			else
+			{
+				$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
+			}
 			foreach($this->aAllowedValues as $key => $display_value)
 			{
 				if ((count($this->aAllowedValues) == 1) && ($this->bMandatory == 'true') )
@@ -122,9 +141,9 @@ class UIExtKeyWidget
 				$sHTMLValue .= "<option value=\"$key\"$sSelected>$display_value</option>\n";
 			}
 			$sHTMLValue .= "</select>\n";
-		$oPage->add_ready_script(
+			$oPage->add_ready_script(
 <<<EOF
-		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, oWizardHelper{$this->sFormPrefix});
+		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, $sWizHelper);
 		oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
 
 EOF
@@ -152,12 +171,12 @@ EOF
 			$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.Search();\"><img style=\"border:0;vertical-align:middle;\" src=\"../images/mini_search.gif\" /></a>&nbsp;";
 	
 			// another hidden input to store & pass the object's Id
-			$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"attr_{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" value=\"$this->value\" />\n";
+			$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$this->sFieldPrefix}{$this->sAttCode}{$this->sNameSuffix}\" value=\"$this->value\" />\n";
 	
 			// Scripts to start the autocomplete and bind some events to it
 		$oPage->add_ready_script(
 <<<EOF
-		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, oWizardHelper{$this->sFormPrefix});
+		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, $sWizHelper);
 		oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
 		$('#label_$this->iId').autocomplete('./ajax.render.php', { scroll:true, minChars:{$iMinChars}, formatItem:formatItem, autoFill:false, matchContains:true, keyHolder:'#{$this->iId}', extraParams:{operation:'autocomplete', sclass:'{$this->sClass}',attCode:'{$this->sAttCode}'}});
 		$('#label_$this->iId').blur(function() { $(this).search(); } );

+ 2 - 2
core/config.class.inc.php

@@ -125,7 +125,7 @@ class Config
 			'show_in_conf_sample' => true,
 		),
 		'max_combo_length' => array(
-			'type' => 'int',
+			'type' => 'integer',
 			'description' => 'The maximum number of elements in a drop-down list. If more then an autocomplete will be used',
 			'default' => 50,
 			'value' => 50,
@@ -133,7 +133,7 @@ class Config
 			'show_in_conf_sample' => false,
 		),
 		'min_autocomplete_chars' => array(
-			'type' => 'int',
+			'type' => 'integer',
 			'description' => 'The minimum number of characters to type in order to trigger the "autocomplete" behavior',
 			'default' => 3,
 			'value' => 3,

+ 1 - 1
css/light-grey.css

@@ -160,7 +160,7 @@ p a:hover, td a:hover {
 	background: url(../images/mini-arrow-orange.gif) no-repeat left;
 }
 
-td a.no-arrow, td a.no-arrow:visited {
+td a.no-arrow, td a.no-arrow:visited, .SearchDrawer a.no-arrow, .SearchDrawer a.no-arrow:visited {
 	text-decoration:none;
 	color:#000000;
 	padding-left:0px;

+ 10 - 2
js/extkeywidget.js

@@ -97,8 +97,16 @@ function ExtKeyWidget(id, sClass, sAttCode, sSuffix, bSelectMode, oWizHelper)
 			}
 		);
 		
-		me.oWizardHelper.UpdateWizard();
-		theMap['json'] = me.oWizardHelper.ToJSON();
+		if (me.oWizardHelper == null)
+		{
+			theMap['json'] = '';
+		}
+		else
+		{
+			// Not inside a "search form", updating a real object
+			me.oWizardHelper.UpdateWizard();
+			theMap['json'] = me.oWizardHelper.ToJSON();
+		}
 		
 		theMap['sRemoteClass'] = theMap['class'];  // swap 'class' (defined in the form) and 'remoteClass'
 		theMap['class'] = me.sClass;

+ 11 - 1
pages/ajax.render.php

@@ -79,10 +79,20 @@ try
 		$iInputId = utils::ReadParam('iInputId', '');
 		$sSuffix = utils::ReadParam('sSuffix', '');
 		$sJson = utils::ReadParam('json', '');
+		if (!empty($sJson))
+		{
 		$oWizardHelper = WizardHelper::FromJSON($sJson);
 		$oObj = $oWizardHelper->GetTargetObject();
+			$currentValue = $oObj->Get($sAttCode);
+		}
+		else
+		{
+			// Search form: no current object
+			$oObj = null;
+			$currentValue = 'eviV bulgroZ';
+		}
 		$aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array('this' => $oObj));
-		$oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, $oObj->Get($sAttCode), $iInputId, false, $sSuffix, '');
+		$oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, $currentValue, $iInputId, false, $sSuffix, '');
 		$oWidget->SearchObjectsToSelect($oPage, $sTargetClass);	
 		break;