Sidebar

Using iTop

Creating your iTop

iTop Customization

"How to" examples
DataModel

User Interface

Automation & Ticket management

Portal Customization

Enrich display of an object

Prerequisite: You must be familiar with the Syntax used in Tutorials and have already created an extension.

learning:
Add information to the display of an object
level:
Intermediate
domains:
PHP, Presentation
methods:
DisplayBareRelations, SetCurrentTab, IsValidClass, GetKey, FromOQL, GetFilter, DisplayBlock::Display
min version:
2.1.0

🚧 Add screenshots of the examples result. Add an explanation to present the various examples, and what they bring.

Email members of a team

In this example, we will add a feature to an existing tab of an object details. We want to offer a mean to directly open a new email form in your favorite email client, with the team members already added in TO field.

We will just add in the tab displaying the team members, a mailto html link with the list of email addresses to use. The function which deals with displaying the relations tabs, when displaying a particular Object, is DisplayBareRelations()

class:Team
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
  // We call the parent class otherwise all relations tab will be missing
  parent::DisplayBareRelations($oPage, $bEditMode);
  // If your new behavior should be limited to the read mode (or not)
  if (!$bEditMode)
  {
    // We assume the Team class as a 'persons_list' attribute
    $oToNotify = $this->Get('persons_list');
    $aMailList = array();
    while ($oContact = $oToNotify->Fetch()) {
      $aMailList[] = $oContact->Get('email');
    }
    $sMailList = implode(', ', $aMailList);
    if ($sMailList != '')
    { // The oPage object contains multiple tabs
      // We want to put our link on a particular tab known by its label
      $sTabName = $oPage->FindTab('/^' . Dict::S('Class:Team/Attribute:persons_list') . '/');
      // Set that Tab as the current one
      // If no Tab with that name exists, it creates a new one after the current tab
      $oPage->SetCurrentTab($sTabName);
      // Add an hyperlink at the end of that tab
      $sLink = "<br>&nbsp;<a href=\"mailto:?to={$sMailList}\">Open mailer</a>";
      // As when writing on an oPage, it writes on the current tab
      $oPage->Add($sLink);
    }
  }
}
If you want to distribute your extension, then you should use those other methods:

Display KnownErrors applicable to a Ticket

In this example, we will add a tab to the UserRequest display. In this tab, we will display related objects, but with a relation more complex than just a LinkedSet attribute.
The Known Errors are not directly linked to a UserRequest in iTop default Datamodel, but they are linked to FunctionalCI and FunctionalCI are linked to Ticket, so following those two relationships, we can propose on a UserRequest the Known Errors which might be applicable to that ticket.

As in the above example, we will just write a PHP method to enrich the display of the UserRequest class.

class:UserRequest
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
   // Mandatory, to get the other tabs displayed as well
   parent::DisplayBareRelations($oPage, $bEditMode);
   // If the UserRequest is in Read mode 
   // and the KnownError option has been selected at iTop setup
   if ((!$bEditMode) && (MetaModel::IsValidClass('KnownError')))
   {
      //Search for known errors related to FunctionalCI
      // ...linked to current UserRequest
      $iTicketID = $this->GetKey();
      // We create a Search (definition) with an OQL
      // Note {$iTicketID} in the OQL will be replaced by the true value
      $oSearch = DBObjectSearch::FromOQL("
         SELECT KnownError AS ke 
         JOIN lnkErrorToFunctionalCI AS l1 ON l1.error_id=ke.id 
         JOIN FunctionalCI AS ci ON l1.functionalci_id=ci.id 
         JOIN lnkFunctionalCIToTicket AS l2 ON l2.functionalci_id=ci.id 
         WHERE l2.ticket_id={$iTicketID}");
      // We get a set of Known Error objects, using the above Search
      $oKnownErrorSet = new CMDBObjectSet($oSearch);
      // Now that we have the Set we can count them
      $iNumberKE = $oKnownErrorSet->count();
      // Here we have decided to always create a new Known Error tab
      // but you could decide to display the tab only if there are some Known Errors
      if ($iNumberKE > 0)
      {  // here we use the standard iTop way to display tab with data inside
         $oPage->SetCurrentTab(Dict::S('Class:UserRequest:KnownErrorList') . " ({$iNumberKE})");
      } else {   // or without data inside with no brackets and no count
         $oPage->SetCurrentTab(Dict::S('Class:UserRequest:KnownErrorList'));
      }
      // We create a Block made of the Known Error in a 'list' mode
      // The Block just need a DBObjectSearch and not the Set itself
      // GetFilter() retrieve that Search from the Set
      $oBlock = new DisplayBlock($oKnownErrorSet->GetFilter(), 'list', false);
      // 'menu' says if the list will offer a menu
      // 'display_limit' says if we display in page mode or all objects at once
      $aExtraParam = array('menu' => true, 'display_limit' => false);
      // Display the block in the page with a Title (optional), and extra params
      $oBlock->Display($oPage, Dict::S('Class:UserRequest:KnownErrorList'), $aExtraParam);
   }
}
You could use that same method, to display a filtered view of a simple relation. For example, on the Team class, display the Open Tickets assigned to that team. If you do it with an AttributeLinkedSetIndirect in 2.7.X and before, the list cannot be filtered and can slow down performance.
Since 2.6.0, this can be done with an AttributeDashboard

Questions & Answers

Question: My object is not fully displayed, relations tabs are missing?
Answer: Are you always calling parent::DisplayBareRelations($oPage, $bEditMode); in your method?

Question: Tab title is Class:UserRequest:KnownErrorList, how can I fix it?
Answer: You must define a dictionary entry for Class:UserRequest:KnownErrorList

Copy data in clipboard

This example uses a Javascript library included in iTop starting from 2.7.0: clipboardjs

🚧 Rough example, need more work…

class:Organization
function DisplayBareRelations(WebPage $oPage, $bEditMode = false)
{
  parent::DisplayBareRelations($oPage, $bEditMode);
  if ((!$bEditMode)
  {
    $oPage->SetCurrentTab("Authorized users ($iCount)");
    $oPage->table($aDisplayConfig, $aDisplayData);
    $oSearch = DBObjectSearch::FromOQL("SELECT Organization WHERE (id=:org_id OR managed_by_id=:org_id)");
    $oSet = new DBObjectSet($oSearch, array('name' => true), array('org_id' => $this->GetKey()));
    $sOrgs ='';
    while ($aRow = $oSet->FetchAssoc())
    {
      $oPerson = $aRow['Organization'];
      // If not the first one, add the | separator
      if ($sOrgs!='') $sOrgs = $sOrgs ."|";
      $sOrgs = $sOrgs . "allowed_org_id:" . $oPerson->GetKey();
    }
    $oPage->Add("<p><input id='MyOrgs'value='{$sOrgs}'/>");
    $oPage->add_linked_script("//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.4.0/clipboard.min.js");
    $oPage->Add('<button class="button" id="copy-button" data-clipboard-target="#MyOrgs">Copy</button><p>');
    $oPage->add_ready_script('new Clipboard("#copy-button");');
  }
}
latest/customization/display-bare-relation.txt · Last modified: 2024/09/10 10:25 by 127.0.0.1
Back to top
Contact us