mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Implementation of bulk modify and bulk apply stimulus... to be tested !
SVN:trunk[1145]
This commit is contained in:
@@ -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 = " <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." ".$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] : ' ';
|
||||
$sInfos = ' ';
|
||||
$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 = " <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> \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> \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> \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> \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
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
|
||||
@@ -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,12 +169,13 @@ 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\"/> ";
|
||||
$sHTMLValue .= "<a class=\"no-arrow\" href=\"javascript:oACWidget_{$this->iId}.Search();\"><img style=\"border:0;vertical-align:middle;\" src=\"../images/mini_search.gif\" /></a> ";
|
||||
$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> ";
|
||||
|
||||
// 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
|
||||
$sDialogTitle = addslashes($this->sTitle);
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sClass}', '{$this->sAttCode}', '{$this->sNameSuffix}', $sSelectMode, $sWizHelper);
|
||||
@@ -181,7 +183,8 @@ EOF
|
||||
$('#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> ";
|
||||
$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> ";
|
||||
$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)." ".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);
|
||||
$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());
|
||||
|
||||
//return array('name' => 'test', 'id' => '42');
|
||||
}
|
||||
else
|
||||
{
|
||||
return array('name' => implode(' ', $aErrors), 'id' => 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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').'"/> <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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +258,9 @@ class WebPage
|
||||
{
|
||||
$sHtml .= "<td class=\"label\">".$aAttrib['label']."</td><td>".$aAttrib['value']."</td>\n";
|
||||
}
|
||||
$sComment = (isset($aAttrib['comments'])) ? $aAttrib['comments'] : ' ';
|
||||
$sInfo = (isset($aAttrib['infos'])) ? $aAttrib['infos'] : ' ';
|
||||
$sHtml .= "<td>$sComment</td><td>$sInfo</td>\n";
|
||||
$sHtml .= "</tr>\n";
|
||||
}
|
||||
$sHtml .= "</tbody>\n";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -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,10 +3549,14 @@ abstract class MetaModel
|
||||
|
||||
// Note: load the dictionary as soon as possible, because it might be
|
||||
// needed when some error occur
|
||||
if (!Dict::InCache())
|
||||
{
|
||||
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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 |
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,6 +174,12 @@ function ReportFieldValidationStatus(sFieldId, sFormId, bValid)
|
||||
function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
||||
{
|
||||
var bValid = true;
|
||||
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
|
||||
@@ -195,6 +201,7 @@ function ValidateField(sFieldId, sPattern, bMandatory, sFormId, nullValue)
|
||||
//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 );
|
||||
return true; // Do not stop propagation ??
|
||||
|
||||
72
js/utils.js
72
js/utils.js
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
934
pages/UI.php
934
pages/UI.php
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user