Przeglądaj źródła

N°930 Better UI on object details part 1. (Careful, Bulf modify and CSV import might be partly broken...)

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@4814 a333f486-631f-4898-b8df-5754b55c2be0
glajarige 8 lat temu
rodzic
commit
f9c3e01cb8

+ 63 - 25
application/cmdbabstract.class.inc.php

@@ -629,6 +629,7 @@ EOF
 		// Compute the list of properties to display, first the attributes in the 'details' list, then 
 		// all the remaining attributes that are not external fields
 		$sHtml = '';
+		$sEditMode = ($bEditMode) ? 'edit' : 'view';
 		$aDetails = array();
 		$iInputId = 0;
 		$aFieldsMap = array();
@@ -639,9 +640,18 @@ EOF
 		foreach($aDetailsStruct as $sTab => $aCols )
 		{
 			$aDetails[$sTab] = array();
-			ksort($aCols);
+            $aTableStyles[] = 'vertical-align:top';
+
+            ksort($aCols);
+			$iColCount = count($aCols);
+			if($iColCount > 1)
+            {
+                $aTableStyles[] = 'width: 100%';
+            }
+            // Else, will size regarding the largest field of the column
+
 			$oPage->SetCurrentTab(Dict::S($sTab));
-			$oPage->add('<table style="vertical-align:top"><tr>');
+			$oPage->add('<table style="'.implode('; ', $aTableStyles).'" data-mode="'.$sEditMode.'"><tr>');
 			foreach($aCols as $sColIndex => $aFieldsets)
 			{
 				$oPage->add('<td style="vertical-align:top">');
@@ -651,7 +661,7 @@ EOF
 				$aDetails[$sTab][$sColIndex] = array();
 				foreach($aFieldsets as $sFieldsetName => $aFields)
 				{
-					if (!empty($sFieldsetName) && ($sFieldsetName[0] != '_'))
+				    if (!empty($sFieldsetName) && ($sFieldsetName[0] != '_'))
 					{
 						$sLabel = $sFieldsetName;
 					}
@@ -680,8 +690,8 @@ EOF
 						{
 
 
-						$sComments = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : '&nbsp;';
-						$sInfos = '&nbsp;';
+						$sComments = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : '';
+						$sInfos = '';
 						$iFlags = $this->GetFormAttributeFlags($sAttCode);
 						if (array_key_exists($sAttCode, $aExtraFlags))
 						{
@@ -698,7 +708,7 @@ EOF
 								{
 									// State attribute is always read-only from the UI
 									$sHTMLValue = $this->GetStateLabel();
-									$val = array('label' => '<span>'.$oAttDef->GetLabel().'</span>', 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos);
+									$val = array('label' => '<label>'.$oAttDef->GetLabel().'</label>', 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos, 'attcode' => $sAttCode);
 								}
 								else
 								{				
@@ -732,17 +742,28 @@ EOF
 										$sValue = $this->Get($sAttCode);
 										$sDisplayValue = $this->GetEditValue($sAttCode);
 										$aArgs = array('this' => $this, 'formPrefix' => $sPrefix);
-										$sHTMLValue = "<span id=\"field_{$sInputId}\">".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</span>';
+										$sHTMLValue = "<div id=\"field_{$sInputId}\" class=\"field_value_container\">".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</div>';
 									}
 									$aFieldsMap[$sAttCode] = $sInputId;
-									$val = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos);
+									$val = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos, 'attcode' => $sAttCode);
 								}
 							}
 							else
 							{
-								$val = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => "<span id=\"field_{$sInputId}\">".$this->GetAsHTML($sAttCode)."</span>", 'comments' => $sComments, 'infos' => $sInfos);
+								$val = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => "<span id=\"field_{$sInputId}\">".$this->GetAsHTML($sAttCode)."</span>", 'comments' => $sComments, 'infos' => $sInfos, 'attcode' => $sAttCode);
 								$aFieldsMap[$sAttCode] = $sInputId;	
 							}
+
+                            // Checking how the field should be rendered
+                            // Note: For view mode, this is done in cmdbAbstractObject::GetFieldAsHtml()
+                            if(in_array($oAttDef->GetEditClass(), array('Text', 'HTML', 'CaseLog', 'CustomFields')))
+                            {
+                                $val['layout'] = 'large';
+                            }
+                            else
+                            {
+                                $val['layout'] = 'small';
+                            }
 						}
 						else
 						{
@@ -761,7 +782,7 @@ EOF
 
 						if ($val != null)
 						{
-							// The field is visible, add it to the current column
+						    // The field is visible, add it to the current column
 							$aDetails[$sTab][$sColIndex][] = $val;
 							$iInputId++;
 						}				
@@ -1786,7 +1807,7 @@ EOF
 				$aEventsList[] ='change';
 				$sPlaceholderValue = 'placeholder="'.htmlentities(AttributeDate::GetFormat()->ToPlaceholder(), ENT_QUOTES, 'UTF-8').'"';
 
-				$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"12\" $sPlaceholderValue name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/>&nbsp;{$sValidationSpan}{$sReloadSpan}";
+				$sHTMLValue = "<div class=\"field_input_zone field_input_date\"><input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" $sPlaceholderValue name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/></div>{$sValidationSpan}{$sReloadSpan}";
 				break;
 
 				case 'DateTime':
@@ -1795,7 +1816,7 @@ EOF
 				$aEventsList[] ='change';
 
 				$sPlaceholderValue = 'placeholder="'.htmlentities(AttributeDateTime::GetFormat()->ToPlaceholder(), ENT_QUOTES, 'UTF-8').'"';
-				$sHTMLValue = "<input title=\"$sHelpText\" class=\"datetime-pick\" type=\"text\" size=\"19\" $sPlaceholderValue name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/>&nbsp;{$sValidationSpan}{$sReloadSpan}";
+				$sHTMLValue = "<div class=\"field_input_zone field_input_datetime\"><input title=\"$sHelpText\" class=\"datetime-pick\" type=\"text\" size=\"19\" $sPlaceholderValue name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/></div>{$sValidationSpan}{$sReloadSpan}";
 				break;
 
 				case 'Duration':
@@ -1819,7 +1840,7 @@ EOF
 					$aEventsList[] ='validate';
 					$aEventsList[] ='keyup';
 					$aEventsList[] ='change';
-					$sHTMLValue = "<input title=\"$sHelpText\" type=\"password\" size=\"30\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/>&nbsp;{$sValidationSpan}{$sReloadSpan}";
+					$sHTMLValue = "<div class=\"field_input_zone field_input_password\"><input title=\"$sHelpText\" type=\"password\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/></div>{$sValidationSpan}{$sReloadSpan}";
 				break;
 				
 				case 'OQLExpression':
@@ -1828,10 +1849,10 @@ EOF
 					$aEventsList[] ='keyup';
 					$aEventsList[] ='change';
 					$sEditValue = $oAttDef->GetEditValue($value);
+
 					$aStyles = array();
 					$sStyle = '';
 					$sWidth = $oAttDef->GetWidth('width', '');
-
 					if (!empty($sWidth))
 					{
 						$aStyles[] = 'width:'.$sWidth;
@@ -1845,6 +1866,7 @@ EOF
 					{
 						$sStyle = 'style="'.implode('; ', $aStyles).'"';
 					}
+
 					if ($oAttDef->GetEditClass() == 'OQLExpression')
 					{
 						$sTestResId = 'query_res_'.$sFieldPrefix.$sAttCode.$sNameSuffix; //$oPage->GetUniqueId();
@@ -1858,7 +1880,7 @@ EOF
 						$sAdditionalStuff = "";
 					}
 					// Ok, the text area is drawn here
-					$sHTMLValue = "<table><tr><td><textarea class=\"resizable\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\" $sStyle>".htmlentities($sEditValue, ENT_QUOTES, 'UTF-8')."</textarea>$sAdditionalStuff</td><td>{$sValidationSpan}{$sReloadSpan}</td></tr></table>";
+					$sHTMLValue = "<div class=\"field_input_zone field_input_text\"><textarea class=\"\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\" $sStyle>".htmlentities($sEditValue, ENT_QUOTES, 'UTF-8')."</textarea>$sAdditionalStuff</div>{$sValidationSpan}{$sReloadSpan}";
 
 				break;
 
@@ -1879,12 +1901,14 @@ EOF
 					{
 						$sStyle = 'style="'.implode('; ', $aStyles).'"';
 					}
+
 					$sHeader = '<div class="caselog_input_header"></div>'; // will be hidden in CSS (via :empty) if it remains empty
 					$sEditValue = is_object($value) ? $value->GetModifiedEntry('html') : '';
 					$sPreviousLog = is_object($value) ? $value->GetAsHTML($oPage, true /* bEditMode */, array('AttributeText', 'RenderWikiHtml')) : '';
 					$iEntriesCount = is_object($value) ? count($value->GetIndex()) : 0;
 					$sHidden = "<input type=\"hidden\" id=\"{$iId}_count\" value=\"$iEntriesCount\"/>"; // To know how many entries the case log already contains
-					$sHTMLValue = "<div class=\"caselog\" $sStyle><table style=\"width:100%;\"><tr><td>$sHeader<textarea class=\"htmlEditor\" style=\"border:0;width:100%\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\">".htmlentities($sEditValue, ENT_QUOTES, 'UTF-8')."</textarea>$sPreviousLog</td><td>{$sValidationSpan}{$sReloadSpan}</td></tr></table>$sHidden</div>";
+
+					$sHTMLValue = "<div class=\"field_input_zone field_input_caselog caselog\" $sStyle>$sHeader<textarea class=\"htmlEditor\" style=\"border:0;width:100%\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\">".htmlentities($sEditValue, ENT_QUOTES, 'UTF-8')."</textarea>$sPreviousLog</div>{$sValidationSpan}{$sReloadSpan}$sHidden";
 					$oPage->add_ready_script("$('#$iId').bind('keyup change validate', function(evt, sFormId) { return ValidateCaseLogField('$iId', $bMandatory, sFormId) } );"); // Custom validation function
 				break;
 
@@ -1919,10 +1943,13 @@ EOF
 						$sFileName = $oDocument->GetFileName();
 					}
 					$iMaxFileSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
-					$sHTMLValue = "<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"$iMaxFileSize\" />\n";
+					$sHTMLValue = "<div class=\"field_input_zone field_input_document\">\n";
+					$sHTMLValue .= "<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"$iMaxFileSize\" />\n";
 					$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[filename]\" type=\"hidden\" id=\"$iId\" \" value=\"".htmlentities($sFileName, ENT_QUOTES, 'UTF-8')."\"/>\n";
-					$sHTMLValue .= "<span id=\"name_$iInputId\">".htmlentities($sFileName, ENT_QUOTES, 'UTF-8')."</span><br/>\n";
-					$sHTMLValue .= "<input title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[fcontents]\" type=\"file\" id=\"file_$iId\" onChange=\"UpdateFileName('$iId', this.value)\"/>&nbsp;{$sValidationSpan}{$sReloadSpan}\n";
+					$sHTMLValue .= "<span id=\"name_$iInputId\"'>".htmlentities($sFileName, ENT_QUOTES, 'UTF-8')."</span><br/>\n";
+					$sHTMLValue .= "<input title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[fcontents]\" type=\"file\" id=\"file_$iId\" onChange=\"UpdateFileName('$iId', this.value)\"/>\n";
+					$sHTMLValue .= "</div>\n";
+					$sHTMLValue .= "{$sValidationSpan}{$sReloadSpan}\n";
 				break;
 
 				case 'Image':
@@ -1940,8 +1967,8 @@ EOF
 						$sUrl = $sDefaultUrl;
 					}
 
-					$sHTMLValue = "<div id=\"edit_$iInputId\" class=\"edit-image\"></div>";
-					$sHTMLValue .= "&nbsp;{$sValidationSpan}{$sReloadSpan}\n";
+					$sHTMLValue = "<div class=\"field_input_zone field_input_image\"><div id=\"edit_$iInputId\" class=\"edit-image\"></div></div>\n";
+					$sHTMLValue .= "{$sValidationSpan}{$sReloadSpan}\n";
 
 					$aEditImage = array(
 						'input_name' => 'attr_'.$sFieldPrefix.$sAttCode.$sNameSuffix,
@@ -2075,7 +2102,7 @@ EOF
 							
 							case 'select':
 							default:
-							$sHTMLValue = "<select title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" id=\"$iId\">\n";
+							$sHTMLValue = "<div class=\"field_input_zone field_input_string\"><select title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" id=\"$iId\">\n";
 							$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
 							foreach($aAllowedValues as $key => $display_value)
 							{
@@ -2090,13 +2117,13 @@ EOF
 								}
 								$sHTMLValue .= "<option value=\"$key\"$sSelected>$display_value</option>\n";
 							}
-							$sHTMLValue .= "</select>&nbsp;{$sValidationSpan}{$sReloadSpan}\n";
+							$sHTMLValue .= "</select></div>{$sValidationSpan}{$sReloadSpan}\n";
 							$aEventsList[] ='change';
 						}
 					}
 					else
 					{
-						$sHTMLValue = "<input title=\"$sHelpText\" type=\"text\" size=\"30\" maxlength=\"$iFieldSize\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/>&nbsp;{$sValidationSpan}{$sReloadSpan}";
+						$sHTMLValue = "<div class=\"field_input_zone field_input_string\"><input title=\"$sHelpText\" type=\"text\" maxlength=\"$iFieldSize\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8')."\" id=\"$iId\"/></div>{$sValidationSpan}{$sReloadSpan}";
 						$aEventsList[] ='keyup';
 						$aEventsList[] ='change';
 					}
@@ -2763,7 +2790,18 @@ EOF
 			{
 				$sDisplayValue = $this->GetAsHTML($sAttCode);
 			}
-			$retVal = array('label' => '<span title="'.MetaModel::GetDescription($sClass, $sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>', 'value' => $sDisplayValue);
+			$retVal = array('label' => '<span title="'.MetaModel::GetDescription($sClass, $sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>', 'value' => $sDisplayValue, 'attcode' => $sAttCode);
+
+            // Checking how the field should be rendered
+            // Note: For edit mode, this is done in self::GetBareProperties()
+            if(in_array($oAttDef->GetEditClass(), array('Text', 'HTML', 'CaseLog', 'CustomFields')))
+            {
+                $retVal['layout'] = 'large';
+            }
+            else
+            {
+                $retVal['layout'] = 'small';
+            }
 		}
 		return $retVal;
 	}

+ 4 - 2
application/itopwebpage.class.inc.php

@@ -236,7 +236,9 @@ EOF;
 		// note: each action implemented here must be idempotent,
 		//       because this helper function might be called several times on a given page 
 	
-		$(".date-pick").datepicker($sJSDatePickerOptions);
+	    // Note: Trigger image is wrapped in a span so we can display it we want 
+		$(".date-pick").datepicker($sJSDatePickerOptions)
+		    .next("img").wrap("<span>");
 	
 		// Hack for the date and time picker addon issue on Chrome (see #1305)
 		// The workaround is to instantiate the widget on demand
@@ -244,7 +246,7 @@ EOF;
 		$(".datetime-pick:not(.is-widget-ready)").each(function(){
 			var oInput = this;
 			$(oInput).addClass('is-widget-ready');
-			$('<img class="datetime-pick-button" src="../images/calendar.png">')
+			$('<span><img class="datetime-pick-button" src="../images/calendar.png"></span>')
 				.insertAfter($(this))
 				.on('click', function(){
 					$(oInput)

+ 25 - 18
application/ui.extkeywidget.class.inc.php

@@ -116,7 +116,7 @@ class UIExtKeyWidget
 		$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
 		$sAttrFieldPrefix = ($this->bSearchMode) ? '' : 'attr_';
 
-		$sHTMLValue = "<span style=\"white-space:nowrap\">"; // no wrap
+		$sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">";
 		$sFilter = addslashes($oAllowedValues->GetFilter()->ToOQL());
 		if($this->bSearchMode)
 		{
@@ -144,14 +144,14 @@ class UIExtKeyWidget
 		$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
 		if ($oAllowedValues->Count() < $iMaxComboLength)
 		{
-			// Discrete list of values, use a SELECT or RADIO buttons depending on the config
+            // Discrete list of values, use a SELECT or RADIO buttons depending on the config
 			switch($sDisplayStyle)
 			{
 				case 'radio':
 				case 'radio_horizontal':
 				case 'radio_vertical':
-				$sValidationField = "<span id=\"v_{$this->iId}\"></span><span id=\"fstatus_{$this->iId}\"></span>";
-				$sHTMLValue = '';
+				$sValidationField = null;
+
 				$bVertical = ($sDisplayStyle != 'radio_horizontal');
 				$bExtensions = false;
 				$oAllowedValues->Rewind();
@@ -160,7 +160,7 @@ class UIExtKeyWidget
 				{
 					$aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
 				}				
-				$sHTMLValue = $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", $bMandatory, $bVertical, $sValidationField);
+				$sHTMLValue .= $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", false /*  $bMandatory will be placed manually */, $bVertical, $sValidationField);
 				$aEventsList[] ='change';
 				break;
 
@@ -170,25 +170,27 @@ class UIExtKeyWidget
 				$sSelectMode = 'true';
 				
 				$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
-				
+				$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
+
 				if ($this->bSearchMode)
 				{
 					if ($bSearchMultiple)
 					{
-						$sHTMLValue = "<select class=\"multiselect\" multiple title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}[]\" id=\"$this->iId\">\n";
+						$sHTMLValue .= "<select class=\"multiselect\" multiple title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}[]\" id=\"$this->iId\">\n";
 					}
 					else
 					{
-						$sHTMLValue = "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
+						$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
 						$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : Dict::S('UI:SearchValue:Any');
 						$sHTMLValue .= "<option value=\"\">$sDisplayValue</option>\n";
 					}
 				}
 				else
 				{
-					$sHTMLValue = "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
+					$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\">\n";
 					$sHTMLValue .= "<option value=\"\">".Dict::S('UI:SelectOne')."</option>\n";
 				}
+
 				$oAllowedValues->Rewind();
 				while($oObj = $oAllowedValues->Fetch())
 				{
@@ -207,6 +209,8 @@ class UIExtKeyWidget
 					$sHTMLValue .= "<option value=\"$key\"$sSelected>$display_value</option>\n";
 				}
 				$sHTMLValue .= "</select>\n";
+				$sHTMLValue .= "</div>\n";
+
 				if (($this->bSearchMode) && $bSearchMultiple)
 				{
 					$aOptions = array(
@@ -257,8 +261,8 @@ EOF
 			$iFieldSize = isset($aArgs['iFieldSize']) ? $aArgs['iFieldSize'] : 20; //@@@ $this->oAttDef->GetMaxSize();
 	
 			// the input for the auto-complete
-			$sHTMLValue = "<input count=\"".$oAllowedValues->Count()."\" type=\"text\" id=\"label_$this->iId\" size=\"$iFieldSize\" value=\"$sDisplayValue\"/>&nbsp;";
-			$sHTMLValue .= "<img id=\"mini_search_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_search.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.Search();\"/>";
+			$sHTMLValue .= "<input class=\"field_autocomplete\" count=\"".$oAllowedValues->Count()."\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
+			$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_search_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_search.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.Search();\"/></span>";
 	
 			// another hidden input to store & pass the object's Id
 			$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n";
@@ -282,7 +286,7 @@ EOF
 		}
 		if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
 		{
-			$sHTMLValue .= "<img id=\"mini_tree_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_tree.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"/>&nbsp;";
+			$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_tree_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_tree.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"/></span>";
 			$oPage->add_ready_script(
 <<<EOF
 			if ($('#ac_tree_{$this->iId}').length == 0)
@@ -294,7 +298,7 @@ EOF
 		}
 		if ($bCreate && $bExtensions)
 		{
-			$sHTMLValue .= "<img id=\"mini_add_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_add.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.CreateObject();\"/>&nbsp;";
+			$sHTMLValue .= "<span class=\"field_input_btn\"><img id=\"mini_add_{$this->iId}\" style=\"border:0;vertical-align:middle;cursor:pointer;\" src=\"../images/mini_add.gif?itopversion=".ITOP_VERSION."\" onClick=\"oACWidget_{$this->iId}.CreateObject();\"/></span>";
 			$oPage->add_ready_script(
 <<<EOF
 		if ($('#ajax_{$this->iId}').length == 0)
@@ -304,11 +308,14 @@ EOF
 EOF
 );
 		}
-		if (($sDisplayStyle == 'select') || ($sDisplayStyle == 'list'))
-		{
-			$sHTMLValue .= "<span id=\"v_{$this->iId}\"></span><span id=\"fstatus_{$this->iId}\"></span>";
-		}
-		$sHTMLValue .= "</span>"; // end of no wrap
+        $sHTMLValue .= "</div>";
+
+		// Note: This test is no longer necessary as we changed the markup to extract validation decoration in the standard .field_input_xxx container
+		//if (($sDisplayStyle == 'select') || ($sDisplayStyle == 'list'))
+		//{
+			$sHTMLValue .= "<span class=\"form_validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
+		//}
+
 		return $sHTMLValue;
 	}
 	

+ 1 - 1
application/ui.htmleditorwidget.class.inc.php

@@ -64,7 +64,7 @@ class UIHTMLEditorWidget
 		$sHelpText = $this->m_sHelpText;
 		$sValidationField = $this->m_sValidationField;
 
-		$sHtmlValue = "<table><tr><td><textarea class=\"htmlEditor\" title=\"$sHelpText\" name=\"attr_{$this->m_sFieldPrefix}{$sCode}\" rows=\"10\" cols=\"10\" id=\"$iId\">$sValue</textarea></td><td>$sValidationField</td></tr></table>";
+		$sHtmlValue = "<div class=\"field_input_zone field_input_html\"><textarea class=\"htmlEditor\" title=\"$sHelpText\" name=\"attr_{$this->m_sFieldPrefix}{$sCode}\" rows=\"10\" cols=\"10\" id=\"$iId\">$sValue</textarea></div>$sValidationField";
 
 		// Replace the text area with CKEditor
 		// To change the default settings of the editor,

+ 22 - 11
application/webpage.class.inc.php

@@ -345,27 +345,38 @@ class WebPage implements Page
 	 */
 	public function GetDetails($aFields)
 	{
-		$sHtml = "<table class=\"details\">\n";
-		$sHtml .= "<tbody>\n";
+		$sHtml = "<div class=\"details\">\n";
 		foreach($aFields as $aAttrib)
 		{
-			$sHtml .= "<tr>\n";
+		    $sHtml .= "<div class=\"field_container field_{$aAttrib['layout']}\" data-attcode=\"{$aAttrib['attcode']}\">\n";
+            $sHtml .= "<div class=\"field_label label\">{$aAttrib['label']}</div>\n";
+
+            $sHtml .= "<div class=\"field_data\">\n";
 			// By Rom, for csv import, proposed to show several values for column selection
 			if (is_array($aAttrib['value']))
 			{
-				$sHtml .= "<td class=\"label\">".$aAttrib['label']."</td><td>".implode("</td><td>", $aAttrib['value'])."</td>\n";
+				$sHtml .= "<div class=\"field_value\">".implode("</div><div>", $aAttrib['value'])."</div>\n";
 			}
 			else
 			{
-				$sHtml .= "<td class=\"label\">".$aAttrib['label']."</td><td>".$aAttrib['value']."</td>\n";
+				$sHtml .= "<div class=\"field_value\">".$aAttrib['value']."</div>\n";
 			}
-			$sComment = (isset($aAttrib['comments'])) ? $aAttrib['comments'] : '&nbsp;';
-			$sInfo = (isset($aAttrib['infos'])) ? $aAttrib['infos'] : '&nbsp;';
-			$sHtml .= "<td>$sComment</td><td>$sInfo</td>\n";
-    		$sHtml .= "</tr>\n";
+			// Checking if we should add comments & infos
+			$sComment = (isset($aAttrib['comments'])) ? $aAttrib['comments'] : '';
+			$sInfo = (isset($aAttrib['infos'])) ? $aAttrib['infos'] : '';
+			if($sComment !== '')
+            {
+                $sHtml .= "<div class=\"field_comments\">$sComment</div>\n";
+            }
+            if($sInfo !== '')
+            {
+                $sHtml .= "<div class=\"field_infos\">$sInfo</div>\n";
+            }
+			$sHtml .= "</div>\n";
+
+			$sHtml .= "</div>\n";
 		}
-		$sHtml .= "</tbody>\n";
-		$sHtml .= "</table>\n";
+		$sHtml .= "</div>\n";
 		return $sHtml;
     }
 

+ 150 - 6
css/light-grey.css

@@ -1138,21 +1138,165 @@ span.form_validation {
   margin-top: 0.25em;
   margin-bottom: 0.25em;
 }
-table.details {
+.details {
   border-collapse: collapse;
   noborder-bottom: 2px #fff solid;
   nowidth: 100%;
 }
-table.details > tbody > tr > td {
+.details * {
+  box-sizing: border-box;
+}
+.details > .field_container {
+  display: table;
+  width: 100%;
+  margin-bottom: 5px;
   border-bottom: 2px #ddd solid;
-  padding-bottom: 5px;
-  padding-top: 3px;
+  /* .field_label, .field_data */
 }
-fieldset table.details > tbody > tr > td {
-  padding-top: 3px;
+.details > .field_container:last-child {
+  margin-bottom: 0px;
+}
+.details > .field_container.field_large {
+  display: inherit;
+  /* .field_label, .field_data */
+}
+.details > .field_container.field_large > div {
+  display: inherit;
+  /* .field_value, .field_comments, .field_infos */
+}
+.details > .field_container.field_large > div.field_label {
+  width: inherit;
+  margin-bottom: 5px;
+}
+.details > .field_container > div {
+  display: table-cell;
+  vertical-align: top;
+  /* .field_value, .field_comments, .field_infos */
+}
+.details > .field_container > div.field_label {
+  width: 30%;
+  padding-right: 10px;
+}
+.details > .field_container > div.field_label > label, .details > .field_container > div.field_label span {
+  color: #000;
+  font-weight: bold;
+}
+.details > .field_container > div.field_data {
+  display: table;
+  width: 100%;
+  margin-bottom: 5px;
+}
+.details > .field_container > div > div {
+  display: table-cell;
+  width: auto;
+}
+.details > .field_container > div > div.field_comments, .details > .field_container > div > div.field_infos {
+  width: 20px;
+}
+.details > .field_container > div > div.field_value .attribute-edit {
+  display: table;
+  width: 100%;
+  /* TODO: Refactor so status icon show over mandatory icon */
+}
+.details > .field_container > div > div.field_value .attribute-edit .form_validation, .details > .field_container > div > div.field_value .attribute-edit .field_status {
+  display: table-cell;
+  width: 20px;
+  padding-left: 0.4em;
+  vertical-align: middle;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone {
+  width: 100%;
+  /* auto; */
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_string > select, .details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_password > select, .details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_string input, .details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_password input {
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_date, .details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_datetime {
+  display: table;
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_date > input, .details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_datetime > input {
+  display: table-cell;
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_date > span, .details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_datetime > span {
+  display: table-cell;
+  width: 20px;
+  padding-left: 0.4em;
+  vertical-align: middle;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_date > span > img, .details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_datetime > span > img {
+  max-width: 16px;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_text {
+  border: none;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_text textarea {
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document > input {
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_document > span {
+  display: inline-block;
+  margin-bottom: 2px;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_image input {
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey {
+  display: table;
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_select_wrapper {
+  display: table-cell;
+  width: auto;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_select_wrapper > select {
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_autocomplete {
+  display: table-cell;
+  width: 100%;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn {
+  display: table-cell;
+  width: 25px;
+  padding-left: 0.4em;
+}
+.details > .field_container > div > div.field_value .attribute-edit .field_input_zone.field_input_extkey > .field_input_btn > img {
+  max-width: 20px;
+}
+fieldset .details > .field_container {
   background: transparent;
   border: 0;
 }
+#SiloSelection {
+  padding-top: 3px;
+  padding-right: 30px;
+  text-align: left;
+}
+#SiloSelection * {
+  box-sizing: border-box;
+  vertical-align: middle;
+}
+#SiloSelection .field_input_extkey {
+  display: table;
+  width: 100%;
+}
+#SiloSelection .field_input_extkey .field_select_wrapper {
+  display: table-cell;
+  width: 100%;
+}
+#SiloSelection .field_input_extkey .field_select_wrapper > select {
+  width: 100%;
+  max-width: initial;
+}
+#SiloSelection .field_input_extkey .field_input_btn {
+  display: table-cell;
+  width: 20px;
+  margin-left: 0.4em;
+}
 .ac_dlg_loading {
   background: white url('../images/indicator.gif') right center no-repeat;
 }

+ 219 - 8
css/light-grey.scss

@@ -1227,21 +1227,232 @@ span.form_validation {
 	margin-top: 0.25em;
 	margin-bottom: 0.25em;
 }
-table.details {
+
+.details {
   border-collapse: collapse;
   noborder-bottom: 2px #fff solid;
   nowidth:100%;
+
+	* {
+		box-sizing: border-box;
+	}
+
+	> .field_container {
+		display: table;
+		width: 100%;
+		margin-bottom: 5px;
+		border-bottom: 2px #ddd solid;
+
+		&:last-child {
+			margin-bottom: 0px;
+		}
+
+		&.field_large{
+			display: inherit;
+
+			/* .field_label, .field_data */
+			> div {
+				display: inherit;
+
+				&.field_label{
+					width: inherit;
+					margin-bottom: 5px;
+				}
+
+				/* .field_value, .field_comments, .field_infos */
+				> div {
+				}
+			}
+		}
+
+		/* .field_label, .field_data */
+		> div {
+			display: table-cell;
+			vertical-align: top;
+
+			&.field_label {
+				width: 30%;
+				padding-right: 10px;
+
+				> label,span {
+					color: #000000;
+					font-weight:bold;
+				}
+			}
+
+			&.field_data {
+				display: table;
+				width: 100%;
+				margin-bottom: 5px;
+			}
+
+			/* .field_value, .field_comments, .field_infos */
+			> div {
+				display: table-cell;
+				width: auto;
+
+				&.field_comments,
+				&.field_infos{
+					width: 20px;
+				}
+
+				&.field_value{
+
+					.attribute-edit{
+						display: table;
+						width: 100%;
+
+						/* TODO: Refactor so status icon show over mandatory icon */
+						.form_validation, .field_status{
+							display: table-cell;
+							width: 20px;
+							padding-left: 0.4em;
+							vertical-align: middle;
+						}
+
+						.field_input_zone{
+							width: 100%; /* auto; */
+
+							&.field_input_string,
+							&.field_input_password{
+								> select, input{
+									width: 100%;
+								}
+							}
+
+							&.field_input_onewaypassword{
+								// Not implemented yet
+							}
+
+							&.field_input_date,
+							&.field_input_datetime{
+								display: table;
+								width: 100%;
+
+								> input {
+									display: table-cell;
+									width: 100%;
+								}
+
+								> span {
+									display: table-cell;
+									width: 20px;
+									padding-left: 0.4em;
+									vertical-align: middle;
+
+									> img {
+										max-width: 16px;
+									}
+								}
+							}
+
+							&.field_input_text{
+								border: none;
+
+								//.f_i_text_header{
+								//	padding: 6px 8px 2px;
+								//	white-space: normal;
+								//	border-bottom: 1px solid #fff;
+								//	background: #f2f2f2;
+								//}
+								textarea{
+									width: 100%;
+									//padding: 5px;
+									//border: none;
+								}
+							}
+
+							&.field_input_html{
+								// Nothing
+							}
+
+							&.field_input_document{
+								> input{
+									width: 100%;
+								}
+
+								> span {
+									display: inline-block;
+									margin-bottom: 2px;
+								}
+							}
+
+							&.field_input_image{
+								input{
+									width: 100%;
+								}
+							}
+
+							&.field_input_extkey{
+								display: table;
+								width: 100%;
+
+								> .field_select_wrapper{
+									display: table-cell;
+									width: auto;
+
+									> select {
+										width: 100%;
+									}
+								}
+
+								> .field_autocomplete{
+									display: table-cell;
+									width: 100%;
+								}
+
+								> .field_input_btn{
+									display: table-cell;
+									width: 25px;
+									padding-left: 0.4em;
+
+									> img {
+										max-width: 20px;
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
 }
-table.details>tbody>tr>td {
-	border-bottom: 2px #ddd solid;
-	padding-bottom: 5px;
-	padding-top: 3px;
-}
-fieldset table.details>tbody>tr>td {
-	padding-top: 3px;
+fieldset .details>.field_container {
 	background: transparent;
 	border: 0;
 }
+#SiloSelection{
+	padding-top: 3px;
+	padding-right: 30px;
+	text-align: left;
+
+	*{
+		box-sizing: border-box;
+		vertical-align: middle;
+	}
+
+	.field_input_extkey{
+		display: table;
+		width: 100%;
+
+		.field_select_wrapper{
+			display: table-cell;
+			width: 100%;
+
+			> select{
+				width: 100%;
+				max-width: initial;
+			}
+		}
+
+		.field_input_btn{
+			display: table-cell;
+			width: 20px;
+			margin-left: 0.4em;
+		}
+	}
+}
 .ac_dlg_loading {
 	background: white url('../images/indicator.gif') right center no-repeat;
 }