diff --git a/application/dashboard.class.inc.php b/application/dashboard.class.inc.php index 3613a6502..f3d0bbb09 100644 --- a/application/dashboard.class.inc.php +++ b/application/dashboard.class.inc.php @@ -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); } } diff --git a/application/dashboardlayout.class.inc.php b/application/dashboardlayout.class.inc.php index d6cb290c0..d9fa2362d 100644 --- a/application/dashboardlayout.class.inc.php +++ b/application/dashboardlayout.class.inc.php @@ -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' => '', ]; } diff --git a/application/dashlet.class.inc.php b/application/dashlet.class.inc.php index b4f7637e2..21a081953 100644 --- a/application/dashlet.class.inc.php +++ b/application/dashlet.class.inc.php @@ -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('

'.$e->GetUserFriendlyDescription().'

'); } - } catch (OqlException $e) { + } + catch (OqlException $e) { $oDashletContainer->AddCSSClass("dashlet-content"); $oDashletContainer->AddHtml('

'.utils::HtmlEntities($e->GetUserFriendlyDescription()).'

'); - } catch (Exception $e) { + } + catch (Exception $e) { $oDashletContainer->AddCSSClass("dashlet-content"); $oDashletContainer->AddHtml('

'.$e->getMessage().'

'); } @@ -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('
This dashlet is not supposed to be rendered as it is just a proxy for third-party widgets.
'); + return $oDashletContainer; } @@ -757,6 +780,7 @@ class DashletProxy extends DashletUnknown $sHtml .= '
'.$sExplainText.'
'; $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 $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, ]; } } diff --git a/js/layouts/dashboard/dashboard.js b/js/layouts/dashboard/dashboard.js index 696b686fb..c58fcc169 100644 --- a/js/layouts/dashboard/dashboard.js +++ b/js/layouts/dashboard/dashboard.js @@ -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 diff --git a/sources/Application/UI/Base/Component/Dashlet/DashletWrapper.php b/sources/Application/UI/Base/Component/Dashlet/DashletWrapper.php index d71d9ea7e..5ad174384 100644 --- a/sources/Application/UI/Base/Component/Dashlet/DashletWrapper.php +++ b/sources/Application/UI/Base/Component/Dashlet/DashletWrapper.php @@ -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; + } } diff --git a/sources/Application/UI/Base/Layout/Dashboard/DashboardGrid.php b/sources/Application/UI/Base/Layout/Dashboard/DashboardGrid.php index 58c0612db..48d6d6aaf 100644 --- a/sources/Application/UI/Base/Layout/Dashboard/DashboardGrid.php +++ b/sources/Application/UI/Base/Layout/Dashboard/DashboardGrid.php @@ -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); diff --git a/sources/Controller/Base/Layout/DashboardController.php b/sources/Controller/Base/Layout/DashboardController.php index c3660726a..af1a4fc64 100644 --- a/sources/Controller/Base/Layout/DashboardController.php +++ b/sources/Controller/Base/Layout/DashboardController.php @@ -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); } } diff --git a/sources/PropertyType/Serializer/XMLSerializer.php b/sources/PropertyType/Serializer/XMLSerializer.php index 1d3187998..ec8758409 100644 --- a/sources/PropertyType/Serializer/XMLSerializer.php +++ b/sources/PropertyType/Serializer/XMLSerializer.php @@ -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 diff --git a/templates/base/components/dashlet/dashlet-wrapper.html.twig b/templates/base/components/dashlet/dashlet-wrapper.html.twig index 208b4c82f..8893b2ed9 100644 --- a/templates/base/components/dashlet/dashlet-wrapper.html.twig +++ b/templates/base/components/dashlet/dashlet-wrapper.html.twig @@ -1,4 +1,4 @@ - +