use Combodo\iTop\Application\UI\Base\Component\Html\Html; use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardColumn; use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock; use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardRow; use Combodo\iTop\Application\WebPage\WebPage; /** * Dashboard presentation * * @copyright Copyright (C) 2010-2024 Combodo SAS * @license http://opensource.org/licenses/AGPL-3.0 */ abstract class DashboardLayout { abstract public function Render($oPage, $aDashlets, $bEditMode = false, array $aExtraParams = []); /** * @param int $iCellIdx * * @return array Containing 2 scalars: Col number and row number (starting from 0) * @since 2.7.0 */ abstract public function GetDashletCoordinates($iCellIdx); public static function GetInfo() { return [ 'label' => '', 'icon' => '', 'description' => '', ]; } } abstract class DashboardLayoutMultiCol extends DashboardLayout { protected $iNbCols; public function __construct() { $this->iNbCols = 1; } protected function TrimCell($aDashlets) { $aKeys = array_reverse(array_keys($aDashlets)); $idx = 0; $bNoVisibleFound = true; while ($idx < count($aKeys) && $bNoVisibleFound) { /** @var \Dashlet $oDashlet */ $oDashlet = $aDashlets[$aKeys[$idx]]; if ($oDashlet::IsVisible()) { $bNoVisibleFound = false; } else { unset($aDashlets[$aKeys[$idx]]); } $idx++; } return $aDashlets; } protected function TrimCellsArray($aCells) { foreach ($aCells as $key => $aDashlets) { $aCells[$key] = $this->TrimCell($aDashlets); } $aKeys = array_reverse(array_keys($aCells)); $idx = 0; $bNoVisibleFound = true; while ($idx < count($aKeys) && $bNoVisibleFound) { $aDashlets = $aCells[$aKeys[$idx]]; if (count($aDashlets) > 0) { $bNoVisibleFound = false; } else { unset($aCells[$aKeys[$idx]]); } $idx++; } return $aCells; } /** * @param WebPage $oPage * @param $aCells * @param bool $bEditMode * @param array $aExtraParams */ public function Render($oPage, $aCells, $bEditMode = false, $aExtraParams = []) { // Trim the list of cells to remove the invisible/empty ones at the end of the array $aCells = $this->TrimCellsArray($aCells); // TODO 3.3 Handle dashboard new format, convert old format if needed $oDashboardLayout = new DashboardLayoutUIBlock($aExtraParams['dashboard_div_id']); //$oPage->AddUiBlock($oDashboardLayout); $iCellIdx = 0; $iNbRows = ceil(count($aCells) / $this->iNbCols); //Js given by each dashlet to reload $sJSReload = ""; $oDashboardGrid = new \Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardGrid(); $oDashboardLayout->SetGrid($oDashboardGrid); for ($iRows = 0; $iRows < $iNbRows; $iRows++) { $oDashboardRow = new DashboardRow(); //$oDashboardLayout->AddDashboardRow($oDashboardRow); for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) { $oDashboardColumn = new DashboardColumn($bEditMode); $oDashboardColumn->SetCellIndex($iCellIdx); //$oDashboardRow->AddDashboardColumn($oDashboardColumn); if (array_key_exists($iCellIdx, $aCells)) { $aDashlets = $aCells[$iCellIdx]; if (count($aDashlets) > 0) { /** @var \Dashlet $oDashlet */ foreach ($aDashlets as $oDashlet) { if ($oDashlet::IsVisible()) { $sDashletId = $oDashlet->GetID(); $sDashletClass = get_class($oDashlet); $aDashletDenormalizedProperties = $oDashlet->GetDenormalizedProperties(); // $aDashletsInfo = $sDashletClass::GetInfo(); // // // TODO 3.3 Gather real position and height/width if any. // // Also set minimal height/width // $iPositionX = null; // $iPositionY = null; // $iWidth = array_key_exists('preferred_width', $aDashletsInfo) ? $aDashletsInfo['preferred_width'] : 1; // $iHeight = array_key_exists('preferred_height', $aDashletsInfo) ? $aDashletsInfo['preferred_height'] : 1; // $oDashboardGrid->AddDashlet($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams), $sDashletId, $sDashletClass, $aDashletDenormalizedProperties, $iPositionX, $iPositionY, $iWidth, $iHeight); $oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams)); } } } else { $oDashboardColumn->AddUIBlock(new Html(' ')); } } else { $oDashboardColumn->AddUIBlock(new Html(' ')); } $iCellIdx++; } $sJSReload .= $oDashboardRow->GetJSRefreshCallback()." "; } // TODO 3.3 We can probably do better with the new dashboard $oPage->add_script("function updateDashboard".$aExtraParams['dashboard_div_id']."(){".$sJSReload."}"); if ($bEditMode) { // Add one row for extensibility $oDashboardRow = new DashboardRow(); $oDashboardLayout->AddDashboardRow($oDashboardRow); for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) { $oDashboardColumn = new DashboardColumn($bEditMode, true); $oDashboardRow->AddDashboardColumn($oDashboardColumn); $oDashboardColumn->AddUIBlock(new Html(' ')); } } return $oDashboardLayout; } /** * @inheritDoc */ public function GetDashletCoordinates($iCellIdx) { $iColNumber = (int)$iCellIdx % $this->iNbCols; $iRowNumber = (int)floor($iCellIdx / $this->iNbCols); return [$iColNumber, $iRowNumber]; } } class DashboardLayoutOneCol extends DashboardLayoutMultiCol { public function __construct() { parent::__construct(); $this->iNbCols = 1; } public static function GetInfo() { return [ 'label' => 'One Column', 'icon' => 'images/layout_1col.png', 'description' => '', ]; } } class DashboardLayoutTwoCols extends DashboardLayoutMultiCol { public function __construct() { parent::__construct(); $this->iNbCols = 2; } public static function GetInfo() { return [ 'label' => 'Two Columns', 'icon' => 'images/layout_2col.png', 'description' => '', ]; } } class DashboardLayoutThreeCols extends DashboardLayoutMultiCol { public function __construct() { parent::__construct(); $this->iNbCols = 3; } public static function GetInfo() { return [ 'label' => 'Two Columns', 'icon' => 'images/layout_3col.png', 'description' => '', ]; } }