mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
- Added validation of the fields based on a regexp pattern
- Fields that depend on another field (in the same form) get refreshed when one of the fields they depend on is changed - Updated the wizard to group all the mandatory fields on the first page, since having inter-dependent fields on one page is now supported SVN:trunk[412]
This commit is contained in:
@@ -828,25 +828,29 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
if (!$oAttDef->IsExternalField())
|
||||
{
|
||||
$aCSSClasses = array();
|
||||
$bMandatory = 0;
|
||||
if ( (!$oAttDef->IsNullAllowed()) || ($iFlags & OPT_ATT_MANDATORY))
|
||||
{
|
||||
$aCSSClasses[] = 'mandatory';
|
||||
$bMandatory = 1;
|
||||
}
|
||||
$sCSSClasses = self::GetCSSClasses($aCSSClasses);
|
||||
$sValidationField = "<span id=\"v_{$iInputId}\"></span>";
|
||||
switch($oAttDef->GetEditClass())
|
||||
{
|
||||
case 'Date':
|
||||
case 'DateTime':
|
||||
$aCSSClasses[] = 'date-pick';
|
||||
$sCSSClasses = self::GetCSSClasses($aCSSClasses);
|
||||
$sHTMLValue = "<input type=\"text\" size=\"20\" name=\"attr_{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iInputId\"{$sCSSClasses}/>";
|
||||
$sHTMLValue = "<input type=\"text\" size=\"20\" name=\"attr_{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iInputId\"{$sCSSClasses}/>$sValidationField";
|
||||
break;
|
||||
|
||||
case 'Password':
|
||||
$sHTMLValue = "<input type=\"password\" size=\"30\" name=\"attr_{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iInputId\"{$sCSSClasses}/>";
|
||||
$sHTMLValue = "<input type=\"password\" size=\"30\" name=\"attr_{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iInputId\"{$sCSSClasses}/>$sValidationField";
|
||||
break;
|
||||
|
||||
case 'Text':
|
||||
$sHTMLValue = "<textarea name=\"attr_{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iInputId\"{$sCSSClasses}>$value</textarea>";
|
||||
$sHTMLValue = "<textarea name=\"attr_{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iInputId\"{$sCSSClasses}>$value</textarea>$sValidationField";
|
||||
break;
|
||||
|
||||
case 'List':
|
||||
@@ -884,7 +888,7 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
{
|
||||
// too many choices, use an autocomplete
|
||||
// The input for the auto complete
|
||||
$sHTMLValue = "<input count=\"".count($aAllowedValues)."\" type=\"text\" id=\"label_$iInputId\" size=\"30\" value=\"$sDisplayValue\"{$sCSSClasses}/>";
|
||||
$sHTMLValue = "<input count=\"".count($aAllowedValues)."\" type=\"text\" id=\"label_$iInputId\" size=\"30\" value=\"$sDisplayValue\"{$sCSSClasses}/>$sValidationField";
|
||||
// another hidden input to store & pass the object's Id
|
||||
$sHTMLValue .= "<input type=\"hidden\" id=\"$iInputId\" name=\"attr_{$sAttCode}{$sNameSuffix}\" value=\"$value\" />\n";
|
||||
$oPage->add_ready_script("\$('#label_$iInputId').autocomplete('./ajax.render.php', { scroll:true, minChars:3, onItemSelect:selectItem, onFindValue:findValue, formatItem:formatItem, autoFill:true, keyHolder:'#$iInputId', extraParams:{operation:'autocomplete', sclass:'$sClass',attCode:'".$sAttCode."'}});");
|
||||
@@ -906,15 +910,22 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
$sSelected = ($value == $key) ? ' selected' : '';
|
||||
$sHTMLValue .= "<option value=\"$key\"$sSelected>$display_value</option>\n";
|
||||
}
|
||||
$sHTMLValue .= "</select>\n";
|
||||
$sHTMLValue .= "</select>$sValidationField\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHTMLValue = "<input type=\"text\" size=\"30\" name=\"attr_{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iInputId\"{$sCSSClasses} />";
|
||||
$sHTMLValue = "<input type=\"text\" size=\"30\" name=\"attr_{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iInputId\"{$sCSSClasses} />$sValidationField";
|
||||
}
|
||||
break;
|
||||
}
|
||||
$sPattern = addslashes($oAttDef->GetValidationPattern()); //'^([0-9]+)$';
|
||||
$oPage->add_ready_script("$('#$iInputId').bind('validate blur', function(evt, sFormId) { return ValidateField('$iInputId', '$sPattern', $bMandatory, sFormId) } );"); // Bind to a custom event: validate
|
||||
$aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode); // List of attributes that depend on the current one
|
||||
if (count($aDependencies) > 0)
|
||||
{
|
||||
$oPage->add_ready_script("$('#$iInputId').bind('change', function(evt, sFormId) { return UpdateDependentFields(['".implode("','", $aDependencies)."']) } );"); // Bind to a custom event: validate
|
||||
}
|
||||
}
|
||||
return $sHTMLValue;
|
||||
}
|
||||
@@ -923,12 +934,14 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
{
|
||||
static $iFormId = 0;
|
||||
$iFormId++;
|
||||
$sClass = get_class($this);
|
||||
$oAppContext = new ApplicationContext();
|
||||
$sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
|
||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||
$iKey = $this->GetKey();
|
||||
$aDetails = array();
|
||||
$oPage->add("<form id=\"form_{$iFormId}\" enctype=\"multipart/form-data\" method=\"post\" onSubmit=\"return CheckMandatoryFields('form_{$iFormId}')\">\n");
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
|
||||
$aFieldsMap = array();
|
||||
$oPage->add("<form id=\"form_{$iFormId}\" enctype=\"multipart/form-data\" method=\"post\" onSubmit=\"return CheckFields('form_{$iFormId}')\">\n");
|
||||
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode=>$oAttDef)
|
||||
{
|
||||
if ($oAttDef->IsWritable())
|
||||
{
|
||||
@@ -957,7 +970,10 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
$sValue = $this->Get($sAttCode);
|
||||
$sDisplayValue = $this->GetEditValue($sAttCode);
|
||||
$aArgs = array('this' => $this);
|
||||
$sHTMLValue = self::GetFormElementForField($oPage, get_class($this), $sAttCode, $oAttDef, $sValue, $sDisplayValue, '', '', $iFlags, $aArgs);
|
||||
$sInputId = $iFormId.'_'.$sAttCode;
|
||||
$sHTMLValue = "<span id=\"field_{$sInputId}\">".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs);
|
||||
$aFieldsMap[$sAttCode] = $sInputId;
|
||||
|
||||
}
|
||||
$aDetails[] = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
|
||||
}
|
||||
@@ -966,7 +982,7 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
}
|
||||
$oPage->details($aDetails);
|
||||
$oPage->add("<input type=\"hidden\" name=\"id\" value=\"$iKey\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"".get_class($this)."\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"class\" value=\"$sClass\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_modify\">\n");
|
||||
$oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\">\n");
|
||||
foreach($aExtraParams as $sName => $value)
|
||||
@@ -977,6 +993,18 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
$oPage->add("<button type=\"button\" class=\"action\" onClick=\"goBack()\"><span>".Dict::S('UI:Button:Cancel')."</span></button> \n");
|
||||
$oPage->add("<button type=\"submit\" class=\"action\"><span>".Dict::S('UI:Button:Apply')."</span></button>\n");
|
||||
$oPage->add("</form>\n");
|
||||
|
||||
$iFieldsCount = count($aFieldsMap);
|
||||
$sJsonFieldsMap = json_encode($aFieldsMap);
|
||||
|
||||
$oPage->add_script(
|
||||
<<<EOF
|
||||
// Initializes the object once at the beginning of the page...
|
||||
var oWizardHelper = new WizardHelper('$sClass');
|
||||
oWizardHelper.SetFieldsMap($sJsonFieldsMap);
|
||||
oWizardHelper.SetFieldsCount($iFieldsCount);
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
public static function DisplayCreationForm(WebPage $oPage, $sClass, $oObjectToClone = null, $aArgs = array(), $aExtraParams = array())
|
||||
@@ -989,7 +1017,7 @@ abstract class cmdbAbstractObject extends CMDBObject
|
||||
$sOperation = ($oObjectToClone == null) ? 'apply_new' : 'apply_clone';
|
||||
$sClass = ($oObjectToClone == null) ? $sClass : get_class($oObjectToClone);
|
||||
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
|
||||
$oPage->add("<form id=\"creation_form_{$iCreationFormId}\" method=\"post\" enctype=\"multipart/form-data\" onSubmit=\"return CheckMandatoryFields('creation_form_{$iCreationFormId}')\">\n");
|
||||
$oPage->add("<form id=\"creation_form_{$iCreationFormId}\" method=\"post\" enctype=\"multipart/form-data\" onSubmit=\"return CheckFields('creation_form_{$iCreationFormId}')\">\n");
|
||||
$aStates = MetaModel::EnumStates($sClass);
|
||||
if ($oObjectToClone == null)
|
||||
{
|
||||
|
||||
@@ -61,8 +61,8 @@ class UIWizard
|
||||
$sFieldFlag = (($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE)) || (!$oAttDef->IsNullAllowed()) )? ' <span class="hilite">*</span>' : '';
|
||||
$oDefaultValuesSet = $oAttDef->GetDefaultValue(/* $oObject->ToArgs() */); // @@@ TO DO: get the object's current value if the object exists
|
||||
$sHTMLValue = cmdbAbstractObject::GetFormElementForField($this->m_oPage, $this->m_sClass, $sAttCode, $oAttDef, $oDefaultValuesSet, '', "att_$iMaxInputId", '', $iOptions, $aArgs);
|
||||
$aFieldsMap[$iMaxInputId] = $sAttCode;
|
||||
$aDetails[] = array('label' => $oAttDef->GetLabel().$sFieldFlag, 'value' => "<div id=\"field_$iMaxInputId\">$sHTMLValue</div>");
|
||||
$aFieldsMap["att_$iMaxInputId"] = $sAttCode;
|
||||
$aDetails[] = array('label' => $oAttDef->GetLabel().$sFieldFlag, 'value' => "<span id=\"field_att_$iMaxInputId\">$sHTMLValue</span>");
|
||||
if ($oAttDef->GetValuesDef() != null)
|
||||
{
|
||||
$sJSHandlerCode .= "\toWizardHelper.RequestAllowedValues('$sAttCode');\n";
|
||||
@@ -128,6 +128,7 @@ $sJSHandlerCode
|
||||
$this->m_oPage->add("<div id=\"object_preview\">\n");
|
||||
$this->m_oPage->add("</div>\n");
|
||||
$this->m_oPage->add($oAppContext->GetForForm());
|
||||
$this->m_oPage->add("<input type=\"button\" value=\"".Dict::S('UI:Button:Back')."\" onClick=\"GoToStep($iStepIndex, $iStepIndex - 1)\" />");
|
||||
$this->m_oPage->add("<input type=\"submit\" value=\"Create ".MetaModel::GetName($this->m_sClass)."\" />\n");
|
||||
$this->m_oPage->add("</div>\n");
|
||||
$this->m_oPage->add("</form>\n");
|
||||
@@ -201,35 +202,45 @@ $sJSHandlerCode
|
||||
}
|
||||
|
||||
// Now use the dependencies between the fields to order them
|
||||
while(count($aFields) > 0)
|
||||
// Start from the order of the 'details'
|
||||
$aList = MetaModel::GetZListItems($this->m_sClass, 'details');
|
||||
$index = 0;
|
||||
$aOrder = array();
|
||||
foreach($aFields as $sAttCode => $void)
|
||||
{
|
||||
$aCurrentStep = array();
|
||||
foreach($aFields as $sAttCode => $aDependencies)
|
||||
$aOrder[$sAttCode] = 999; // At the end of the list...
|
||||
}
|
||||
foreach($aList as $sAttCode)
|
||||
{
|
||||
if (array_key_exists($sAttCode, $aFields))
|
||||
{
|
||||
// All fields with no remaining dependencies can be entered at this
|
||||
// step of the wizard
|
||||
if (count($aDependencies) == 0)
|
||||
$aOrder[$sAttCode] = $index;
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
foreach($aFields as $sAttCode => $aDependencies)
|
||||
{
|
||||
// All fields with no remaining dependencies can be entered at this
|
||||
// step of the wizard
|
||||
if (count($aDependencies) > 0)
|
||||
{
|
||||
$iMaxPos = 0;
|
||||
// Remove this field from the dependencies of the other fields
|
||||
foreach($aDependencies as $sDependentAttCode => $void)
|
||||
{
|
||||
$aCurrentStep[] = $sAttCode;
|
||||
$aFieldsDone[$sAttCode] = '';
|
||||
unset($aFields[$sAttCode]);
|
||||
// Remove this field from the dependencies of the other fields
|
||||
foreach($aFields as $sUpdatedCode => $aDummy)
|
||||
{
|
||||
// remove the dependency
|
||||
unset($aFields[$sUpdatedCode][$sAttCode]);
|
||||
}
|
||||
// position the current field after the ones it depends on
|
||||
$iMaxPos = max($iMaxPos, 1+$aOrder[$sDependentAttCode]);
|
||||
}
|
||||
}
|
||||
if (count($aCurrentStep) == 0)
|
||||
{
|
||||
// This step of the wizard would contain NO field !
|
||||
echo "<strong>Error:</strong> Circular reference in the dependencies between the fields.";
|
||||
print_r($aFields);
|
||||
break;
|
||||
}
|
||||
$aWizardSteps['mandatory'][] = $aCurrentStep;
|
||||
}
|
||||
asort($aOrder);
|
||||
$aCurrentStep = array();
|
||||
foreach($aOrder as $sAttCode => $rank)
|
||||
{
|
||||
$aCurrentStep[] = $sAttCode;
|
||||
$aFieldsDone[$sAttCode] = '';
|
||||
}
|
||||
$aWizardSteps['mandatory'][] = $aCurrentStep;
|
||||
|
||||
|
||||
// Now computes the steps to fill the optional fields
|
||||
|
||||
@@ -16,9 +16,8 @@ class WizardHelper
|
||||
public function GetTargetObject($bReadUploadedFiles = false)
|
||||
{
|
||||
$oObj = MetaModel::NewObject($this->m_aData['m_sClass']);
|
||||
foreach($this->m_aData['m_aCurrentValues'] as $iIndex => $value)
|
||||
foreach($this->m_aData['m_oCurrentValues'] as $sAttCode => $value)
|
||||
{
|
||||
$sAttCode = array_search($iIndex, $this->m_aData['m_oFieldsMap']);
|
||||
// Because this is stored in a Javascript array, unused indexes
|
||||
// are filled with null values
|
||||
if ( ($sAttCode !== false) && ($value !== null))
|
||||
@@ -104,7 +103,6 @@ class WizardHelper
|
||||
// Protect against a request for a non existing field
|
||||
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode]))
|
||||
{
|
||||
$iIndex = $this->m_aData['m_oFieldsMap'][$sAttCode];
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->m_aData['m_sClass'], $sAttCode);
|
||||
if ($oAttDef->GetEditClass() == 'List')
|
||||
{
|
||||
@@ -124,13 +122,13 @@ class WizardHelper
|
||||
}
|
||||
$aData[] = $aRow;
|
||||
}
|
||||
$this->m_aData['m_aDefaultValue'][$iIndex] = json_encode($aData);
|
||||
$this->m_aData['m_oDefaultValue'][$sAttCode] = json_encode($aData);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal handling for all other scalar attributes
|
||||
$this->m_aData['m_aDefaultValue'][$iIndex] = $value;
|
||||
$this->m_aData['m_oDefaultValue'][$sAttCode] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,8 +143,7 @@ class WizardHelper
|
||||
// Protect against a request for a non existing field
|
||||
if (isset($this->m_aData['m_oFieldsMap'][$sAttCode]))
|
||||
{
|
||||
$iIndex = $this->m_aData['m_oFieldsMap'][$sAttCode];
|
||||
$this->m_aData['m_aAllowedValues'][$iIndex] = $sHtml;
|
||||
$this->m_aData['m_oAllowedValues'][$sAttCode] = $sHtml;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user