Dashlet form in new dashboard layout (suite)

This commit is contained in:
Benjamin DALSASS
2026-01-08 15:30:51 +01:00
parent b014b9f638
commit 4a8804b8ac
9 changed files with 218 additions and 148 deletions

View File

@@ -12,6 +12,8 @@ use Combodo\iTop\Application\UI\Base\Component\Toolbar\ToolbarUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Layout\Dashboard\DashboardLayout as DashboardLayoutUIBlock;
use Combodo\iTop\Application\WebPage\iTopWebPage;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\PropertyType\PropertyTypeDesign;
use Combodo\iTop\Service\DependencyInjection\ServiceLocator;
require_once(APPROOT.'application/dashboardlayout.class.inc.php');
require_once(APPROOT.'application/dashlet.class.inc.php');
@@ -24,7 +26,7 @@ require_once(APPROOT.'core/modelreflection.class.inc.php');
*/
abstract class Dashboard
{
/** @var string $sTitle*/
/** @var string $sTitle */
protected $sTitle;
/** @var bool $bAutoReload */
protected $bAutoReload;
@@ -68,7 +70,7 @@ abstract class Dashboard
{
$this->aCells = []; // reset the content of the dashboard
set_error_handler(['Dashboard', 'ErrorHandler']);
$oDoc = new DOMDocument();
$oDoc = new PropertyTypeDesign();
$oDoc->loadXML($sXml);
restore_error_handler();
$this->FromDOMDocument($oDoc);
@@ -121,7 +123,7 @@ abstract class Dashboard
$aDashletOrder = [];
/** @var \DOMElement $oDomNode */
foreach ($oDashletList as $oDomNode) {
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
$oRank = $oDomNode->getElementsByTagName('rank')->item(0);
if ($oRank) {
$iRank = (float)$oRank->textContent;
}
@@ -215,6 +217,7 @@ abstract class Dashboard
$this->ToDOMNode($oMainNode);
$sXml = $oDoc->saveXML();
return $sXml;
}
@@ -279,7 +282,7 @@ abstract class Dashboard
}
$this->sTitle = $aParams['title'];
$this->bAutoReload = $aParams['auto_reload'] == 'true';
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int) $aParams['auto_reload_sec']);
$this->iAutoReloadSec = max(MetaModel::GetConfig()->Get('min_reload_interval'), (int)$aParams['auto_reload_sec']);
foreach ($aParams['cells'] as $aCell) {
$aCellDashlets = [];
@@ -640,6 +643,7 @@ JS
$iNewId = max($iNewId, (int)$oDashlet->GetID());
}
}
return $iNewId + 1;
}
@@ -674,6 +678,7 @@ JS
if (is_subclass_of($sType, 'Dashlet')) {
return $sType;
}
return 'DashletUnknown';
}
@@ -726,6 +731,7 @@ class RuntimeDashboard extends Dashboard
{
parent::__construct($sId);
$this->oMetaModel = new ModelReflectionRuntime();
ServiceLocator::GetInstance()->RegisterService('ModelReflection', $this->oMetaModel);
$this->bCustomized = false;
}
@@ -740,6 +746,7 @@ class RuntimeDashboard extends Dashboard
/**
* @param bool $bCustomized
*
* @since 2.7.0
*/
public function SetCustomFlag($bCustomized)
@@ -784,6 +791,7 @@ class RuntimeDashboard extends Dashboard
utils::PushArchiveMode(false);
$oUserDashboard->DBWrite();
utils::PopArchiveMode();
return $bIsNew;
}
@@ -1059,7 +1067,8 @@ JS
$oUDSet = new DBObjectSet($oUDSearch);
return ($oUDSet->Count() > 0);
} catch (Exception $e) {
}
catch (Exception $e) {
return false;
}
}
@@ -1238,7 +1247,7 @@ EOF
$sId = json_encode($this->sId);
$sLayoutClass = json_encode($this->sLayoutClass);
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
$sAutoReloadSec = (string) $this->iAutoReloadSec;
$sAutoReloadSec = (string)$this->iAutoReloadSec;
$sTitle = json_encode($this->sTitle);
$sFile = json_encode($this->GetDefinitionFile());
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
@@ -1586,7 +1595,7 @@ JS
*/
private function UpdateDashletUserPrefs(Dashlet $oDashlet, $sDashletIdOrig, array $aExtraParams)
{
$bIsDashletWithListPref = ($oDashlet instanceof DashletObjectList);
$bIsDashletWithListPref = ($oDashlet instanceof DashletObjectList);
if (!$bIsDashletWithListPref) {
return;
}
@@ -1630,10 +1639,12 @@ JS
try {
$oFilter = $oDashlet->GetDBSearch($aExtraParams);
$aClassAliases = $oFilter->GetSelectedClasses();
} catch (Exception $e) {
}
catch (Exception $e) {
//on error, return default value
return null;
}
return DataTableSettings::GetAppUserPreferenceKey($aClassAliases, $sDataTableId);
}
}

View File

@@ -43,8 +43,8 @@ abstract class DashboardLayout
public static function GetInfo()
{
return [
'label' => '',
'icon' => '',
'label' => '',
'icon' => '',
'description' => '',
];
}
@@ -74,6 +74,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
}
$idx++;
}
return $aDashlets;
}
@@ -94,6 +95,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
}
$idx++;
}
return $aCells;
}
@@ -135,7 +137,7 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
/** @var \Dashlet $oDashlet */
foreach ($aDashlets as $oDashlet) {
if ($oDashlet::IsVisible()) {
$oDashboardGrid->AddDashlet($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams), $oDashlet->GetID(), get_class($oDashlet));
$oDashboardGrid->AddDashlet($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams), $oDashlet->GetID(), get_class($oDashlet), $oDashlet->GetNormalizedProperties());
//$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
}
}
@@ -172,8 +174,8 @@ abstract class DashboardLayoutMultiCol extends DashboardLayout
*/
public function GetDashletCoordinates($iCellIdx)
{
$iColNumber = (int) $iCellIdx % $this->iNbCols;
$iRowNumber = (int) floor($iCellIdx / $this->iNbCols);
$iColNumber = (int)$iCellIdx % $this->iNbCols;
$iRowNumber = (int)floor($iCellIdx / $this->iNbCols);
return [$iColNumber, $iRowNumber];
}
@@ -186,11 +188,12 @@ class DashboardLayoutOneCol extends DashboardLayoutMultiCol
parent::__construct();
$this->iNbCols = 1;
}
public static function GetInfo()
{
return [
'label' => 'One Column',
'icon' => 'images/layout_1col.png',
'label' => 'One Column',
'icon' => 'images/layout_1col.png',
'description' => '',
];
}
@@ -203,11 +206,12 @@ class DashboardLayoutTwoCols extends DashboardLayoutMultiCol
parent::__construct();
$this->iNbCols = 2;
}
public static function GetInfo()
{
return [
'label' => 'Two Columns',
'icon' => 'images/layout_2col.png',
'label' => 'Two Columns',
'icon' => 'images/layout_2col.png',
'description' => '',
];
}
@@ -220,11 +224,12 @@ class DashboardLayoutThreeCols extends DashboardLayoutMultiCol
parent::__construct();
$this->iNbCols = 3;
}
public static function GetInfo()
{
return [
'label' => 'Two Columns',
'icon' => 'images/layout_3col.png',
'label' => 'Two Columns',
'icon' => 'images/layout_3col.png',
'description' => '',
];
}

View File

@@ -25,6 +25,8 @@ use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
use Combodo\iTop\Application\UI\Base\iUIBlock;
use Combodo\iTop\Application\UI\Base\UIBlock;
use Combodo\iTop\Application\WebPage\WebPage;
use Combodo\iTop\DesignElement;
use Combodo\iTop\PropertyType\Serializer\XMLSerializer;
require_once(APPROOT.'application/forms.class.inc.php');
@@ -46,6 +48,7 @@ abstract class Dashlet
protected $aProperties; // array of {property => value}
protected $aCSSClasses;
protected $sDashletType;
private $aNormalizedProperties = null; // array of properties from serialized form
/**
* Dashlet constructor.
@@ -90,6 +93,7 @@ abstract class Dashlet
$ret = $sValue;
settype($ret, $sRefType);
}
return $ret;
}
@@ -106,8 +110,9 @@ abstract class Dashlet
} elseif ($sType == 'array') {
$sRet = implode(',', $value);
} else {
$sRet = (string) $value;
$sRet = (string)$value;
}
return $sRet;
}
@@ -116,10 +121,12 @@ abstract class Dashlet
}
/**
* @param \DOMElement $oDOMNode
*/
public function FromDOMNode($oDOMNode)
public function FromDOMNode(DesignElement $oDOMNode)
{
/* @var DesignElement $oDOMNode */
$this->aNormalizedProperties = XMLSerializer::GetInstance()->Unserialize($oDOMNode, get_class($this), 'Dashlet');
foreach ($this->aProperties as $sProperty => $value) {
$oPropNode = $oDOMNode->getElementsByTagName($sProperty)->item(0);
if ($oPropNode != null) {
@@ -150,6 +157,7 @@ abstract class Dashlet
protected function PropertyFromDOMNode($oDOMNode, $sProperty)
{
$res = $this->Str2Prop($sProperty, $oDOMNode->textContent);
return $res;
}
@@ -246,17 +254,20 @@ abstract class Dashlet
$oBlock = $this->RenderNoData($oPage, $bEditMode, $aExtraParams);
}
$oDashletContainer->AddSubBlock($oBlock);
} catch (UnknownClassOqlException $e) {
}
catch (UnknownClassOqlException $e) {
// Maybe the class is part of a non-installed module, fail silently
// Except in Edit mode
if ($bEditMode) {
$oDashletContainer->AddCSSClass("dashlet-content");
$oDashletContainer->AddHtml('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
}
} catch (OqlException $e) {
}
catch (OqlException $e) {
$oDashletContainer->AddCSSClass("dashlet-content");
$oDashletContainer->AddHtml('<p>'.utils::HtmlEntities($e->GetUserFriendlyDescription()).'</p>');
} catch (Exception $e) {
}
catch (Exception $e) {
$oDashletContainer->AddCSSClass("dashlet-content");
$oDashletContainer->AddHtml('<p>'.$e->getMessage().'</p>');
}
@@ -342,6 +353,7 @@ EOF
}
}
$this->OnUpdate();
return $this;
}
@@ -367,8 +379,8 @@ EOF
public static function GetInfo()
{
return [
'label' => '',
'icon' => '',
'label' => '',
'icon' => '',
'description' => '',
];
}
@@ -477,9 +489,11 @@ EOF
}
}
asort($aGroupBy);
} catch (Exception $e) {
}
catch (Exception $e) {
// Fallback in case of OQL problem
}
return $aGroupBy;
}
@@ -498,6 +512,11 @@ EOF
{
$this->sDashletType = $sDashletType;
}
public function GetNormalizedProperties(): ?array
{
return $this->aNormalizedProperties;
}
}
/**
@@ -635,6 +654,7 @@ class DashletUnknown extends Dashlet
if (isset($aInfo['configuration']) && empty($this->sOriginalDashletXML)) {
$this->sOriginalDashletXML = $aInfo['configuration'];
}
return parent::GetForm($aInfo);
}
@@ -663,6 +683,7 @@ class DashletUnknown extends Dashlet
if ($bHasSubProperties) {
$sTmp = $oDOMNode->ownerDocument->saveXML($oDOMNode, LIBXML_NOENT);
$sTmp = trim(preg_replace("/(<".$oDOMNode->tagName."[^>]*>|<\/".$oDOMNode->tagName.">)/", "", $sTmp));
return $sTmp;
} else {
return parent::PropertyFromDOMNode($oDOMNode, $sProperty);
@@ -693,6 +714,7 @@ class DashletUnknown extends Dashlet
public function Update($aValues, $aUpdatedFields)
{
$this->FromParams($aValues);
// OnUpdate() already done in FromParams()
return $this;
}
@@ -703,8 +725,8 @@ class DashletUnknown extends Dashlet
public static function GetInfo()
{
return [
'label' => Dict::S('UI:DashletUnknown:Label'),
'icon' => 'images/dashlet-unknown.png',
'label' => Dict::S('UI:DashletUnknown:Label'),
'icon' => 'images/dashlet-unknown.png',
'description' => Dict::S('UI:DashletUnknown:Description'),
];
}
@@ -735,6 +757,7 @@ class DashletProxy extends DashletUnknown
// This should never be called.
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
$oDashletContainer->AddHtml('<div>This dashlet is not supposed to be rendered as it is just a proxy for third-party widgets.</div>');
return $oDashletContainer;
}
@@ -757,6 +780,7 @@ class DashletProxy extends DashletUnknown
$sHtml .= '<div class="dashlet-pxy-text">'.$sExplainText.'</div>';
$oDashletContainer->AddHtml($sHtml);
return $oDashletContainer;
}
@@ -766,8 +790,8 @@ class DashletProxy extends DashletUnknown
public static function GetInfo()
{
return [
'label' => Dict::S('UI:DashletProxy:Label'),
'icon' => 'images/dashlet-proxy.png',
'label' => Dict::S('UI:DashletProxy:Label'),
'icon' => 'images/dashlet-proxy.png',
'description' => Dict::S('UI:DashletProxy:Description'),
];
}
@@ -804,8 +828,8 @@ class DashletEmptyCell extends Dashlet
public static function GetInfo()
{
return [
'label' => 'Empty Cell',
'icon' => 'images/dashlet-text.png',
'label' => 'Empty Cell',
'icon' => 'images/dashlet-text.png',
'description' => 'Empty Cell Dashlet Placeholder',
];
}
@@ -860,8 +884,8 @@ class DashletPlainText extends Dashlet
public static function GetInfo()
{
return [
'label' => Dict::S('UI:DashletPlainText:Label'),
'icon' => 'images/dashlets/icons8-text-box-48.png',
'label' => Dict::S('UI:DashletPlainText:Label'),
'icon' => 'images/dashlets/icons8-text-box-48.png',
'description' => Dict::S('UI:DashletPlainText:Description'),
];
}
@@ -898,12 +922,12 @@ class DashletObjectList extends Dashlet
$oBlock = new DisplayBlock($oFilter, 'list');
$aParams = [
'menu' => $sShowMenu,
'table_id' => self::APPUSERPREFERENCES_PREFIX.$this->sId,
'menu' => $sShowMenu,
'table_id' => self::APPUSERPREFERENCES_PREFIX.$this->sId,
'surround_with_panel' => true,
'max_height' => '500px',
"panel_title" => Dict::S($sTitle),
"panel_class" => $sClass,
'max_height' => '500px',
"panel_title" => Dict::S($sTitle),
"panel_class" => $sClass,
];
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
//$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
@@ -989,13 +1013,13 @@ HTML;
public static function GetInfo()
{
return [
'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
'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,
];
}
@@ -1087,7 +1111,8 @@ abstract class DashletGroupBy extends Dashlet
$oQuery = $this->oModelReflection->GetQuery($sQuery);
$this->sClass = $oQuery->GetClass();
$sClassAlias = $oQuery->GetClassAlias();
} catch (Exception $e) {
}
catch (Exception $e) {
// Invalid query, let the user edit the dashlet/dashboard anyhow
$this->sClass = null;
$sClassAlias = '';
@@ -1186,15 +1211,15 @@ abstract class DashletGroupBy extends Dashlet
case 'bars':
$sType = 'chart';
$aParams = [
'chart_type' => 'bars',
'chart_title' => $sTitle,
'group_by' => $this->sGroupByExpr,
'group_by_label' => $this->sGroupByLabel,
'aggregation_function' => $this->sAggregationFunction,
'chart_type' => 'bars',
'chart_title' => $sTitle,
'group_by' => $this->sGroupByExpr,
'group_by_label' => $this->sGroupByLabel,
'aggregation_function' => $this->sAggregationFunction,
'aggregation_attribute' => $this->sAggregationAttribute,
'limit' => $this->sLimit,
'order_direction' => $this->sOrderDirection,
'order_by' => $this->sOrderBy,
'limit' => $this->sLimit,
'order_direction' => $this->sOrderDirection,
'order_by' => $this->sOrderBy,
];
$sHtmlTitle = ''; // done in the itop block
break;
@@ -1202,15 +1227,15 @@ abstract class DashletGroupBy extends Dashlet
case 'pie':
$sType = 'chart';
$aParams = [
'chart_type' => 'pie',
'chart_title' => $sTitle,
'group_by' => $this->sGroupByExpr,
'group_by_label' => $this->sGroupByLabel,
'aggregation_function' => $this->sAggregationFunction,
'chart_type' => 'pie',
'chart_title' => $sTitle,
'group_by' => $this->sGroupByExpr,
'group_by_label' => $this->sGroupByLabel,
'aggregation_function' => $this->sAggregationFunction,
'aggregation_attribute' => $this->sAggregationAttribute,
'limit' => $this->sLimit,
'order_direction' => $this->sOrderDirection,
'order_by' => $this->sOrderBy,
'limit' => $this->sLimit,
'order_direction' => $this->sOrderDirection,
'order_by' => $this->sOrderBy,
];
$sHtmlTitle = ''; // done in the itop block
break;
@@ -1220,13 +1245,13 @@ abstract class DashletGroupBy extends Dashlet
$sHtmlTitle = utils::HtmlEntities(Dict::S($sTitle)); // done in the itop block
$sType = 'count';
$aParams = [
'group_by' => $this->sGroupByExpr,
'group_by_label' => $this->sGroupByLabel,
'aggregation_function' => $this->sAggregationFunction,
'group_by' => $this->sGroupByExpr,
'group_by_label' => $this->sGroupByLabel,
'aggregation_function' => $this->sAggregationFunction,
'aggregation_attribute' => $this->sAggregationAttribute,
'limit' => $this->sLimit,
'order_direction' => $this->sOrderDirection,
'order_by' => $this->sOrderBy,
'limit' => $this->sLimit,
'order_direction' => $this->sOrderDirection,
'order_by' => $this->sOrderBy,
];
break;
}
@@ -1297,7 +1322,7 @@ abstract class DashletGroupBy extends Dashlet
$aAllowed = $this->oModelReflection->GetAllowedValues_att($sClass, $this->sGroupByAttCode);
if ($aAllowed) { // null for non enums
foreach ($aAllowed as $sValue => $sValueLabel) {
$iCount = (int) rand(2, 100);
$iCount = (int)rand(2, 100);
$aDisplayValues[] = [
'label' => $sValueLabel,
'value' => $iCount,
@@ -1310,6 +1335,7 @@ abstract class DashletGroupBy extends Dashlet
$aDisplayValues[] = ['label' => 'c', 'value' => 456];
}
}
return $aDisplayValues;
}
@@ -1320,6 +1346,7 @@ abstract class DashletGroupBy extends Dashlet
{
$oDashletContainer = new DashletContainer(null, ['dashlet-content']);
$oDashletContainer->AddHtml('error!');
return $oDashletContainer;
}
@@ -1344,7 +1371,8 @@ abstract class DashletGroupBy extends Dashlet
$oField = new DesignerComboField('group_by', Dict::S('UI:DashletGroupBy:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetMandatory();
$oField->SetAllowedValues($aGroupBy);
} catch (Exception $e) {
}
catch (Exception $e) {
$oField = new DesignerTextField('group_by', Dict::S('UI:DashletGroupBy:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetReadOnly();
$aGroupBy = [];
@@ -1352,8 +1380,8 @@ abstract class DashletGroupBy extends Dashlet
$oForm->AddField($oField);
$aStyles = [
'pie' => Dict::S('UI:DashletGroupByPie:Label'),
'bars' => Dict::S('UI:DashletGroupByBars:Label'),
'pie' => Dict::S('UI:DashletGroupByPie:Label'),
'bars' => Dict::S('UI:DashletGroupByBars:Label'),
'table' => Dict::S('UI:DashletGroupByTable:Label'),
];
@@ -1403,9 +1431,9 @@ abstract class DashletGroupBy extends Dashlet
}
$aOrderDirections = [
'asc' => Dict::S('UI:DashletGroupBy:Order:asc'),
'asc' => Dict::S('UI:DashletGroupBy:Order:asc'),
'desc' => Dict::S('UI:DashletGroupBy:Order:desc'),
];
];
$sOrderDirection = empty($this->aProperties['order_direction']) ? $this->sOrderDirection : $this->aProperties['order_direction'];
$oField = new DesignerComboField('order_direction', Dict::S('UI:DashletGroupBy:Prop-OrderDirection'), $sOrderDirection);
$oField->SetMandatory();
@@ -1422,9 +1450,11 @@ abstract class DashletGroupBy extends Dashlet
if (is_null($this->sClass)) {
return [];
}
return [
$this->aProperties['group_by'] => $this->oModelReflection->GetLabel($this->sClass, $this->aProperties['group_by']),
'_itop_'.$this->aProperties['aggregation_function'].'_' => Dict::S('UI:GroupBy:'.$this->aProperties['aggregation_function'])];
$this->aProperties['group_by'] => $this->oModelReflection->GetLabel($this->sClass, $this->aProperties['group_by']),
'_itop_'.$this->aProperties['aggregation_function'].'_' => Dict::S('UI:GroupBy:'.$this->aProperties['aggregation_function']),
];
}
/**
@@ -1472,7 +1502,8 @@ abstract class DashletGroupBy extends Dashlet
break;
}
}
} catch (Exception $e) {
}
catch (Exception $e) {
// In case the OQL is bad
}
@@ -1499,7 +1530,8 @@ abstract class DashletGroupBy extends Dashlet
// wrong but not necessary - unset($aUpdatedFields['group_by']);
$this->aProperties['group_by'] = '';
}
} catch (Exception $e) {
}
catch (Exception $e) {
$this->bFormRedrawNeeded = true;
}
}
@@ -1531,6 +1563,7 @@ abstract class DashletGroupBy extends Dashlet
$oDashlet->bRedrawNeeded = true;
$oDashlet->bFormRedrawNeeded = true;
}
return $oDashlet;
}
@@ -1541,8 +1574,8 @@ abstract class DashletGroupBy extends Dashlet
{
// Note: no need to translate, should never be visible to the end-user!
return [
'label' => 'Objects grouped by...',
'icon' => 'images/dashlets/icons8-transaction-list-48.png',
'label' => 'Objects grouped by...',
'icon' => 'images/dashlets/icons8-transaction-list-48.png',
'description' => 'Grouped objects dashlet (abstract)',
];
}
@@ -1604,13 +1637,13 @@ class DashletGroupByPie extends DashletGroupBy
public static function GetInfo()
{
return [
'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
'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,
];
}
@@ -1704,13 +1737,13 @@ class DashletGroupByBars extends DashletGroupBy
public static function GetInfo()
{
return [
'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
'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,
];
}
@@ -1808,13 +1841,13 @@ class DashletGroupByTable extends DashletGroupBy
public static function GetInfo()
{
return [
'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
'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,
];
}
@@ -1913,6 +1946,7 @@ class DashletHeaderStatic extends Dashlet
{
if ($sProperty == 'icon') {
$oIconField = $this->oModelReflection->GetIconSelectionField('icon');
return $oIconField->ValueFromDOMNode($oDOMNode);
} else {
return parent::PropertyFromDOMNode($oDOMNode, $sProperty);
@@ -1938,13 +1972,13 @@ class DashletHeaderStatic extends Dashlet
public static function GetInfo()
{
return [
'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
'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,
];
}
}
@@ -1990,6 +2024,7 @@ class DashletHeaderDynamic extends Dashlet
}
}
}
return $aValues;
}
@@ -2018,17 +2053,17 @@ class DashletHeaderDynamic extends Dashlet
// Stats grouped by <group_by>
$sCSV = implode(',', $aValues);
$aParams = [
'title[block]' => $sTitle,
'label[block]' => $sSubtitle,
'status[block]' => $sGroupBy,
'title[block]' => $sTitle,
'label[block]' => $sSubtitle,
'status[block]' => $sGroupBy,
'status_codes[block]' => $sCSV,
'context_filter' => 1,
'context_filter' => 1,
];
} else {
// Simple stats
$aParams = [
'title[block]' => $sTitle,
'label[block]' => $sSubtitle,
'title[block]' => $sTitle,
'label[block]' => $sSubtitle,
'context_filter' => 1,
];
}
@@ -2082,7 +2117,8 @@ class DashletHeaderDynamic extends Dashlet
foreach ($aValues as $sValue) {
$aValueLabels[] = $this->oModelReflection->GetValueLabel($sClass, $sGroupBy, $sValue);
}
} catch (UnknownClassOqlException $e) {
}
catch (UnknownClassOqlException $e) {
$aValueLabels[] = $e->GetUserFriendlyDescription();
$aValues[] = 1;
}
@@ -2159,7 +2195,8 @@ class DashletHeaderDynamic extends Dashlet
$oField = new DesignerComboField('group_by', Dict::S('UI:DashletHeaderDynamic:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetMandatory();
$oField->SetAllowedValues($aGroupBy);
} catch (Exception $e) {
}
catch (Exception $e) {
$oField = new DesignerTextField('group_by', Dict::S('UI:DashletHeaderDynamic:Prop-GroupBy'), $this->aProperties['group_by']);
$oField->SetReadOnly();
}
@@ -2197,7 +2234,8 @@ class DashletHeaderDynamic extends Dashlet
$this->aProperties['group_by'] = '';
$this->aProperties['values'] = [];
}
} catch (Exception $e) {
}
catch (Exception $e) {
$this->bFormRedrawNeeded = true;
}
}
@@ -2205,6 +2243,7 @@ class DashletHeaderDynamic extends Dashlet
$this->bFormRedrawNeeded = true;
$this->aProperties['values'] = [];
}
return parent::Update($aValues, $aUpdatedFields);
}
@@ -2215,6 +2254,7 @@ class DashletHeaderDynamic extends Dashlet
{
if ($sProperty == 'icon') {
$oIconField = $this->oModelReflection->GetIconSelectionField('icon');
return $oIconField->ValueFromDOMNode($oDOMNode);
} else {
return parent::PropertyFromDOMNode($oDOMNode, $sProperty);
@@ -2240,13 +2280,13 @@ class DashletHeaderDynamic extends Dashlet
public static function GetInfo()
{
return [
'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
'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,
];
}
}
@@ -2353,13 +2393,13 @@ HTML;
public static function GetInfo()
{
return [
'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
'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

@@ -87,6 +87,7 @@ class IboDashboard extends HTMLElement {
const sNewDashletUrl = GetAbsoluteUrlAppRoot() + '/pages/UI.php?route=dashboard.new_dashlet&dashlet_class='+encodeURIComponent(sDashletClass);
fetch(sNewDashletUrl)
.then(async data => {
const sDashletId = this.oGrid.AddDashlet(await data.text(), aDashletOptions);
// TODO 3.3 Either open the dashlet form right away, or just enter edit mode

View File

@@ -2,27 +2,32 @@
namespace Combodo\iTop\Application\UI\Base\Component\Dashlet;
use Combodo\iTop\Application\UI\Base\UIBlock;
use Dashlet;
class DashletWrapper extends UIBlock {
public const BLOCK_CODE = 'ibo-dashlet-wrapper';
class DashletWrapper extends UIBlock
{
public const BLOCK_CODE = 'ibo-dashlet-wrapper';
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/components/dashlet/dashlet-wrapper';
protected $oDashlet;
protected DashletContainer $oDashletContainer;
protected $sDashletClass;
protected $sDashletId;
private array $aFormViewData;
public function __construct($oDashlet, ?string $sDashletId = null, ?string $sDashletClass = null) {
public function __construct($oDashlet, string $sDashletClass, ?string $sDashletId = null, array $aFormViewData = [])
{
parent::__construct(null);
$this->oDashlet = $oDashlet;
$this->oDashletContainer = $oDashlet;
$this->sDashletId = $sDashletId;
$this->sDashletClass = $sDashletClass;
$this->aFormViewData = $aFormViewData;
}
public function GetDashlet() {
return $this->oDashlet;
public function GetDashlet()
{
return $this->oDashletContainer;
}
public function GetDashletId(): ?string
@@ -48,4 +53,9 @@ class DashletWrapper extends UIBlock {
return $this;
}
public function GetFormViewData()
{
return $this->aFormViewData;
}
}

View File

@@ -18,7 +18,7 @@ class DashboardGrid extends UIBlock
public const BLOCK_CODE = 'ibo-dashboard-grid';
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/layouts/dashboard/grid/layout';
public const DEFAULT_JS_FILES_REL_PATH = [
public const DEFAULT_JS_FILES_REL_PATH = [
'js/layouts/dashboard/dashboard-grid.js',
];
@@ -53,8 +53,9 @@ class DashboardGrid extends UIBlock
return $this;
}
public function AddDashlet(UIBlock $oDashlet, ?string $sDashletId = null, ?string $sDashletClass = null): DashboardGrid {
$oWrapper = new DashletWrapper($oDashlet, $sDashletId, $sDashletClass);
public function AddDashlet(UIBlock $oDashlet, string $sDashletId, string $sDashletClass, array $aFormViewData): DashboardGrid
{
$oWrapper = new DashletWrapper($oDashlet, $sDashletClass, $sDashletId, $aFormViewData);
$oSlot = new DashboardGridSlot(null, $oWrapper);
$this->AddSlot($oSlot);

View File

@@ -32,7 +32,7 @@ class DashboardController extends AbstractController
if ($oDashletBlock instanceof iUIBlock) {
// Wrap the dashlet
$oDashletWrapper = new DashletWrapper($oDashletBlock, $oDashlet->GetID(), $sDashletClass);
$oDashletWrapper = new DashletWrapper($oDashletBlock, $sDashletClass, $oDashlet->GetID());
$oPage->AddUiBlock($oDashletWrapper);
}
}

View File

@@ -38,7 +38,9 @@ class XMLSerializer
public function Unserialize(DesignElement $oDOMNode, string $sId, string $sType): mixed
{
return null;
$sPropertyTypeXML = PropertyTypeCompiler::GetInstance()->GetXMLContent($sId, $sType);
return $this->UnserializeForPropertyType($oDOMNode, $sPropertyTypeXML);
}
public function SerializeForPropertyType(mixed $value, DesignElement $oParentNode, string $sPropertyTypeXML): void

View File

@@ -1,4 +1,4 @@
<ibo-dashlet class="grid-stack-item-content aa" data-dashlet-type="{{ oUIBlock.GetDashletClass() }}" data-dashlet-id="{{ oUIBlock.GetDashletId() }}">
<ibo-dashlet class="grid-stack-item-content aa" data-dashlet-type="{{ oUIBlock.GetDashletClass() }}" data-dashlet-id="{{ oUIBlock.GetDashletId() }}" data-form-view-data="{{ oUIBlock.GetFormViewData()|json_encode }}">
<div class="ibo-dashlet--actions">
<button class="ibo-dashlet--action ibo-dashlet--action--edit ibo-button ibo-is-alternative ibo-is-neutral"
title="Edit dashlet"