Implementation of bulk modify and bulk apply stimulus... to be tested !

SVN:trunk[1145]
This commit is contained in:
Denis Flaven
2011-03-23 16:22:35 +00:00
parent 9b50124513
commit bec8b57fe1
21 changed files with 1458 additions and 226 deletions

View File

@@ -76,7 +76,15 @@ interface iDisplay
abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
protected $m_iFormId; // The ID of the form used to edit the object (when in edition mode !)
static $iGlobalFormId = 1;
/**
* returns what will be the next ID for the forms
*/
public static function GetNextFormId()
{
return 1 + self::$iGlobalFormId;
}
public static function GetUIPage()
{
return '../pages/UI.php';
@@ -380,7 +388,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$aReasons = array();
$iSynchroFlags = $this->GetSynchroReplicaFlags($sAttCode, $aReasons);
$sSynchroIcon = '';
if ($iSynchroFlags & OPT_ATT_READONLY)
if ($iSynchroFlags & OPT_ATT_SLAVE)
{
$sSynchroIcon = "&nbsp;<img id=\"synchro_$iInputId\" src=\"../images/transp-lock.png\" style=\"vertical-align:middle\"/>";
$sTip = '';
@@ -391,7 +399,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
$oPage->add_ready_script("$('#synchro_$iInputId').qtip( { content: '$sTip', show: 'mouseover', hide: 'mouseout', style: { name: 'dark', tip: 'leftTop' }, position: { corner: { target: 'rightMiddle', tooltip: 'leftTop' }} } );");
}
$val['value'] .= $sSynchroIcon;
$val['comments'] = $sSynchroIcon;
// The field is visible, add it to the current column
$aDetails[$sTab][$sColIndex][] = $val;
$iInputId++;
@@ -555,7 +563,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
{
if (!$bSingleSelectMode)
{
$aAttribs['form::select'] = array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$iListId}', this.checked);\"></input>", 'description' => Dict::S('UI:SelectAllToggle+'));
$aAttribs['form::select'] = array('label' => "<input type=\"checkbox\" onClick=\"CheckAll('.selectList{$iListId}:not(:disabled)', this.checked);\"></input>", 'description' => Dict::S('UI:SelectAllToggle+'));
}
else
{
@@ -596,13 +604,21 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
}
if ($bSelectMode)
{
if ($bSingleSelectMode)
if (array_key_exists('selection_enabled', $aExtraParams) && isset($aExtraParams['selection_enabled'][$oObj->GetKey()]))
{
$aRow['form::select'] = "<input type=\"radio\" class=\"selectList{$iListId}\" name=\"selectObject\" value=\"".$oObj->GetKey()."\"></input>";
$sDisabled = ($aExtraParams['selection_enabled'][$oObj->GetKey()]) ? '' : ' disabled="disabled"';
}
else
{
$aRow['form::select'] = "<input type=\"checkBox\" class=\"selectList{$iListId}\" name=\"selectObject[]\" value=\"".$oObj->GetKey()."\"></input>";
$sDisabled = '';
}
if ($bSingleSelectMode)
{
$aRow['form::select'] = "<input type=\"radio\" $sDisabled class=\"selectList{$iListId}\" name=\"selectObject\" value=\"".$oObj->GetKey()."\"></input>";
}
else
{
$aRow['form::select'] = "<input type=\"checkBox\" $sDisabled class=\"selectList{$iListId}\" name=\"selectObject[]\" value=\"".$oObj->GetKey()."\"></input>";
}
}
foreach($aList as $sAttCode)
@@ -1238,6 +1254,7 @@ EOF
$sSeconds = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[s]{$sNameSuffix}\" value=\"{$aVal['seconds']}\" id=\"{$iId}_s\"/>";
$sHidden = "<input type=\"hidden\" id=\"{$iId}\" value=\"$value\"/>";
$sHTMLValue = Dict::Format('UI:DurationForm_Days_Hours_Minutes_Seconds', $sDays, $sHours, $sMinutes, $sSeconds).$sHidden."&nbsp;".$sValidationField;
$oPage->add_ready_script("$('#{$iId}').bind('update', function(evt, sFormId) { return ToggleDurationField('$iId'); });");
break;
case 'Password':
@@ -1304,6 +1321,7 @@ EOF
$iMaxComboLength = $oAttDef->GetMaximumComboLength();
$oWidget = new UIExtKeyWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $aAllowedValues, $value, $iId, $bMandatory, $sNameSuffix, $sFieldPrefix, $sFormPrefix);
$sHTMLValue = $oWidget->Display($oPage, $aArgs);
$sHTMLValue .= "<!-- iFlags: $iFlags bMandatory: $bMandatory -->\n";
break;
case 'String':
@@ -1362,14 +1380,15 @@ EOF
public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array())
{
static $iGlobalFormId = 1;
$iGlobalFormId++;
self::$iGlobalFormId++;
$sPrefix = '';
if (isset($aExtraParams['formPrefix']))
{
$sPrefix = $aExtraParams['formPrefix'];
}
$this->m_iFormId = $sPrefix.$iGlobalFormId;
$aFieldsComments = (isset($aExtraParams['fieldsComments'])) ? $aExtraParams['fieldsComments'] : array();
$this->m_iFormId = $sPrefix.self::$iGlobalFormId;
$sClass = get_class($this);
$oAppContext = new ApplicationContext();
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
@@ -1448,6 +1467,8 @@ EOF
foreach($aFields as $sAttCode)
{
$aVal = null;
$sComments = isset($aFieldsComments[$sAttCode]) ? $aFieldsComments[$sAttCode] : '&nbsp;';
$sInfos = '&nbsp;';
$iFlags = $this->GetAttributeFlags($sAttCode);
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ( (!$oAttDef->IsLinkSet()) && (($iFlags & OPT_ATT_HIDDEN) == 0))
@@ -1458,7 +1479,7 @@ EOF
{
// State attribute is always read-only from the UI
$sHTMLValue = $this->GetStateLabel();
$aVal = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue);
$aVal = array('label' => $oAttDef->GetLabel(), 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos);
}
else
{
@@ -1471,15 +1492,15 @@ EOF
}
else
{
if ($iFlags & OPT_ATT_READONLY)
if ($iFlags & (OPT_ATT_READONLY|OPT_ATT_SLAVE))
{
// Check if the attribute is not read-only becuase of a synchro...
$aReasons = array();
$iSynchroFlags = $this->GetSynchroReplicaFlags($sAttCode, $aReasons);
$sSynchroIcon = '';
if ($iSynchroFlags & OPT_ATT_READONLY)
if ($iFlags & OPT_ATT_SLAVE)
{
$iSynchroFlags = $this->GetSynchroReplicaFlags($sAttCode, $aReasons);
$sSynchroIcon = "&nbsp;<img id=\"synchro_$sInputId\" src=\"../images/transp-lock.png\" style=\"vertical-align:middle\"/>";
$sTip = '';
foreach($aReasons as $aRow)
@@ -1490,9 +1511,10 @@ EOF
}
// Attribute is read-only
$sHTMLValue = $this->GetAsHTML($sAttCode).$sSynchroIcon;
$sHTMLValue = $this->GetAsHTML($sAttCode);;
$sHTMLValue .= '<input type="hidden" id="'.$sInputId.'" name="attr_'.$sPrefix.$sAttCode.'" value="'.htmlentities($this->Get($sAttCode), ENT_QUOTES, 'UTF-8').'"/>';
$aFieldsMap[$sAttCode] = $sInputId;
$sComments = $sSynchroIcon;
}
else
{
@@ -1503,13 +1525,13 @@ EOF
$aFieldsMap[$sAttCode] = $sInputId;
}
$aVal = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => $sHTMLValue);
$aVal = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => $sHTMLValue, 'comments' => $sComments, 'infos' => $sInfos);
}
}
}
else
{
$aVal = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => $this->GetAsHTML($sAttCode));
$aVal = array('label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>', 'value' => $this->GetAsHTML($sAttCode), 'comments' => $sComments, 'infos' => $sInfos);
}
}
if ($aVal != null)
@@ -1548,22 +1570,48 @@ EOF
$oPage->add("<input type=\"hidden\" name=\"$sName\" value=\"$value\">\n");
}
$oPage->add($oAppContext->GetForForm());
// Custom operation for the form ?
if (isset($aExtraParams['custom_operation']))
{
$sOperation = $aExtraParams['custom_operation'];
}
else if ($iKey > 0)
{
$sOperation = 'apply_modify';
}
else
{
$sOperation = 'apply_new';
}
// Custom label for the apply button ?
if (isset($aExtraParams['custom_button']))
{
$sApplyButton = $aExtraParams['custom_button'];
}
else if ($iKey > 0)
{
$sApplyButton = Dict::S('UI:Button:Apply');
}
else
{
$sApplyButton = Dict::S('UI:Button:Create');
}
if ($iKey > 0)
{
// The object already exists in the database, it's modification
// The object already exists in the database, it's a modification
$oPage->add("<input type=\"hidden\" name=\"id\" value=\"$iKey\">\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_modify\">\n");
// $oPage->add("<button type=\"button\" id=\"btn_cancel_{$sPrefix}\" class=\"action\" onClick=\"BackToDetails('$sClass', $iKey)\"><span>".Dict::S('UI:Button:Cancel')."</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"{$sOperation}\">\n");
$oPage->add("<button type=\"button\" class=\"action cancel\"><span>".Dict::S('UI:Button:Cancel')."</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>".Dict::S('UI:Button:Apply')."</span></button>\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>{$sApplyButton}</span></button>\n");
}
else
{
// The object does not exist in the database it's a creation
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"apply_new\">\n");
// $oPage->add("<button type=\"button\" id=\"btn_cancel_{$sPrefix}\" class=\"action\" onClick=\"BackToDetails('$sClass', $iKey)\"><span>".Dict::S('UI:Button:Cancel')."</span></button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<input type=\"hidden\" name=\"operation\" value=\"$sOperation\">\n");
$oPage->add("<button type=\"button\" class=\"action cancel\">".Dict::S('UI:Button:Cancel')."</button>&nbsp;&nbsp;&nbsp;&nbsp;\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>".Dict::S('UI:Button:Create')."</span></button>\n");
$oPage->add("<button type=\"submit\" class=\"action\"><span>{$sApplyButton}</span></button>\n");
}
// Hook the cancel button via jQuery so that it can be unhooked easily as well if needed
$sDefaultUrl = '../pages/UI.php?operation=cancel';
@@ -1572,11 +1620,12 @@ EOF
$iFieldsCount = count($aFieldsMap);
$sJsonFieldsMap = json_encode($aFieldsMap);
$sState = $this->GetState();
$oPage->add_script(
<<<EOF
// Create the object once at the beginning of the page...
var oWizardHelper$sPrefix = new WizardHelper('$sClass', '$sPrefix');
var oWizardHelper$sPrefix = new WizardHelper('$sClass', '$sPrefix', '$sState');
oWizardHelper$sPrefix.SetFieldsMap($sJsonFieldsMap);
oWizardHelper$sPrefix.SetFieldsCount($iFieldsCount);
EOF
@@ -1917,11 +1966,14 @@ EOF
*/
public function UpdateObject($sFormPrefix = '')
{
$aErrors = array();
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
{
if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect())
{
$aLinks = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", '');
$aLinks = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
if (is_null($aLinks)) continue;
$sLinkedClass = $oAttDef->GetLinkedClass();
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
@@ -1965,10 +2017,18 @@ EOF
else if ($oAttDef->IsWritable())
{
$iFlags = $this->GetAttributeFlags($sAttCode);
if ($iFlags & (OPT_ATT_HIDDEN | OPT_ATT_READONLY))
if ( $iFlags & (OPT_ATT_HIDDEN | OPT_ATT_READONLY))
{
// Non-visible, or read-only attribute, do nothing
}
elseif($iFlags & OPT_ATT_SLAVE)
{
$value = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
if (!is_null($value) && ($value != $this->Get($sAttCode)))
{
$aErrors[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel());
}
}
elseif ($oAttDef->GetEditClass() == 'Document')
{
// There should be an uploaded file with the named attr_<attCode>
@@ -1993,14 +2053,9 @@ EOF
elseif ($oAttDef->GetEditClass() == 'Duration')
{
$rawValue = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
if (!is_array($rawValue))
{
$iValue = null;
}
else
{
$iValue = (((24*$rawValue['d'])+$rawValue['h'])*60 +$rawValue['m'])*60 + $rawValue['s'];
}
if (!is_array($rawValue)) continue;
$iValue = (((24*$rawValue['d'])+$rawValue['h'])*60 +$rawValue['m'])*60 + $rawValue['s'];
$this->Set($sAttCode, $iValue);
$previousValue = $this->Get($sAttCode);
if ($previousValue !== $iValue)
@@ -2023,6 +2078,7 @@ EOF
}
}
}
return $aErrors;
}
protected function DBInsertTracked_Internal($bDoNotReload = false)

View File

@@ -1092,8 +1092,48 @@ class MenuBlock extends DisplayBlock
// many objects in the set, possible actions are: new / modify all / delete all
$sUrl = utils::GetAbsoluteUrl();
if ($bIsModifyAllowed) { $aActions[] = array ('label' => Dict::S('UI:Menu:New'), 'url' => "../pages/$sUIPage?operation=new&class=$sClass&$sContext{$sDefault}"); }
//if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => 'Modify All...', 'url' => "../pages/$sUIPage?operation=modify_all&filter=$sFilter&$sContext"); }
if ($bIsBulkModifyAllowed) { $aActions[] = array ('label' => Dict::S('UI:Menu:ModifyAll'), 'url' => "../pages/$sUIPage?operation=select_for_modify_all&class=$sClass&filter=$sFilter&sContext"); }
if ($bIsBulkDeleteAllowed) { $aActions[] = array ('label' => Dict::S('UI:Menu:BulkDelete'), 'url' => "../pages/$sUIPage?operation=select_for_deletion&filter=$sFilter&$sContext"); }
// Stimuli
$aStates = MetaModel::EnumStates($sClass);
if (count($aStates) > 0)
{
// Life cycle actions may be available... if all objects are in the same state
$oSet->Rewind();
$aStates = array();
while($oObj = $oSet->Fetch())
{
$aStates[$oObj->GetState()] = $oObj->GetState();
}
$oSet->Rewind();
if (count($aStates) == 1)
{
// All objects are in the same state...
$sState = array_pop($aStates);
$aTransitions = Metamodel::EnumTransitions($sClass, $sState);
if (count($aTransitions))
{
$this->AddMenuSeparator($aActions);
$aStimuli = Metamodel::EnumStimuli($sClass);
foreach($aTransitions as $sStimulusCode => $aTransitionDef)
{
$oChecker = new StimulusChecker($this->m_oFilter, $sState, $sStimulusCode);
$iActionAllowed = (get_class($aStimuli[$sStimulusCode]) == 'StimulusUserAction') ? $oChecker->IsAllowed() : UR_ALLOWED_NO;
switch($iActionAllowed)
{
case UR_ALLOWED_YES:
case UR_ALLOWED_DEPENDS:
$aActions[] = array('label' => $aStimuli[$sStimulusCode]->GetLabel(), 'url' => "../pages/UI.php?operation=select_bulk_stimulus&stimulus=$sStimulusCode&state=$sState&class=$sClass&filter=$sFilter&$sContext");
break;
default:
// Do nothing
}
}
}
}
}
$this->AddMenuSeparator($aActions);
$aActions[] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=".$oSet->GetFilter()->__DescribeHTML()."&body=".urlencode("$sUrl?operation=search&filter=$sFilter&$sContext"));
$aActions[] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "../pages/$sUIPage?operation=search&filter=$sFilter&format=csv&$sContext");

View File

@@ -399,6 +399,21 @@ EOF
}
var oUserPreferences = $sUserPrefs;
// For disabling the CKEditor at init time when the corresponding textarea is disabled !
CKEDITOR.plugins.add( 'disabler',
{
init : function( editor )
{
editor.on( 'instanceReady', function(e)
{
e.removeListener();
$('#'+ editor.name).trigger('update');
});
}
});
EOF
);

View File

@@ -145,6 +145,7 @@ class UIExtKeyWidget
<<<EOF
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>";
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
EOF
);
@@ -168,20 +169,22 @@ EOF
// the input for the auto-complete
$sHTMLValue = "<input count=\"".count($this->aAllowedValues)."\" type=\"text\" id=\"label_$this->iId\" size=\"30\" maxlength=\"$iFieldSize\" value=\"$sDisplayValue\"/>&nbsp;";
$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;";
$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.Search();\"><img id=\"mini_search_{$this->iId}\" 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=\"{$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(
$sDialogTitle = addslashes($this->sTitle);
$oPage->add_ready_script(
<<<EOF
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(); } );
$('#label_$this->iId').result( function(event, data, formatted) { OnAutoComplete('{$this->iId}', event, data, formatted); } );
$('#ac_dlg_$this->iId').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, title: '{$this->sTitle}', resizeStop: oACWidget_{$this->iId}.UpdateSizes, close: oACWidget_{$this->iId}.OnClose });
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
$('#ac_dlg_$this->iId').dialog({ width: $(window).width()*0.8, height: $(window).height()*0.8, autoOpen: false, modal: true, title: '$sDialogTitle', resizeStop: oACWidget_{$this->iId}.UpdateSizes, close: oACWidget_{$this->iId}.OnClose });
EOF
);
@@ -190,7 +193,7 @@ EOF
}
if ($bCreate)
{
$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.CreateObject();\"><img style=\"border:0;vertical-align:middle;\" src=\"../images/mini_add.gif\" /></a>&nbsp;";
$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.CreateObject();\"><img id=\"mini_add_{$this->iId}\" style=\"border:0;vertical-align:middle;\" src=\"../images/mini_add.gif\" /></a>&nbsp;";
$oPage->add_at_the_end('<div id="ajax_'.$this->iId.'"></div>');
}
$sHTMLValue .= "<span id=\"v_{$this->iId}\"></span>";
@@ -259,11 +262,12 @@ EOF
*/
public function GetObjectCreationForm(WebPage $oPage)
{
$sDialogTitle = addslashes($this->sTitle);
$oPage->add('<div id="ac_create_'.$this->iId.'"><div class="wizContainer" style="vertical-align:top;"><div id="dcr_'.$this->iId.'">');
$oPage->add("<h1>".MetaModel::GetClassIcon($this->sTargetClass)."&nbsp;".Dict::Format('UI:CreationTitle_Class', MetaModel::GetName($this->sTargetClass))."</h1>\n");
cmdbAbstractObject::DisplayCreationForm($oPage, $this->sTargetClass, null, array(), array('formPrefix' => $this->iId, 'noRelations' => true));
$oPage->add('</div></div></div>');
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: $(window).width()*0.8, height: 'auto', autoOpen: false, modal: true, title: '$this->sTitle'});\n");
$oPage->add_ready_script("\$('#ac_create_$this->iId').dialog({ width: $(window).width()*0.8, height: 'auto', autoOpen: false, modal: true, title: '$sDialogTitle'});\n");
$oPage->add_ready_script("$('#dcr_{$this->iId} form').removeAttr('onsubmit');");
$oPage->add_ready_script("$('#dcr_{$this->iId} form').bind('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);");
}
@@ -274,17 +278,21 @@ EOF
public function DoCreateObject($oPage)
{
$oObj = MetaModel::NewObject($this->sTargetClass);
$oObj->UpdateObject($this->sFormPrefix.$this->iId);
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$sUserString = CMDBChange::GetCurrentUserName();
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$oObj->DBInsertTracked($oMyChange);
return array('name' => $oObj->GetName(), 'id' => $oObj->GetKey());
//return array('name' => 'test', 'id' => '42');
$aErrors = $oObj->UpdateObject($this->sFormPrefix.$this->iId);
if (count($aErrors) == 0)
{
$oMyChange = MetaModel::NewObject("CMDBChange");
$oMyChange->Set("date", time());
$sUserString = CMDBChange::GetCurrentUserName();
$oMyChange->Set("userinfo", $sUserString);
$iChangeId = $oMyChange->DBInsert();
$oObj->DBInsertTracked($oMyChange);
return array('name' => $oObj->GetName(), 'id' => $oObj->GetKey());
}
else
{
return array('name' => implode(' ', $aErrors), 'id' => 0);
}
}
}
?>

View File

@@ -61,14 +61,14 @@ 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=\"14\" cols=\"110\" id=\"$iId\">$sValue</textarea></td><td>$sValidationField</td></tr></table>";
$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>";
// Replace the text area with CKEditor
// To change the default settings of the editor,
// a) edit the file /js/ckeditor/config.js
// b) or override some of the configuration settings, using the second parameter of ckeditor()
$sLanguage = strtolower(trim(UserRights::GetUserLanguage()));
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, { language : '$sLanguage' , contentsLanguage : '$sLanguage' });"); // Transform $iId into a CKEdit
$oPage->add_ready_script("$('#$iId').ckeditor(function() { /* callback code */ }, { language : '$sLanguage' , contentsLanguage : '$sLanguage', extraPlugins: 'disabler' });"); // Transform $iId into a CKEdit
// Please read...
// ValidateCKEditField triggers a timer... calling itself indefinitely
@@ -78,7 +78,8 @@ class UIHTMLEditorWidget
// The most relevant solution would be to implement a plugin to CKEdit, and handle the internal events like: setData, insertHtml, insertElement, loadSnapshot, key, afterUndo, afterRedo
// Could also be bound to 'instanceReady.ckeditor'
$oPage->add_ready_script("$('#$iId').bind('validate', function(evt, sFormId) { return ValidateCKEditField('$iId', '', {$this->m_sMandatory}, sFormId, '') } );");
$oPage->add_ready_script("$('#$iId').bind('validate', function(evt, sFormId) { return ValidateCKEditField('$iId', '', {$this->m_sMandatory}, sFormId, '') } );\n");
$oPage->add_ready_script("$('#$iId').bind('update', function() { BlockField('cke_$iId', $('#$iId').attr('disabled')); } );\n");
return $sHtmlValue;
}

View File

@@ -57,13 +57,28 @@ class UIPasswordWidget
$sChangedValue = (($sPasswordValue != '*****') || ($sConfirmPasswordValue != '*****')) ? 1 : 0;
$sHtmlValue = '';
$sHtmlValue = '<input type="password" maxlength="255" name="attr_'.$sCode.'" id="'.$this->iId.'" value="'.htmlentities($sPasswordValue, ENT_QUOTES, 'UTF-8').'"/>&nbsp;<span class="form_validation" id="v_'.$this->iId.'"></span><br/>';
$sHtmlValue .= '<input type="password" maxlength="255" id="'.$this->iId.'_confirm" value="'.htmlentities($sConfirmPasswordValue, ENT_QUOTES, 'UTF-8').'" name="attr_'.$sCode.'_confirmed"/> '.Dict::S('UI:PasswordConfirm').' <input type="button" value="'.Dict::S('UI:Button:ResetPassword').'" onClick="ResetPwd(\''.$this->iId.'\');">';
$sHtmlValue .= '<input type="password" maxlength="255" id="'.$this->iId.'_confirm" value="'.htmlentities($sConfirmPasswordValue, ENT_QUOTES, 'UTF-8').'" name="attr_'.$sCode.'_confirmed"/> '.Dict::S('UI:PasswordConfirm').' <input id="'.$this->iId.'_reset" type="button" value="'.Dict::S('UI:Button:ResetPassword').'" onClick="ResetPwd(\''.$this->iId.'\');">';
$sHtmlValue .= '<input type="hidden" id="'.$this->iId.'_changed" name="attr_'.$sCode.'_changed" value="'.$sChangedValue.'"/>';
$oPage->add_ready_script("$('#$this->iId').bind('keyup change', function(evt) { return PasswordFieldChanged('$this->iId') } );"); // Bind to a custom event: validate
$oPage->add_ready_script("$('#$this->iId').bind('keyup change validate', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
$oPage->add_ready_script("$('#{$this->iId}_confirm').bind('keyup change', function(evt, sFormId) { return ValidatePasswordField('$this->iId', sFormId) } );"); // Bind to a custom event: validate
$oPage->add_ready_script("$('#{$this->iId}').bind('update', function(evt, sFormId)
{
if ($(this).attr('disabled'))
{
$('#{$this->iId}_confirm').attr('disabled', 'disabled');
$('#{$this->iId}_changed').attr('disabled', 'disabled');
$('#{$this->iId}_reset').attr('disabled', 'disabled');
}
else
{
$('#{$this->iId}_confirm').removeAttr('disabled');
$('#{$this->iId}_changed').removeAttr('disabled');
$('#{$this->iId}_reset').removeAttr('disabled');
}
}
);"); // Bind to a custom event: update to handle enabling/disabling
return $sHtmlValue;
}
}

View File

@@ -258,6 +258,9 @@ class WebPage
{
$sHtml .= "<td class=\"label\">".$aAttrib['label']."</td><td>".$aAttrib['value']."</td>\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";
}
$sHtml .= "</tbody>\n";

View File

@@ -121,6 +121,11 @@ class WizardHelper
}
}
}
if (isset($this->m_aData['m_sState']) && !empty($this->m_aData['m_sState']))
{
$oObj->Set(MetaModel::GetStateAttributeCode($this->m_aData['m_sClass']), $this->m_aData['m_sState']);
}
return $oObj;
}

View File

@@ -1543,7 +1543,7 @@ abstract class DBObject
{
if (($oSyncAttr->Get('attcode') == $sAttCode) && ($oSyncAttr->Get('update') == 1) && ($oSyncAttr->Get('update_policy') == 'master_locked'))
{
$iFlags |= OPT_ATT_READONLY;
$iFlags |= OPT_ATT_SLAVE;
$sUrl = $oSource->GetApplicationUrl($this, $oReplica);
$aReason[] = array('name' => $oSource->GetName(), 'description' => $oSource->Get('description'), 'url_application' => $sUrl);
}

View File

@@ -526,6 +526,109 @@ class DBObjectSet
}
return $aRelatedObjs;
}
/**
* Builds an object that contains the values that are common to all the objects
* in the set. If for a given attribute, objects in the set have various values
* then the resulting object will contain null for this value.
* @param $aValues Hash Output: the distribution of the values, in the set, for each attribute
* @return Object
*/
public function ComputeCommonObject(&$aValues)
{
$sClass = $this->GetClass();
$aList = MetaModel::FlattenZlist(MetaModel::GetZListItems($sClass, 'details'));
$aValues = array();
foreach($aList as $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef->IsScalar())
{
$aValues[$sAttCode] = array();
}
}
$this->Rewind();
while($oObj = $this->Fetch())
{
foreach($aList as $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
{
$currValue = $oObj->Get($sAttCode);
if (is_object($currValue)) continue; // Skip non scalar values...
if(!array_key_exists($currValue, $aValues[$sAttCode]))
{
$aValues[$sAttCode][$currValue] = array('count' => 1, 'display' => $oObj->GetAsHTML($sAttCode));
}
else
{
$aValues[$sAttCode][$currValue]['count']++;
}
}
}
}
foreach($aValues as $sAttCode => $aMultiValues)
{
if (count($aMultiValues) > 1)
{
uasort($aValues[$sAttCode], 'HashCountComparison');
}
}
// Now create an object that has values for the homogenous values only
$oCommonObj = new $sClass(); // @@ What if the class is abstract ?
$aComments = array();
$iFormId = cmdbAbstractObject::GetNextFormId(); // Identifier that prefixes all the form fields
$sReadyScript = '';
$aDependsOn = array();
$sFormPrefix = '2_';
foreach($aList as $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
if ($oAttDef->IsScalar() && $oAttDef->IsWritable())
{
if ($oAttDef->GetEditClass() == 'One Way Password')
{
$oCommonObj->Set($sAttCode, null);
}
else
{
$iCount = count($aValues[$sAttCode]);
if ($iCount == 1)
{
// Homogenous value
reset($aValues[$sAttCode]);
$aKeys = array_keys($aValues[$sAttCode]);
$currValue = $aKeys[0]; // The only value is the first key
$oCommonObj->Set($sAttCode, $currValue);
}
else
{
// Non-homogenous value
$oCommonObj->Set($sAttCode, null);
}
}
}
}
$this->Rewind();
return $oCommonObj;
}
}
/**
* Helper function to perform a custom sort of a hash array
*/
function HashCountComparison($a, $b) // Sort descending on 'count'
{
if ($a['count'] == $b['count'])
{
return 0;
}
return ($a['count'] > $b['count']) ? -1 : 1;
}
?>

View File

@@ -98,6 +98,13 @@ define('OPT_ATT_MUSTCHANGE', 8);
* @package iTopORM
*/
define('OPT_ATT_MUSTPROMPT', 16);
/**
* Specifies that the attribute is in 'slave' mode compared to one data exchange task:
* it should not be edited inside iTop anymore
*
* @package iTopORM
*/
define('OPT_ATT_SLAVE', 32);
/**
* DB Engine -should be moved into CMDBSource
@@ -3542,9 +3549,13 @@ abstract class MetaModel
// Note: load the dictionary as soon as possible, because it might be
// needed when some error occur
foreach (self::$m_oConfig->GetDictionaries() as $sModule => $sToInclude)
if (!Dict::InCache())
{
self::Plugin($sConfigFile, 'dictionaries', $sToInclude);
foreach (self::$m_oConfig->GetDictionaries() as $sModule => $sToInclude)
{
self::Plugin($sConfigFile, 'dictionaries', $sToInclude);
}
Dict::InitCache();
}
// Set the language... after the dictionaries have been loaded!
Dict::SetDefaultLanguage(self::$m_oConfig->GetDefaultLanguage());

View File

@@ -816,4 +816,169 @@ class UserRights
}
}
/**
* Helper class to get the number/list of items for which a given action is allowed/possible
*/
class ActionChecker
{
var $oFilter;
var $iActionCode;
var $iAllowedCount = null;
var $aAllowedIDs = null;
public function __construct(DBObjectSearch $oFilter, $iActionCode)
{
$this->oFilter = $oFilter;
$this->iActionCode = $iActionCode;
$this->iAllowedCount = null;
$this->aAllowedIDs = null;
}
/**
* returns the number of objects for which the action is allowed
* @return integer The number of "allowed" objects 0..N
*/
public function GetAllowedCount()
{
if ($this->iAllowedCount == null) $this->CheckObjects();
return $this->iAllowedCount;
}
/**
* If IsAllowed returned UR_ALLOWED_DEPENDS, this methods returns
* an array of ObjKey => Status (true|false)
* @return array
*/
public function GetAllowedIDs()
{
if ($this->aAllowedIDs == null) $this->IsAllowed();
return $this->aAllowedIDs;
}
/**
* Check if the speficied stimulus is allowed for the set of objects
* @return UR_ALLOWED_YES, UR_ALLOWED_NO or UR_ALLOWED_DEPENDS
*/
public function IsAllowed()
{
$sClass = $this->oFilter->GetClass();
$oSet = new DBObjectSet($this->oFilter);
$iActionAllowed = UserRights::IsActionAllowed($sClass, $oSet, $this->iActionCode);
if ($iActionAllowed == UR_ALLOWED_DEPENDS)
{
// Check for each object if the action is allowed or not
$this->aAllowedIDs = array();
$oSet->Rewind();
$this->iAllowedCount = 0;
while($oObj = $oSet->Fetch())
{
$oObjSet = DBObjectSet::FromArray($sClass, array($oObj));
if (UserRights::IsActionAllowed($sClass, $this->iActionCode, $oObjSet) == UR_ALLOWED_NO)
{
$this->aAllowedIDs[$oObj->GetKey()] = false;
}
else
{
// Assume UR_ALLOWED_YES, since there is just one object !
$this->aAllowedIDs[$oObj->GetKey()] = true;
$this->iAllowedCount++;
}
}
}
else if ($iActionAllowed == UR_ALLOWED_YES)
{
$this->iAllowedCount = $oSet->Count();
$this->aAllowedIDs = array(); // Optimization: not filled when Ok for all objects
}
else // UR_ALLOWED_NO
{
$this->iAllowedCount = 0;
$this->aAllowedIDs = array();
}
return $iActionAllowed;
}
}
/**
* Helper class to get the number/list of items for which a given stimulus can be applied (allowed & possible)
*/
class StimulusChecker extends ActionChecker
{
var $sState = null;
public function __construct(DBObjectSearch $oFilter, $sState, $iStimulusCode)
{
parent::__construct($oFilter, $iStimulusCode);
$this->sState = $sState;
}
/**
* Check if the speficied stimulus is allowed for the set of objects
* @return UR_ALLOWED_YES, UR_ALLOWED_NO or UR_ALLOWED_DEPENDS
*/
public function IsAllowed()
{
$sClass = $this->oFilter->GetClass();
$oSet = new DBObjectSet($this->oFilter);
$iActionAllowed = UserRights::IsStimulusAllowed($sClass, $oSet, $this->iActionCode);
if ($iActionAllowed == UR_ALLOWED_NO)
{
$this->iAllowedCount = 0;
$this->aAllowedIDs = array();
}
else // Even if UR_ALLOWED_YES, we need to check if each object is in the appropriate state
{
// Hmmm, may not be needed right now because we limit the "multiple" action to object in
// the same state... may be useful later on if we want to extend this behavior...
// Check for each object if the action is allowed or not
$this->aAllowedIDs = array();
$oSet->Rewind();
$iAllowedCount = 0;
$iActionAllowed = UR_ALLOWED_DEPENDS;
while($oObj = $oSet->Fetch())
{
$aTransitions = $oObj->EnumTransitions();
if (array_key_exists($this->iActionCode, $aTransitions))
{
// Temporary optimization possible: since the current implementation
// of IsActionAllowed does not perform a 'per instance' check, we could
// skip this second validation phase and assume it would return UR_ALLOWED_YES
$oObjSet = DBObjectSet::FromArray($sClass, array($oObj));
if (UserRights::IsActionAllowed($sClass, $this->iActionCode, $oObjSet) == UR_ALLOWED_NO)
{
$this->aAllowedIDs[$oObj->GetKey()] = false;
}
else
{
// Assume UR_ALLOWED_YES, since there is just one object !
$this->aAllowedIDs[$oObj->GetKey()] = true;
$this->iState = $oObj->GetState();
$this->iAllowedCount++;
}
}
else
{
$this->aAllowedIDs[$oObj->GetKey()] = false;
}
}
}
if ($this->iAllowedCount == $oSet->Count())
{
$iActionAllowed = UR_ALLOWED_YES;
}
if ($this->iAllowedCount == 0)
{
$iActionAllowed = UR_ALLOWED_NO;
}
return $iActionAllowed;
}
public function GetState()
{
return $this->iState;
}
}
?>

View File

@@ -126,9 +126,9 @@ th.headerSortDown {
td {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: 8pt;
font-size: 12px;
color:#696969;
background-color: #ffffff;
nobackground-color: #ffffff;
padding: 0px;
}
@@ -142,7 +142,7 @@ td.label {
font-family: Tahoma, Verdana, Arial, Helvetica;
font-size: 12px;
color: #000000;
background-color:#f6f6f6;
nobackground-color:#f6f6f6;
padding: 0.25em;
font-weight:bold;
}
@@ -938,3 +938,29 @@ span.form_validation {
vertical-align:middle;
text-align:center;
}
.mono_value {
display: inline-block;
background-color: #3c3;
color: #fff;
font-weight:bold;
padding: 3px;
padding-left: 5px;
padding-right: 5px;
margin-left:3px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
.multi_values {
display: inline-block;
background-color: #c33;
color: #fff;
font-weight:bold;
padding: 3px;
padding-left: 5px;
padding-right: 5px;
margin-left:3px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}

View File

@@ -885,5 +885,26 @@ When associated with a trigger, each action is given an "order" number, specifyi
'Portal:Attachment_No_To_Ticket_Name' => 'Attachment #%1$d to %2$s (%3$s)',
'Enum:Undefined' => 'Undefined',
'UI:DurationForm_Days_Hours_Minutes_Seconds' => '%1$s Days %2$s Hours %3$s Minutes %4$s Seconds',
'UI:ModifyAllPageTitle' => 'Modify All',
'UI:Modify_N_ObjectsOf_Class' => 'Modifying %1$d objects of class %2$s',
'UI:Modify_M_ObjectsOf_Class_OutOf_N' => 'Modifying %1$d objects of class %2$s out of %3$d',
'UI:Menu:ModifyAll' => 'Modify...',
'UI:Button:ModifyAll' => 'Modify All',
'UI:Button:PreviewModifications' => 'Preview Modifications >>',
'UI:ModifiedObject' => 'Object Modified',
'UI:BulkModifyStatus' => 'Operation',
'UI:BulkModifyStatus+' => 'Status of the operation',
'UI:BulkModifyErrors' => 'Errors (if any)',
'UI:BulkModifyErrors+' => 'Errors preventing the modification',
'UI:BulkModifyStatusOk' => 'Ok',
'UI:BulkModifyStatusError' => 'Error',
'UI:BulkModifyStatusModified' => 'Modified',
'UI:BulkModifyStatusSkipped' => 'Skipped',
'UI:BulkModify_Count_DistinctValues' => '%1$d distinct values:',
'UI:BulkModify:Value_Exists_N_Times' => '%1$s, %2$d time(s)',
'UI:BulkModify:N_MoreValues' => '%1$d more values...',
'UI:AttemptingToSetAReadOnlyAttribute_Name' => 'Attempting to set the read-only field: %1$s',
'UI:FailedToApplyStimuli' => 'The action has failed.',
'UI:StimulusModify_N_ObjectsOf_Class' => '%1$s: Modifying %2$d objects of class %3$s',
));
?>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 406 B

View File

@@ -45,6 +45,7 @@ function ExtKeyWidget(id, sClass, sAttCode, sSuffix, bSelectMode, oWizHelper)
this.Search = function()
{
if($('#'+me.id).attr('disabled')) return; // Disabled, do nothing
$('#ac_dlg_'+me.id).dialog('open');
this.UpdateSizes();
this.UpdateButtons();
@@ -189,6 +190,7 @@ function ExtKeyWidget(id, sClass, sAttCode, sSuffix, bSelectMode, oWizHelper)
this.CreateObject = function(oWizHelper)
{
if($('#'+me.id).attr('disabled')) return; // Disabled, do nothing
// Query the server to get the form to create a target object
if (me.bSelectMode)
{
@@ -309,4 +311,23 @@ function ExtKeyWidget(id, sClass, sAttCode, sSuffix, bSelectMode, oWizHelper)
}
return false; // do NOT submit the form
}
this.Update = function()
{
if ($('#'+me.id).attr('disabled'))
{
$('#v_'+me.id).html('');
$('#label_'+me.id).attr('disabled', 'disabled');
$('#label_'+me.id).css({'background': 'transparent'});
$('#mini_add_'+me.id).hide();
$('#mini_search_'+me.id).hide();
}
else
{
$('#label_'+me.id).attr('disabled', '');
$('#label_'+me.id).css({'background': '#fff url(../images/ac-background.gif) no-repeat right'});
$('#mini_add_'+me.id).show();
$('#mini_search_'+me.id).show();
}
}
}

View File

@@ -174,26 +174,33 @@ function ReportFieldValidationStatus(sFieldId, sFormId, bValid)
function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
{
var bValid = true;
var currentVal = $('#'+sFieldId).val();
if ($('#'+sFieldId).attr('disabled'))
{
bValid = true; // disabled fields are not checked
}
else
{
var currentVal = $('#'+sFieldId).val();
if (currentVal == '$$NULL$$') // Convention to indicate a non-valid value since it may have to be passed as text
{
bValid = false;
}
else if (bMandatory && (currentVal == nullValue))
{
bValid = false;
}
else if (currentVal == nullValue)
{
// An empty field is Ok...
bValid = true;
}
else if (sPattern != '')
{
re = new RegExp(sPattern);
//console.log('Validating field: '+sFieldId + ' current value: '+currentVal + ' pattern: '+sPattern );
bValid = re.test(currentVal);
if (currentVal == '$$NULL$$') // Convention to indicate a non-valid value since it may have to be passed as text
{
bValid = false;
}
else if (bMandatory && (currentVal == nullValue))
{
bValid = false;
}
else if (currentVal == nullValue)
{
// An empty field is Ok...
bValid = true;
}
else if (sPattern != '')
{
re = new RegExp(sPattern);
//console.log('Validating field: '+sFieldId + ' current value: '+currentVal + ' pattern: '+sPattern );
bValid = re.test(currentVal);
}
}
ReportFieldValidationStatus(sFieldId, sFormId, bValid);
//console.log('Form: '+sFormId+' Validating field: '+sFieldId + ' current value: '+currentVal+' pattern: '+sPattern+' result: '+bValid );

View File

@@ -212,3 +212,75 @@ function CheckAll(sSelector, bValue)
this.checked = value;
});
}
/**
* Toggle (enabled/disabled) the specified field of a form
*/
function ToogleField(value, field_id)
{
if (value)
{
$('#'+field_id).removeAttr('disabled');
}
else
{
$('#'+field_id).attr('disabled', 'disabled');
}
$('#'+field_id).trigger('update');
$('#'+field_id).trigger('validate');
}
/**
* For the fields that cannot be visually disabled, they can be blocked
* @return
*/
function BlockField(field_id, bBlocked)
{
if (bBlocked)
{
$('#'+field_id).block({ message: ' ** disabled ** '});
}
else
{
$('#'+field_id).unblock();
}
}
/**
* Updates (enables/disables) a "duration" field
*/
function ToggleDurationField(field_id)
{
// Toggle all the subfields that compose the "duration" input
aSubFields = new Array('d', 'h', 'm', 's');
if ($('#'+field_id).attr('disabled'))
{
for(var i=0; i<aSubFields.length; i++)
{
$('#'+field_id+'_'+aSubFields[i]).attr('disabled', 'disabled');
}
}
else
{
for(var i=0; i<aSubFields.length; i++)
{
$('#'+field_id+'_'+aSubFields[i]).removeAttr('disabled');
}
}
}
/**
* PropagateCheckBox
*/
function PropagateCheckBox(bCurrValue, aFieldsList, bCheck)
{
if (bCurrValue == bCheck)
{
for(var i=0;i<aFieldsList.length;i++)
{
$('#enable_'+aFieldsList[i]).attr('checked', bCheck);
ToogleField(bCheck, aFieldsList[i]);
}
}
}

View File

@@ -17,7 +17,7 @@ if (!Array.prototype.indexOf) // Emulation of the indexOf function for IE and ol
};
}
function WizardHelper(sClass, sFormPrefix)
function WizardHelper(sClass, sFormPrefix, sState)
{
this.m_oData = { 'm_sClass' : '',
'm_oFieldsMap': {},
@@ -27,7 +27,8 @@ function WizardHelper(sClass, sFormPrefix)
'm_oDefaultValue': {},
'm_oAllowedValues': {},
'm_iFieldsCount' : 0,
'm_sFormPrefix' : sFormPrefix
'm_sFormPrefix' : sFormPrefix,
'm_sState': sState
};
this.m_oData.m_sClass = sClass;
@@ -92,10 +93,16 @@ function WizardHelper(sClass, sFormPrefix)
// Set the full HTML for the input field
for(i=0; i<this.m_oData.m_aAllowedValuesRequested.length; i++)
{
sAttCode = this.m_oData.m_aAllowedValuesRequested[i];
sFieldId = this.m_oData.m_oFieldsMap[sAttCode];
var sAttCode = this.m_oData.m_aAllowedValuesRequested[i];
var sFieldId = this.m_oData.m_oFieldsMap[sAttCode];
var bDisabled = $('#'+sFieldId).attr('disabled');
//console.log('Setting #field_'+sFieldId+' to: '+this.m_oData.m_oAllowedValues[sAttCode]);
$('#field_'+sFieldId).html(this.m_oData.m_oAllowedValues[sAttCode]);
if (bDisabled)
{
$('#'+sFieldId).attr('disabled', 'disabled');
//$('#'+sFieldId).trigger('update'); // Propagate the disable
}
aRefreshed.push(sFieldId);
}
// Set the actual value of the input
@@ -113,7 +120,7 @@ function WizardHelper(sClass, sFormPrefix)
// For each "refreshed" field, asynchronously trigger a change in case there are dependent fields to update
for(i=0; i<aRefreshed.length; i++)
{
var sString = "$('#"+aRefreshed[i]+"').trigger('change');"
var sString = "$('#"+aRefreshed[i]+"').trigger('change').trigger('update');"
window.setTimeout(sString, 1); // Synchronous 'trigger' does nothing, call it asynchronously
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -274,7 +274,7 @@ function RequestCreationForm($oP, $oUserOrg)
$sJsonFieldsMap = json_encode($aFieldsMap);
$oP->add_ready_script(
<<<EOF
// Create the object once at the beginning of the page...
// Create the object once at the beginning of the page... no state specified => new
var oWizardHelper = new WizardHelper('UserRequest', '');
oWizardHelper.SetFieldsMap($sJsonFieldsMap);
oWizardHelper.SetFieldsCount($iFieldsCount);