N°8641 - Dashboard editor front-end first commit for Form SDK integration.

* No dashlet edition
* Dashboard are not persisted
* Unable to load a dashboard from an endpoint (refresh)
* Grid library need proper npm integration
This commit is contained in:
Stephen Abello
2026-01-06 15:23:51 +01:00
parent 3e879c64a7
commit a713e1b56e
167 changed files with 32266 additions and 763 deletions

View File

@@ -1077,6 +1077,7 @@ JS
$sId = utils::Sanitize($this->GetId(), '', 'element_identifier');
$sMenuTogglerId = "ibo-dashboard-menu-toggler-{$sId}";
$sActionEditId = "ibo-dashboard-menu-edit-{$sId}";
$sPopoverMenuId = "ibo-dashboard-menu-popover-{$sId}";
$sName = 'UI:Dashboard:Actions';
@@ -1090,6 +1091,20 @@ JS
} else {
$oToolbar = $oDashboard->GetToolbar();
}
// TODO 3.3 Check if we need different action for custom dashboard creation / edition
$oActionEditButton = ButtonUIBlockFactory::MakeIconAction('fas fa-pen',
$this->HasCustomDashboard() ? Dict::S('UI:Dashboard:EditCustom') : Dict::S('UI:Dashboard:CreateCustom'),
$sActionEditId,
'',
false,
$sActionEditId
)
->AddCSSClass('ibo-top-bar--toolbar-dashboard-edit-button')
->AddCSSClass('ibo-action-button');
$oToolbar->AddSubBlock($oActionEditButton);
$oActionButton = ButtonUIBlockFactory::MakeIconAction('fas fa-ellipsis-v', Dict::S($sName), $sName, '', false, $sMenuTogglerId)
->AddCSSClass('ibo-top-bar--toolbar-dashboard-menu-toggler')
->AddCSSClass('ibo-action-button');
@@ -1099,8 +1114,8 @@ JS
$sFile = addslashes(utils::LocalPath($this->sDefinitionFile));
$sJSExtraParams = json_encode($aExtraParams);
if ($this->HasCustomDashboard()) {
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
// $oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:EditCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
// $aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
$oRevert = new JSPopupMenuItem(
'UI:Dashboard:RevertConfirm',
Dict::S('UI:Dashboard:DeleteCustom'),
@@ -1108,8 +1123,8 @@ JS
);
$aActions[$oRevert->GetUID()] = $oRevert->GetMenuItem();
} else {
$oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
$aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
// $oEdit = new JSPopupMenuItem('UI:Dashboard:Edit', Dict::S('UI:Dashboard:CreateCustom'), "return EditDashboard('{$this->sId}', '$sFile', $sJSExtraParams)");
// $aActions[$oEdit->GetUID()] = $oEdit->GetMenuItem();
}
utils::GetPopupMenuItems($oPage, iPopupMenuExtension::MENU_DASHBOARD_ACTIONS, $this, $aActions);

View File

@@ -109,7 +109,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
// Trim the list of cells to remove the invisible/empty ones at the end of the array
$aCells = $this->TrimCellsArray($aCells);
$oDashboardLayout = new DashboardLayoutUIBlock();
// TODO 3.3 Handle dashboard new format, convert old format if needed
$oDashboardLayout = new DashboardLayoutUIBlock($aExtraParams['dashboard_div_id']);
//$oPage->AddUiBlock($oDashboardLayout);
$iCellIdx = 0;
@@ -117,15 +118,16 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
//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);
//$oDashboardLayout->AddDashboardRow($oDashboardRow);
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
$oDashboardColumn = new DashboardColumn($bEditMode);
$oDashboardColumn->SetCellIndex($iCellIdx);
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
//$oDashboardRow->AddDashboardColumn($oDashboardColumn);
if (array_key_exists($iCellIdx, $aCells)) {
$aDashlets = $aCells[$iCellIdx];
@@ -133,7 +135,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
/** @var \Dashlet $oDashlet */
foreach ($aDashlets as $oDashlet) {
if ($oDashlet::IsVisible()) {
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
$oDashboardGrid->AddDashlet($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams), $oDashlet->GetID(), get_class($oDashlet));
//$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
}
}
} else {
@@ -147,6 +150,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
$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

View File

@@ -992,6 +992,10 @@ HTML;
'label' => Dict::S('UI:DashletObjectList:Label'),
'icon' => 'images/dashlets/icons8-list-48.png',
'description' => Dict::S('UI:DashletObjectList:Description'),
'min_height' => 1,
'min_width' => 2,
'preferred_width' => 4,
'preferred_height' => 3
];
}
@@ -1603,6 +1607,10 @@ class DashletGroupByPie extends DashletGroupBy
'label' => Dict::S('UI:DashletGroupByPie:Label'),
'icon' => 'images/dashlets/icons8-pie-chart-48.png',
'description' => Dict::S('UI:DashletGroupByPie:Description'),
'min_height' => 2,
'min_width' => 2,
'preferred_width' => 3,
'preferred_height' => 3
];
}
@@ -1699,6 +1707,10 @@ class DashletGroupByBars extends DashletGroupBy
'label' => Dict::S('UI:DashletGroupByBars:Label'),
'icon' => 'images/dashlets/icons8-bar-chart-48.png',
'description' => Dict::S('UI:DashletGroupByBars:Description'),
'min_height' => 2,
'min_width' => 2,
'preferred_width' => 3,
'preferred_height' => 3
];
}
@@ -1799,6 +1811,10 @@ class DashletGroupByTable extends DashletGroupBy
'label' => Dict::S('UI:DashletGroupByTable:Label'),
'description' => Dict::S('UI:DashletGroupByTable:Description'),
'icon' => 'images/dashlets/icons8-transaction-list-48.png',
'min_height' => 2,
'min_width' => 2,
'preferred_width' => 3,
'preferred_height' => 3
];
}
@@ -1925,6 +1941,10 @@ class DashletHeaderStatic extends Dashlet
'label' => Dict::S('UI:DashletHeaderStatic:Label'),
'icon' => 'images/dashlets/icons8-header-48.png',
'description' => Dict::S('UI:DashletHeaderStatic:Description'),
'min_height' => 1,
'min_width' => 3,
'preferred_width' => 3,
'preferred_height' => 1
];
}
}
@@ -2223,6 +2243,10 @@ class DashletHeaderDynamic extends Dashlet
'label' => Dict::S('UI:DashletHeaderDynamic:Label'),
'icon' => 'images/dashlets/icons8-header-altered-48.png',
'description' => Dict::S('UI:DashletHeaderDynamic:Description'),
'min_height' => 1,
'min_width' => 2,
'preferred_width' => 4,
'preferred_height' => 3
];
}
}
@@ -2332,6 +2356,10 @@ HTML;
'label' => Dict::S('UI:DashletBadge:Label'),
'icon' => 'images/dashlets/icons8-badge-48.png',
'description' => Dict::S('UI:DashletBadge:Description'),
'min_height' => 1,
'min_width' => 2,
'preferred_width' => 2,
'preferred_height' => 2
];
}
}

View File

@@ -6,6 +6,7 @@
*/
use Combodo\iTop\Application\Helper\WebResourcesHelper;
use Combodo\iTop\Application\UI\Base\Layout\PageContent\PageContentFactory;
use Combodo\iTop\Application\WebPage\ErrorPage;
use Combodo\iTop\Application\WebPage\iTopWebPage;
use Combodo\iTop\Application\WebPage\WebPage;
@@ -1279,13 +1280,14 @@ class DashboardMenuNode extends MenuNode
if ($oDashboard != null) {
WebResourcesHelper::EnableC3JSToWebPage($oPage);
// TODO 3.3 this works for dashboard menu, what about other places ?
$oPageLayout = PageContentFactory::MakeForDashboard();
$oPage->SetContentLayout($oPageLayout, $oPage);
$sDivId = utils::Sanitize($this->sMenuId, '', 'element_identifier');
$oPage->add('<div id="'.$sDivId.'" class="ibo-dashboard" data-role="ibo-dashboard">');
$aExtraParams['dashboard_div_id'] = $sDivId;
$aExtraParams['from_dashboard_page'] = true;
$oDashboard->SetReloadURL($this->GetHyperlink($aExtraParams));
$oDashboard->Render($oPage, false, $aExtraParams);
$oPage->add('</div>');
$bEdit = utils::ReadParam('edit', false);
if ($bEdit) {