Sidebar

Using iTop

Creating your iTop

iTop Customization

"How to" examples
DataModel

User Interface

Automation & Ticket management

Portal Customization

Adding 2 buttons to the display of sub-objects so you can navigate between them

Configuration

Navigation between objects can be enabled in iTop.

For each class you can only define a single navigation rule:

  • code optional must be a valid scalar attribute code for the class. It defines the group in which the navigation will be proposed, all objects having the same value as the displayed object for this field.
  • filter optional allow to reduce the objects on which we will navigate, for example reducing the list to the active one only.
    • code mandatory attribute code
    • operator optional default: = egal. >,>=, <, , != are supported
    • value optional default: '' empty string
  • order optional default: id. It's a scalar attribute code of the class. It defines the order in which you will navigate on the objects. For now it supposes that the values are unique on that field, duplicates are ignored/skipped.
Configuration
$MySettings = array(
        // shortcut_actions: Actions that are available as direct buttons next to the "Actions" menu
        //    default: 'UI:Menu:Modify,UI:Menu:New'
        'shortcut_actions' => '_previous_object,_next_object,UI:Menu:Modify,UI:Menu:New',
...
 
$MyModuleSettings = array(
   'combodo-object-navigation' => array(
       'classes' => array(
            'UserRequest' => array(  // Must be a valid class name
                'code' => 'org_id',  // Must be a code attribute of the class
                'filter'=> array('code'=>'status','value'=>'closed','operator'=>'!='),
            ),
            'WorkOrder' => array(
                'code' => 'ticket_id',
                'filter'=> array('code'=>'status','value'=>'closed','operator'=>'!='),
                'order' => 'start_date',
            ),
            'Team' => array(
                'code' => 'org_id',
                'filter'=> array('code'=>'status','value'=>'active'),
                'order'=>'name',
            ),
            'Person' => array(
                'code' => 'org_id',
                'filter'=> array('code'=>'status','value'=>'active'),
                'order'=>'name',
            ),
        )
    );

Extension code

main.php
class ObjectNavigationMenuExtension implements iPopupMenuExtension
{
    // Classes for which we want a navigation, and for each the attributecode which must be fixed (identical to current object)
    static public function GetConfig()
    {
        return MetaModel::GetModuleSetting('combodo-object-navigation', 'classes', array());
    }
 
  public static function EnumItems($iMenuId, $param)
  {
    $aResult = array();
    $aClassCode = static::GetConfig();
    switch($iMenuId) 
    {
        case iPopupMenuExtension::MENU_OBJDETAILS_ACTIONS: // Console only
 
        $sClass = get_class($param);
        if (array_key_exists($sClass, $aClassCode)) {
            $sAttCode = $aClassCode[$sClass]['code'];
            $sOrder = array_key_exists('order', $aClassCode[$sClass]) ? $aClassCode[$sClass]['order'] :'id';
            $sOrderValue = ($sOrder === 'id') ? $param->GetKey() : $param->Get($sOrder);
            $bFilter = false;
            if (array_key_exists('filter', $aClassCode[$sClass])) {
                $sFilterCode = array_key_exists('code', $aClassCode[$sClass]['filter']) ? $aClassCode[$sClass]['filter']['code'] : '';
                $sFilterValue = array_key_exists('value', $aClassCode[$sClass]['filter']) ? $aClassCode[$sClass]['filter']['value'] : '';
                $sFilterOperator = array_key_exists('operator', $aClassCode[$sClass]['filter']) ? $aClassCode[$sClass]['filter']['operator'] : '=';
                $bFilter = MetaModel::IsValidAttCode($sClass, $sFilterCode);
            }
 
            foreach ( ['>','<'] AS $sOperator) {
                $bAsc = ($sOperator === '>') ? true : false;
                $oSearch = new DBObjectSearch($sClass);
                if (MetaModel::IsValidAttCode($sClass, $sAttCode))
                    $oSearch->AddCondition($sAttCode, $param->Get($sAttCode), '=');
                if (($sOrder === 'id') || MetaModel::IsValidAttCode($sClass, $sOrder))
                    $oSearch->AddCondition($sOrder, $sOrderValue, $sOperator);
                if ($bFilter)
                    $oSearch->AddCondition($sFilterCode, $sFilterValue, $sFilterOperator);
                $oSet = new DBObjectSet($oSearch, array($sOrder => $bAsc),[],null,3);
                // $oSet->OptimizeColumnLoad(array($sClass => array('id')));
                $oObj = $oSet->Fetch();
                if (is_object($oObj)) {
                    if ($sOperator === '>') {
                        $oItem = new URLButtonItem(
                            '_next_object',
                            'Next',
                            utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class='.get_class($oObj).'&id='.$oObj->GetKey(),
                            '_top'
                        );
                        $oItem->SetIconClass('fas fa-caret-right');
                        $oItem->SetTooltip("Switch to the next logical object");
                    } elseif ($sOperator === '<') {
                        $oItem = new URLButtonItem(
                            '_previous_object',
                            'Previous',
                            utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class='.get_class($oObj).'&id='.$oObj->GetKey(),
                            '_top'
                        );
                        $oItem->SetIconClass('fas fa-caret-left');
                        $oItem->SetTooltip("Switch to the previous logical object");
                    }
                    $aResult[] = $oItem;
                }
            }
        }
        break;
    }
    return $aResult;
  }
}
latest/customization/nextobject.txt · Last modified: 2024/06/20 17:28 (external edit)
Back to top
Contact us