mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 02:28:44 +02:00
N°2847 - Dashboards
This commit is contained in:
@@ -15,15 +15,17 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardColumn;
|
||||
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardLayout as UIDashboardLayout;
|
||||
use Combodo\iTop\Application\UI\Layout\Dashboard\DashboardRow;
|
||||
|
||||
/**
|
||||
* Dashboard presentation
|
||||
*
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2012 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
*/
|
||||
abstract class DashboardLayout
|
||||
{
|
||||
abstract public function Render($oPage, $aDashlets, $bEditMode = false);
|
||||
@@ -114,72 +116,52 @@ 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);
|
||||
|
||||
$oPage->add('<table class="ibo-dashboard--grid"><tbody>');
|
||||
$oDashboardLayout = new UIDashboardLayout();
|
||||
$oPage->AddUiBlock($oDashboardLayout);
|
||||
|
||||
$iCellIdx = 0;
|
||||
$fColSize = ceil(100 / $this->iNbCols); // Note: ceil() is necessary otherwise the table will be too short since the new flex layout (N°2847)
|
||||
$iNbRows = ceil(count($aCells) / $this->iNbCols);
|
||||
|
||||
$aStyleProperties = [];
|
||||
// - Explicit full width when single column
|
||||
if($this->iNbCols > 1)
|
||||
{
|
||||
$aStyleProperties[] = 'width: '.$fColSize.'%;';
|
||||
}
|
||||
// - Visible borders in editor
|
||||
if($bEditMode)
|
||||
{
|
||||
$aStyleProperties[] = 'border: 1px #ccc dashed;';
|
||||
for ($iRows = 0; $iRows < $iNbRows; $iRows++) {
|
||||
$oDashboardRow = new DashboardRow();
|
||||
$oDashboardLayout->AddDashboardRow($oDashboardRow);
|
||||
|
||||
}
|
||||
$sClass = $bEditMode ? 'layout_cell edit_mode' : 'dashboard';
|
||||
for ($iCols = 0; $iCols < $this->iNbCols; $iCols++) {
|
||||
$oDashboardColumn = new DashboardColumn($bEditMode);
|
||||
$oDashboardColumn->SetCellIndex($iCellIdx);
|
||||
$oDashboardRow->AddDashboardColumn($oDashboardColumn);
|
||||
|
||||
for($iRows = 0; $iRows < $iNbRows; $iRows++)
|
||||
{
|
||||
$oPage->add("<tr class=\"ibo-dashboard--grid-row\" data-dashboard-grid-row-index=\"$iRows\">");
|
||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
||||
{
|
||||
$sCellClass = ($iRows == $iNbRows-1) ? $sClass.' layout_last_used_rank' : $sClass;
|
||||
$oPage->add("<td class=\"ibo-dashboard--grid-column ibo-dashboard--grid-cell $sCellClass\" style=\"".implode(' ', $aStyleProperties)."\" data-dashboard-grid-column-index=\"$iCols\" data-dashboard-grid-cell-index=\"$iCellIdx\">");
|
||||
if (array_key_exists($iCellIdx, $aCells))
|
||||
{
|
||||
if (array_key_exists($iCellIdx, $aCells)) {
|
||||
$aDashlets = $aCells[$iCellIdx];
|
||||
if (count($aDashlets) > 0)
|
||||
{
|
||||
if (count($aDashlets) > 0) {
|
||||
/** @var \Dashlet $oDashlet */
|
||||
foreach($aDashlets as $oDashlet)
|
||||
{
|
||||
if ($oDashlet::IsVisible())
|
||||
{
|
||||
$oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams);
|
||||
foreach ($aDashlets as $oDashlet) {
|
||||
if ($oDashlet::IsVisible()) {
|
||||
$oDashboardColumn->AddUIBlock($oDashlet->DoRender($oPage, $bEditMode, true /* bEnclosingDiv */, $aExtraParams));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add(' ');
|
||||
}
|
||||
} else {
|
||||
$oDashboardColumn->AddUIBlock(new Html(' '));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add(' ');
|
||||
}
|
||||
$oPage->add('</td>');
|
||||
$iCellIdx++;
|
||||
}
|
||||
$oPage->add('</tr>');
|
||||
}
|
||||
|
||||
if ($bEditMode) // Add one row for extensibility
|
||||
{
|
||||
$oPage->add("<tr class=\"ibo-dashboard--grid-row\" data-dashboard-grid-row-index=\"$iRows\">");
|
||||
for($iCols = 0; $iCols < $this->iNbCols; $iCols++)
|
||||
{
|
||||
$oPage->add("<td class=\"ibo-dashboard--grid-column ibo-dashboard--grid-cell layout_cell edit_mode layout_extension\" style=\"".implode(' ', $aStyleProperties)."\" data-dashboard-grid-column-index=\"$iCols\" data-dashboard-grid-cell-index=\"$iCellIdx\">");
|
||||
$oPage->add(' ');
|
||||
$oPage->add('</td>');
|
||||
$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(' '));
|
||||
}
|
||||
$oPage->add('</tr>');
|
||||
}
|
||||
$oPage->add('</tbody></table>');
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with iTop. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
use Combodo\iTop\Application\UI\Component\Dashlet\DashletContainer;
|
||||
use Combodo\iTop\Application\UI\Component\Dashlet\DashletFactory;
|
||||
use Combodo\iTop\Application\UI\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Component\Panel\PanelFactory;
|
||||
use Combodo\iTop\Application\UI\iUIBlock;
|
||||
|
||||
require_once(APPROOT.'application/forms.class.inc.php');
|
||||
|
||||
@@ -69,21 +72,14 @@ abstract class Dashlet
|
||||
{
|
||||
$refValue = $this->aProperties[$sProperty];
|
||||
$sRefType = gettype($refValue);
|
||||
if (gettype($sValue) == $sRefType)
|
||||
{
|
||||
if (gettype($sValue) == $sRefType) {
|
||||
// Do not change anything in that case!
|
||||
$ret = $sValue;
|
||||
}
|
||||
elseif ($sRefType == 'boolean')
|
||||
{
|
||||
} elseif ($sRefType == 'boolean') {
|
||||
$ret = ($sValue == 'true');
|
||||
}
|
||||
elseif ($sRefType == 'array')
|
||||
{
|
||||
} elseif (($sRefType == 'array') || (is_array($sValue))) {
|
||||
$ret = explode(',', $sValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$ret = $sValue;
|
||||
settype($ret, $sRefType);
|
||||
}
|
||||
@@ -212,77 +208,57 @@ abstract class Dashlet
|
||||
*/
|
||||
public function DoRender($oPage, $bEditMode = false, $bEnclosingDiv = true, $aExtraParams = array())
|
||||
{
|
||||
$sCSSClasses = implode(' ', $this->aCSSClasses);
|
||||
$sId = $this->GetID();
|
||||
if ($bEnclosingDiv)
|
||||
{
|
||||
if ($bEditMode)
|
||||
{
|
||||
$oPage->add('<div class="'.$sCSSClasses.'" id="dashlet_'.$sId.'">');
|
||||
|
||||
$sCSSClasses = implode(' ', $this->aCSSClasses);
|
||||
if ($bEnclosingDiv) {
|
||||
if ($bEditMode) {
|
||||
$oDashletContainer = new DashletContainer("dashlet_{$sId}");
|
||||
} else {
|
||||
$oDashletContainer = new DashletContainer();
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPage->add('<div class="'.$sCSSClasses.'">');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($this->aCSSClasses as $sCSSClass)
|
||||
{
|
||||
$oDashletContainer->AddCSSClasses($sCSSClasses);
|
||||
} else {
|
||||
$oDashletContainer = new DashletContainer();
|
||||
|
||||
foreach ($this->aCSSClasses as $sCSSClass) {
|
||||
$oPage->add_ready_script("$('#dashlet_".$sId."').addClass('$sCSSClass');");
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (get_class($this->oModelReflection) == 'ModelReflectionRuntime')
|
||||
{
|
||||
$this->Render($oPage, $bEditMode, $aExtraParams);
|
||||
try {
|
||||
if (get_class($this->oModelReflection) == 'ModelReflectionRuntime') {
|
||||
$oBlock = $this->Render($oPage, $bEditMode, $aExtraParams);
|
||||
} else {
|
||||
$oBlock = $this->RenderNoData($oPage, $bEditMode, $aExtraParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->RenderNoData($oPage, $bEditMode, $aExtraParams);
|
||||
}
|
||||
}
|
||||
catch(UnknownClassOqlException $e)
|
||||
{
|
||||
$oDashletContainer->AddSubBlock($oBlock);
|
||||
} catch (UnknownClassOqlException $e) {
|
||||
// Maybe the class is part of a non-installed module, fail silently
|
||||
// Except in Edit mode
|
||||
if ($bEditMode)
|
||||
{
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oPage->add('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
|
||||
$oPage->add('</div>');
|
||||
if ($bEditMode) {
|
||||
$oDashletContainer->AddCSSClasses("dashlet-content");
|
||||
$oDashletContainer->AddHtml('<h2>'.$e->GetUserFriendlyDescription().'</h2>');
|
||||
}
|
||||
}
|
||||
catch(OqlException $e)
|
||||
{
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oPage->p($e->GetUserFriendlyDescription());
|
||||
$oPage->add('</div>');
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oPage->p($e->getMessage());
|
||||
$oPage->add('</div>');
|
||||
} catch (OqlException $e) {
|
||||
$oDashletContainer->AddCSSClasses("dashlet-content");
|
||||
$oDashletContainer->AddHtml('<p>'.$e->GetUserFriendlyDescription().'</p>');
|
||||
} catch (Exception $e) {
|
||||
$oDashletContainer->AddCSSClasses("dashlet-content");
|
||||
$oDashletContainer->AddHtml('<p>'.$e->getMessage().'</p>');
|
||||
}
|
||||
|
||||
if ($bEnclosingDiv)
|
||||
{
|
||||
$oPage->add('</div>');
|
||||
}
|
||||
|
||||
if ($bEditMode)
|
||||
{
|
||||
if ($bEditMode) {
|
||||
$sClass = get_class($this);
|
||||
$sType = $this->sDashletType;
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
$('#dashlet_$sId').dashlet({dashlet_id: '$sId', dashlet_class: '$sClass', 'dashlet_type': '$sType'});
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
return $oDashletContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -306,7 +282,7 @@ EOF
|
||||
* @param bool $bEditMode
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @return mixed
|
||||
* @return iUIBlock
|
||||
*/
|
||||
abstract public function Render($oPage, $bEditMode = false, $aExtraParams = array());
|
||||
|
||||
@@ -316,10 +292,12 @@ EOF
|
||||
* @param \WebPage $oPage
|
||||
* @param bool $bEditMode
|
||||
* @param array $aExtraParams
|
||||
*
|
||||
* @return iUIBlock
|
||||
*/
|
||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$this->Render($oPage, $bEditMode, $aExtraParams);
|
||||
return $this->Render($oPage, $bEditMode, $aExtraParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -622,12 +600,12 @@ class DashletUnknown extends Dashlet
|
||||
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
||||
$sExplainText = ($bEditMode) ? Dict::Format('UI:DashletUnknown:RenderText:Edit', $this->GetDashletType()) : Dict::S('UI:DashletUnknown:RenderText:View');
|
||||
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$oPage->add('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||
$oPage->add('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
|
||||
$oPage->add('</div>');
|
||||
return $oDashletContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -642,12 +620,12 @@ class DashletUnknown extends Dashlet
|
||||
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
||||
$sExplainText = Dict::Format('UI:DashletUnknown:RenderNoDataText:Edit', $this->GetDashletType());
|
||||
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$oPage->add('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||
$oPage->add('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-image"><img src="'.$sIconUrl.'" /></div>');
|
||||
$oDashletContainer->AddHtml('<div class="dashlet-ukn-text">'.$sExplainText.'</div>');
|
||||
|
||||
$oPage->add('</div>');
|
||||
return $oDashletContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -766,9 +744,9 @@ class DashletProxy extends DashletUnknown
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
// This should never be called.
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oPage->add('<div>This dashlet is not supposed to be rendered as it is just a proxy for third-party widgets.</div>');
|
||||
$oPage->add('</div>');
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -783,12 +761,14 @@ class DashletProxy extends DashletUnknown
|
||||
$sIconUrl = utils::HtmlEntities(utils::GetAbsoluteUrlAppRoot().$aInfos['icon']);
|
||||
$sExplainText = Dict::Format('UI:DashletProxy:RenderNoDataText:Edit', $this->GetDashletType());
|
||||
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$oPage->add('<div class="dashlet-pxy-image"><img src="'.$sIconUrl.'" /></div>');
|
||||
$oPage->add('<div class="dashlet-pxy-text">'.$sExplainText.'</div>');
|
||||
$sHtml = '';
|
||||
$sHtml .= '<div class="dashlet-pxy-image"><img src="'.$sIconUrl.'" /></div>';
|
||||
$sHtml .= '<div class="dashlet-pxy-text">'.$sExplainText.'</div>';
|
||||
|
||||
$oPage->add('</div>');
|
||||
$oDashletContainer->AddHtml($sHtml);
|
||||
return $oDashletContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -819,7 +799,7 @@ class DashletEmptyCell extends Dashlet
|
||||
*/
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$oPage->add(' ');
|
||||
return new Html(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -871,8 +851,7 @@ class DashletPlainText extends Dashlet
|
||||
|
||||
$sId = 'plaintext_'.($bEditMode ? 'edit_' : '').$this->sId;
|
||||
|
||||
$oBlock = DashletFactory::MakeForDashletText($sId, $sText);
|
||||
$oPage->AddUiBlock($oBlock);
|
||||
return DashletFactory::MakeForDashletText($sId, $sText);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -924,7 +903,6 @@ class DashletObjectList extends Dashlet
|
||||
$sShowMenu = $this->aProperties['menu'] ? '1' : '0';
|
||||
|
||||
$oPanel = PanelFactory::MakeNeutral(Dict::S($sTitle));
|
||||
$oPage->AddUiBlock($oPanel);
|
||||
|
||||
$oFilter = $this->GetDBSearch($aExtraParams);
|
||||
$oBlock = new DisplayBlock($oFilter, 'list');
|
||||
@@ -934,26 +912,8 @@ class DashletObjectList extends Dashlet
|
||||
);
|
||||
$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));
|
||||
}
|
||||
|
||||
public function GetDBSearch($aExtraParams = array())
|
||||
{
|
||||
$sQuery = $this->aProperties['query'];
|
||||
if (isset($aExtraParams['query_params']))
|
||||
{
|
||||
$aQueryParams = $aExtraParams['query_params'];
|
||||
}
|
||||
elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id']))
|
||||
{
|
||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||
$aQueryParams = $oObj->ToArgsForQuery();
|
||||
}
|
||||
else
|
||||
{
|
||||
$aQueryParams = array();
|
||||
}
|
||||
|
||||
return DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
||||
return $oPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -967,22 +927,35 @@ class DashletObjectList extends Dashlet
|
||||
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$sHtmlTitle = utils::HtmlEntities($this->oModelReflection->DictString($sTitle)); // done in the itop block
|
||||
if ($sHtmlTitle != '')
|
||||
{
|
||||
if ($sHtmlTitle != '') {
|
||||
$oPage->add('<h1>'.$sHtmlTitle.'</h1>');
|
||||
}
|
||||
$oQuery = $this->oModelReflection->GetQuery($sQuery);
|
||||
$sClass = $oQuery->GetClass();
|
||||
$oPage->add('<div id="block_fake_'.$this->sId.'" class="display_block">');
|
||||
$oPage->p(Dict::S('UI:NoObjectToDisplay'));
|
||||
if ($bShowMenu)
|
||||
{
|
||||
if ($bShowMenu) {
|
||||
$oPage->p('<a>'.Dict::Format('UI:ClickToCreateNew', $this->oModelReflection->GetName($sClass)).'</a>');
|
||||
}
|
||||
$oPage->add('</div>');
|
||||
$oPage->add('</div>');
|
||||
}
|
||||
|
||||
public function GetDBSearch($aExtraParams = array())
|
||||
{
|
||||
$sQuery = $this->aProperties['query'];
|
||||
if (isset($aExtraParams['query_params'])) {
|
||||
$aQueryParams = $aExtraParams['query_params'];
|
||||
} elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id'])) {
|
||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||
$aQueryParams = $oObj->ToArgsForQuery();
|
||||
} else {
|
||||
$aQueryParams = array();
|
||||
}
|
||||
|
||||
return DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@@ -1200,96 +1173,81 @@ abstract class DashletGroupBy extends Dashlet
|
||||
$sStyle = $this->aProperties['style'];
|
||||
|
||||
// First perform the query - if the OQL is not ok, it will generate an exception : no need to go further
|
||||
if (isset($aExtraParams['query_params']))
|
||||
{
|
||||
if (isset($aExtraParams['query_params'])) {
|
||||
$aQueryParams = $aExtraParams['query_params'];
|
||||
}
|
||||
elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id']))
|
||||
{
|
||||
} elseif (isset($aExtraParams['this->class']) && isset($aExtraParams['this->id'])) {
|
||||
$oObj = MetaModel::GetObject($aExtraParams['this->class'], $aExtraParams['this->id']);
|
||||
$aQueryParams = $oObj->ToArgsForQuery();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$aQueryParams = array();
|
||||
}
|
||||
$oFilter = DBObjectSearch::FromOQL($sQuery, $aQueryParams);
|
||||
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
|
||||
|
||||
$sClass = $oFilter->GetClass();
|
||||
if (!$this->oModelReflection->IsValidAttCode($sClass, $this->sGroupByAttCode))
|
||||
{
|
||||
$oPage->add('<p>'.Dict::S('UI:DashletGroupBy:MissingGroupBy').'</p>');
|
||||
if (!$this->oModelReflection->IsValidAttCode($sClass, $this->sGroupByAttCode)) {
|
||||
return new Html('<p>'.Dict::S('UI:DashletGroupBy:MissingGroupBy').'</p>');
|
||||
}
|
||||
else
|
||||
{
|
||||
switch($sStyle)
|
||||
{
|
||||
case 'bars':
|
||||
$sType = 'chart';
|
||||
$aParams = array(
|
||||
'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,
|
||||
);
|
||||
$sHtmlTitle = ''; // done in the itop block
|
||||
break;
|
||||
|
||||
case 'pie':
|
||||
$sType = 'chart';
|
||||
$aParams = array(
|
||||
'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,
|
||||
);
|
||||
$sHtmlTitle = ''; // done in the itop block
|
||||
break;
|
||||
switch ($sStyle) {
|
||||
case 'bars':
|
||||
$sType = 'chart';
|
||||
$aParams = array(
|
||||
'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,
|
||||
);
|
||||
$sHtmlTitle = ''; // done in the itop block
|
||||
break;
|
||||
|
||||
case 'table':
|
||||
default:
|
||||
$sHtmlTitle = utils::HtmlEntities(Dict::S($sTitle)); // done in the itop block
|
||||
$sType = 'count';
|
||||
$aParams = array(
|
||||
'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,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'pie':
|
||||
$sType = 'chart';
|
||||
$aParams = array(
|
||||
'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,
|
||||
);
|
||||
$sHtmlTitle = ''; // done in the itop block
|
||||
break;
|
||||
|
||||
$oPanel = PanelFactory::MakeNeutral(Dict::S($sTitle));
|
||||
$oPage->AddUiBlock($oPanel);
|
||||
|
||||
|
||||
// $oPage->add('<div class="dashlet-content">');
|
||||
// if ($sHtmlTitle != '')
|
||||
// {
|
||||
// $oPage->add('<div class="main_header"><h1> '.$sHtmlTitle.'</h1></div>');
|
||||
// }
|
||||
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
||||
$oBlock = new DisplayBlock($oFilter, $sType);
|
||||
$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
||||
if ($bEditMode) {
|
||||
$oPanel->AddHtml('<div class="dashlet-blocker"></div>');
|
||||
}
|
||||
// $oPage->add('</div>');
|
||||
case 'table':
|
||||
default:
|
||||
$sHtmlTitle = utils::HtmlEntities(Dict::S($sTitle)); // done in the itop block
|
||||
$sType = 'count';
|
||||
$aParams = array(
|
||||
'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,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
$oPanel = PanelFactory::MakeNeutral(Dict::S($sTitle));
|
||||
|
||||
|
||||
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
||||
$oBlock = new DisplayBlock($oFilter, $sType);
|
||||
$oBlock->DisplayIntoContentBlock($oPanel, $oPage, $sBlockId, array_merge($aExtraParams, $aParams));
|
||||
if ($bEditMode) {
|
||||
$oPanel->AddHtml('<div class="dashlet-blocker"></div>');
|
||||
}
|
||||
return $oPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1372,9 +1330,9 @@ abstract class DashletGroupBy extends Dashlet
|
||||
*/
|
||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oPage->add('error!');
|
||||
$oPage->add('</div>');
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
$oDashletContainer->AddHtml('error!');
|
||||
return $oDashletContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1695,26 +1653,27 @@ class DashletGroupByPie extends DashletGroupBy
|
||||
*/
|
||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$sTitle = $this->aProperties['title'];
|
||||
|
||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||
|
||||
$HTMLsTitle = ($sTitle != '') ? '<h1 style="text-align:center">'.utils::HtmlEntities($sTitle).'</h1>' : '';
|
||||
$oPage->add("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
||||
$oDashletContainer->AddHtml("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
||||
|
||||
$aDisplayValues = $this->MakeSimulatedData();
|
||||
|
||||
$aColumns = array();
|
||||
$aNames = array();
|
||||
foreach($aDisplayValues as $idx => $aValue)
|
||||
{
|
||||
foreach ($aDisplayValues as $idx => $aValue) {
|
||||
$aColumns[] = array('series_'.$idx, (int)$aValue['value']);
|
||||
$aNames['series_'.$idx] = $aValue['label'];
|
||||
}
|
||||
$sJSColumns = json_encode($aColumns);
|
||||
$sJSNames = json_encode($aNames);
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
window.setTimeout(function() {
|
||||
var chart = c3.generate({
|
||||
bindto: '#{$sBlockId}',
|
||||
@@ -1735,6 +1694,8 @@ var chart = c3.generate({
|
||||
});}, 100);
|
||||
EOF
|
||||
);
|
||||
|
||||
return $oDashletContainer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1767,25 +1728,26 @@ class DashletGroupByBars extends DashletGroupBy
|
||||
*/
|
||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$sTitle = $this->aProperties['title'];
|
||||
|
||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||
|
||||
$HTMLsTitle = ($sTitle != '') ? '<h1 style="text-align:center">'.utils::HtmlEntities($sTitle).'</h1>' : '';
|
||||
$oPage->add("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
||||
$oDashletContainer->AddHtml("<div style=\"background-color:#fff;padding:0.25em;\">$HTMLsTitle<div id=\"$sBlockId\" style=\"background-color:#fff;\"></div></div>");
|
||||
|
||||
$aDisplayValues = $this->MakeSimulatedData();
|
||||
|
||||
$aNames = array();
|
||||
foreach($aDisplayValues as $idx => $aValue)
|
||||
{
|
||||
foreach ($aDisplayValues as $idx => $aValue) {
|
||||
$aNames[$idx] = $aValue['label'];
|
||||
}
|
||||
$sJSNames = json_encode($aNames);
|
||||
|
||||
$sJson = json_encode($aDisplayValues);
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
<<<EOF
|
||||
window.setTimeout(function() {
|
||||
var chart = c3.generate({
|
||||
bindto: '#{$sBlockId}',
|
||||
@@ -1833,6 +1795,8 @@ window.setTimeout(function() {
|
||||
}, 100);
|
||||
EOF
|
||||
);
|
||||
|
||||
return $oDashletContainer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1864,40 +1828,44 @@ class DashletGroupByTable extends DashletGroupBy
|
||||
*/
|
||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$oDashletContainer = new DashletContainer();
|
||||
|
||||
$aDisplayValues = $this->MakeSimulatedData();
|
||||
$iTotal = 0;
|
||||
foreach($aDisplayValues as $iRow => $aDisplayData)
|
||||
{
|
||||
foreach ($aDisplayValues as $iRow => $aDisplayData) {
|
||||
$iTotal += $aDisplayData['value'];
|
||||
}
|
||||
|
||||
|
||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||
|
||||
$oPage->add('<div id="'.$sBlockId.'" class="display_block">');
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oPage->add('<p>'.Dict::Format('UI:Pagination:HeaderNoSelection', $iTotal).'</p>');
|
||||
$oPage->add('<table class="listResults">');
|
||||
$oPage->add('<thead>');
|
||||
$oPage->add('<tr>');
|
||||
$oPage->add('<th class="header" title="">'.$this->sGroupByLabel.'</th>');
|
||||
$oPage->add('<th class="header" title="'.Dict::S('UI:GroupBy:Count+').'">'.Dict::S('UI:GroupBy:Count').'</th>');
|
||||
$oPage->add('</tr>');
|
||||
$oPage->add('</thead>');
|
||||
$oPage->add('<tbody>');
|
||||
foreach($aDisplayValues as $aDisplayData)
|
||||
{
|
||||
$oPage->add('<tr class="even">');
|
||||
$oPage->add('<td class=""><span title="Active">'.$aDisplayData['label'].'</span></td>');
|
||||
$oPage->add('<td class=""><a>'.$aDisplayData['value'].'</a></td>');
|
||||
$oPage->add('</tr>');
|
||||
$sHtml = '';
|
||||
$sHtml .= '<div id="'.$sBlockId.'" class="display_block">';
|
||||
$sHtml .= '<div class="dashlet-content">';
|
||||
$sHtml .= '<p>'.Dict::Format('UI:Pagination:HeaderNoSelection', $iTotal).'</p>';
|
||||
$sHtml .= '<table class="listResults">';
|
||||
$sHtml .= '<thead>';
|
||||
$sHtml .= '<tr>';
|
||||
$sHtml .= '<th class="header" title="">'.$this->sGroupByLabel.'</th>';
|
||||
$sHtml .= '<th class="header" title="'.Dict::S('UI:GroupBy:Count+').'">'.Dict::S('UI:GroupBy:Count').'</th>';
|
||||
$sHtml .= '</tr>';
|
||||
$sHtml .= '</thead>';
|
||||
$sHtml .= '<tbody>';
|
||||
foreach ($aDisplayValues as $aDisplayData) {
|
||||
$sHtml .= '<tr class="even">';
|
||||
$sHtml .= '<td class=""><span title="Active">'.$aDisplayData['label'].'</span></td>';
|
||||
$sHtml .= '<td class=""><a>'.$aDisplayData['value'].'</a></td>';
|
||||
$sHtml .= '</tr>';
|
||||
}
|
||||
$oPage->add('</tbody>');
|
||||
$oPage->add('</table>');
|
||||
$oPage->add('</div>');
|
||||
$sHtml .= '</tbody>';
|
||||
$sHtml .= '</table>';
|
||||
$sHtml .= '</div>';
|
||||
|
||||
$oPage->add('</div>');
|
||||
$sHtml .= '</div>';
|
||||
|
||||
$oDashletContainer->AddHtml($sHtml);
|
||||
|
||||
return $oDashletContainer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1926,8 +1894,7 @@ class DashletHeaderStatic extends Dashlet
|
||||
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
||||
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
||||
|
||||
$oBlock = DashletFactory::MakeForDashletHeaderStatic($this->oModelReflection->DictString($sTitle), $sIconPath);
|
||||
$oPage->AddUiBlock($oBlock);
|
||||
return DashletFactory::MakeForDashletHeaderStatic($this->oModelReflection->DictString($sTitle), $sIconPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2074,7 +2041,6 @@ class DashletHeaderDynamic extends Dashlet
|
||||
}
|
||||
|
||||
$oPanel = PanelFactory::MakeEnhancedNeutral(Dict::S(str_replace('_', ':', $sTitle)), $sIconPath);
|
||||
$oPage->AddUiBlock($oPanel);
|
||||
|
||||
if (isset($aExtraParams['query_params'])) {
|
||||
$aQueryParams = $aExtraParams['query_params'];
|
||||
@@ -2096,8 +2062,7 @@ class DashletHeaderDynamic extends Dashlet
|
||||
$sHyperlink = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=search&'.$oAppContext->GetForLink().'&filter='.rawurlencode($oFilter->serialize());
|
||||
$oSubTitle->AddHtml('<a class="summary" href="'.$sHyperlink.'">'.Dict::Format(str_replace('_', ':', $sSubtitle), $iCount).'</a>');
|
||||
|
||||
// $oPage->add('</div>');
|
||||
// $oPage->add('</div>');
|
||||
return $oPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2117,46 +2082,48 @@ class DashletHeaderDynamic extends Dashlet
|
||||
$oIconSelect = $this->oModelReflection->GetIconSelectionField('icon');
|
||||
$sIconPath = utils::HtmlEntities($oIconSelect->MakeFileUrl($sIcon));
|
||||
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$oPage->add('<div class="main_header">');
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$oPage->add('<img src="'.$sIconPath.'">');
|
||||
$sHtml = '';
|
||||
$sHtml .= '<img src="'.$sIconPath.'">';
|
||||
|
||||
$sBlockId = 'block_fake_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occuring in the same DOM)
|
||||
|
||||
$iTotal = 0;
|
||||
$aValues = $this->GetValues();
|
||||
|
||||
$oPage->add('<div class="display_block" id="'.$sBlockId.'">');
|
||||
$oPage->add('<div class="summary-details">');
|
||||
$oPage->add('<table><tbody>');
|
||||
$oPage->add('<tr>');
|
||||
foreach ($aValues as $sValue)
|
||||
{
|
||||
$sHtml .= '<div class="display_block" id="'.$sBlockId.'">';
|
||||
$sHtml .= '<div class="summary-details">';
|
||||
$sHtml .= '<table><tbody>';
|
||||
$sHtml .= '<tr>';
|
||||
foreach ($aValues as $sValue) {
|
||||
$sValueLabel = $this->oModelReflection->GetValueLabel($sClass, $sGroupBy, $sValue);
|
||||
$oPage->add(' <th>'.$sValueLabel.'</th>');
|
||||
$sHtml .= ' <th>'.$sValueLabel.'</th>';
|
||||
}
|
||||
$oPage->add('</tr>');
|
||||
$oPage->add('<tr>');
|
||||
foreach ($aValues as $sValue)
|
||||
{
|
||||
$iCount = (int) rand(2, 100);
|
||||
$sHtml .= '</tr>';
|
||||
$sHtml .= '<tr>';
|
||||
foreach ($aValues as $sValue) {
|
||||
$iCount = (int)rand(2, 100);
|
||||
$iTotal += $iCount;
|
||||
$oPage->add(' <td>'.$iCount.'</td>');
|
||||
$sHtml .= ' <td>'.$iCount.'</td>';
|
||||
}
|
||||
$oPage->add('</tr>');
|
||||
$oPage->add('</tbody></table>');
|
||||
$oPage->add('</div>');
|
||||
$sHtml .= '</tr>';
|
||||
$sHtml .= '</tbody></table>';
|
||||
$sHtml .= '</div>';
|
||||
|
||||
$sTitle = $this->oModelReflection->DictString($sTitle);
|
||||
$sSubtitle = $this->oModelReflection->DictFormat($sSubtitle, $iTotal);
|
||||
|
||||
$oPage->add('<h1>'.utils::HtmlEntities($sTitle).'</h1>');
|
||||
$oPage->add('<a class="summary">'.utils::HtmlEntities($sSubtitle).'</a>');
|
||||
$oPage->add('</div>');
|
||||
$sHtml .= '<h1>'.utils::HtmlEntities($sTitle).'</h1>';
|
||||
$sHtml .= '<a class="summary">'.utils::HtmlEntities($sSubtitle).'</a>';
|
||||
$sHtml .= '</div>';
|
||||
|
||||
$sHtml .= '</div>';
|
||||
|
||||
$oDashletContainer->AddHtml($sHtml);
|
||||
|
||||
return $oDashletContainer;
|
||||
|
||||
$oPage->add('</div>');
|
||||
$oPage->add('</div>');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2312,17 +2279,16 @@ class DashletBadge extends Dashlet
|
||||
*/
|
||||
public function Render($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$sClass = $this->aProperties['class'];
|
||||
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
$oBlock = new DisplayBlock($oFilter, 'actions');
|
||||
$aExtraParams['context_filter'] = 1;
|
||||
$sBlockId = 'block_'.$this->sId.($bEditMode ? '_edit' : ''); // make a unique id (edition occurring in the same DOM)
|
||||
$oBlock->Display($oPage, $sBlockId, $aExtraParams);
|
||||
$oBlock->DisplayIntoContentBlock($oDashletContainer, $oPage, $sBlockId, $aExtraParams);
|
||||
|
||||
$oPage->add('</div>');
|
||||
return $oDashletContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2330,23 +2296,25 @@ class DashletBadge extends Dashlet
|
||||
*/
|
||||
public function RenderNoData($oPage, $bEditMode = false, $aExtraParams = array())
|
||||
{
|
||||
$sClass = $this->aProperties['class'];
|
||||
$oDashletContainer = new DashletContainer(null, 'dashlet-content');
|
||||
|
||||
$sClass = $this->aProperties['class'];
|
||||
$sIconUrl = $this->oModelReflection->GetClassIcon($sClass, false);
|
||||
$sClassLabel = $this->oModelReflection->GetName($sClass);
|
||||
|
||||
$oPage->add('<div class="dashlet-content">');
|
||||
$sHtml = '';
|
||||
$sHtml .= '<div id="block_fake_'.$this->sId.'" class="display_block">';
|
||||
$sHtml .= '<p>';
|
||||
$sHtml .= ' <a class="actions"><img src="'.utils::HtmlEntities($sIconUrl).'" style="vertical-align:middle;float;left;margin-right:10px;border:0;">'.$sClassLabel.': 947</a>';
|
||||
$sHtml .= '</p>';
|
||||
$sHtml .= '<p>';
|
||||
$sHtml .= ' <a>'.Dict::Format('UI:ClickToCreateNew', $sClassLabel).'</a>';
|
||||
$sHtml .= '</p>';
|
||||
$sHtml .= '</div>';
|
||||
|
||||
$oPage->add('<div id="block_fake_'.$this->sId.'" class="display_block">');
|
||||
$oPage->add('<p>');
|
||||
$oPage->add(' <a class="actions"><img src="'.utils::HtmlEntities($sIconUrl).'" style="vertical-align:middle;float;left;margin-right:10px;border:0;">'.$sClassLabel.': 947</a>');
|
||||
$oPage->add('</p>');
|
||||
$oPage->add('<p>');
|
||||
$oPage->add(' <a>'.Dict::Format('UI:ClickToCreateNew', $sClassLabel).'</a>');
|
||||
$oPage->add('</p>');
|
||||
$oPage->add('</div>');
|
||||
$oDashletContainer->AddHtml($sHtml);
|
||||
|
||||
$oPage->add('</div>');
|
||||
return $oDashletContainer;
|
||||
}
|
||||
|
||||
static protected $aClassList = null;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
$ibo-badge--margin: 0px 8px !default;
|
||||
$ibo-badge--margin: 4px 8px !default;
|
||||
$ibo-badge--padding: 6px 10px !default;
|
||||
$ibo-badge--border-radius: $ibo-border-radius-300 !default;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ $ibo-dashlet-header-dynamic--count--margin-right: 10px !default;
|
||||
/* Rules */
|
||||
.ibo-dashlet-header-dynamic--container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,31 +17,39 @@ $ibo-dashboard--grid--elements-spacing-y: $ibo-dashlet--elements-spacing-y !defa
|
||||
width: $ibo-dashboard--grid--width;
|
||||
}
|
||||
.ibo-dashboard--grid-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: hidden; /* Because of the column negative margin (which is for the dashlets spacing) */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
overflow: hidden; /* Because of the column negative margin (which is for the dashlets spacing) */
|
||||
|
||||
/* Compensate negative margin on inner borders to simulate egal dashlets spacing between rows */
|
||||
&:not(:last-child){
|
||||
padding-bottom: calc(#{$ibo-dashboard--grid--elements-spacing-y} / 2);
|
||||
}
|
||||
&:not(:first-child){
|
||||
padding-top: calc(#{$ibo-dashboard--grid--elements-spacing-y} / 2);
|
||||
}
|
||||
/* Compensate negative margin on inner borders to simulate egal dashlets spacing between rows */
|
||||
&:not(:last-child) {
|
||||
padding-bottom: calc(#{$ibo-dashboard--grid--elements-spacing-y} / 2);
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
padding-top: calc(#{$ibo-dashboard--grid--elements-spacing-y} / 2);
|
||||
}
|
||||
}
|
||||
.ibo-dashboard--grid-column{
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
width: calc(100% + (2 * #{$ibo-dashboard--grid--elements-spacing-x}));
|
||||
margin: calc(-1 * #{$ibo-dashboard--grid--elements-spacing-y} / 2) calc(-1 * #{$ibo-dashboard--grid--elements-spacing-x} / 2); /* Because of the margin all around the dashlets, we need to compensate it */
|
||||
|
||||
/* Compensate negative margin on inner borders to simulate egal dashlets spacing between columns */
|
||||
&:not(:last-child) {
|
||||
margin-right: 0;
|
||||
}
|
||||
&:not(:first-child) {
|
||||
margin-left: 0;
|
||||
}
|
||||
.ibo-dashboard--grid-column {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
width: calc(100% + (2 * #{$ibo-dashboard--grid--elements-spacing-x}));
|
||||
margin: calc(-1 * #{$ibo-dashboard--grid--elements-spacing-y} / 2) calc(-1 * #{$ibo-dashboard--grid--elements-spacing-x} / 2); /* Because of the margin all around the dashlets, we need to compensate it */
|
||||
|
||||
/* Compensate negative margin on inner borders to simulate egal dashlets spacing between columns */
|
||||
&:not(:last-child) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-dashboard--grid-column.edit-mode {
|
||||
border: 1px #ccc dashed;
|
||||
}
|
||||
@@ -158,7 +158,7 @@ return array(
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Button\\Button' => $baseDir . '/sources/application/UI/Component/Button/Button.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Button\\ButtonFactory' => $baseDir . '/sources/application/UI/Component/Button/ButtonFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletBadge' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletBadge.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletComponent' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletComponent.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletContainer' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletContainer.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletFactory' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletHeaderStatic' => $baseDir . '/sources/application/UI/Component/Dashlet/DashletHeaderStatic.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => $baseDir . '/sources/application/UI/Component/FieldSet/FieldSet.php',
|
||||
@@ -210,6 +210,9 @@ return array(
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\ActivityPanel\\ActivityNewEntryForm\\ActivityNewEntryForm' => $baseDir . '/sources/application/UI/Layout/ActivityPanel/ActivityNewEntryForm/ActivityNewEntryForm.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\ActivityPanel\\ActivityPanel' => $baseDir . '/sources/application/UI/Layout/ActivityPanel/ActivityPanel.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\ActivityPanel\\ActivityPanelFactory' => $baseDir . '/sources/application/UI/Layout/ActivityPanel/ActivityPanelFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\Dashboard\\DashboardColumn' => $baseDir . '/sources/application/UI/Layout/Dashboard/DashboardColumn.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\Dashboard\\DashboardLayout' => $baseDir . '/sources/application/UI/Layout/Dashboard/DashboardLayout.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\Dashboard\\DashboardRow' => $baseDir . '/sources/application/UI/Layout/Dashboard/DashboardRow.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\MultiColumn\\Column\\Column' => $baseDir . '/sources/application/UI/Layout/MultiColumn/Column/Column.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\MultiColumn\\MultiColumn' => $baseDir . '/sources/application/UI/Layout/MultiColumn/MultiColumn.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\NavigationMenu\\NavigationMenu' => $baseDir . '/sources/application/UI/Layout/NavigationMenu/NavigationMenu.php',
|
||||
|
||||
@@ -388,7 +388,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Button\\Button' => __DIR__ . '/../..' . '/sources/application/UI/Component/Button/Button.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Button\\ButtonFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/Button/ButtonFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletBadge' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletBadge.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletComponent' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletComponent.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletContainer' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletContainer.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletFactory' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\Dashlet\\DashletHeaderStatic' => __DIR__ . '/../..' . '/sources/application/UI/Component/Dashlet/DashletHeaderStatic.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Component\\FieldSet\\FieldSet' => __DIR__ . '/../..' . '/sources/application/UI/Component/FieldSet/FieldSet.php',
|
||||
@@ -440,6 +440,9 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\ActivityPanel\\ActivityNewEntryForm\\ActivityNewEntryForm' => __DIR__ . '/../..' . '/sources/application/UI/Layout/ActivityPanel/ActivityNewEntryForm/ActivityNewEntryForm.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\ActivityPanel\\ActivityPanel' => __DIR__ . '/../..' . '/sources/application/UI/Layout/ActivityPanel/ActivityPanel.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\ActivityPanel\\ActivityPanelFactory' => __DIR__ . '/../..' . '/sources/application/UI/Layout/ActivityPanel/ActivityPanelFactory.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\Dashboard\\DashboardColumn' => __DIR__ . '/../..' . '/sources/application/UI/Layout/Dashboard/DashboardColumn.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\Dashboard\\DashboardLayout' => __DIR__ . '/../..' . '/sources/application/UI/Layout/Dashboard/DashboardLayout.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\Dashboard\\DashboardRow' => __DIR__ . '/../..' . '/sources/application/UI/Layout/Dashboard/DashboardRow.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\MultiColumn\\Column\\Column' => __DIR__ . '/../..' . '/sources/application/UI/Layout/MultiColumn/Column/Column.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\MultiColumn\\MultiColumn' => __DIR__ . '/../..' . '/sources/application/UI/Layout/MultiColumn/MultiColumn.php',
|
||||
'Combodo\\iTop\\Application\\UI\\Layout\\NavigationMenu\\NavigationMenu' => __DIR__ . '/../..' . '/sources/application/UI/Layout/NavigationMenu/NavigationMenu.php',
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
namespace Combodo\iTop\Application\UI\Component\Dashlet;
|
||||
|
||||
|
||||
class DashletBadge extends DashletComponent
|
||||
class DashletBadge extends DashletContainer
|
||||
{
|
||||
public const BLOCK_CODE = 'ibo-dashlet-badge';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'components/dashlet/dashletbadge';
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Component\Dashlet;
|
||||
|
||||
|
||||
use Combodo\iTop\Application\UI\UIBlock;
|
||||
|
||||
class DashletComponent extends UIBlock
|
||||
{
|
||||
public const BLOCK_CODE = 'ibo-dashlet';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'components/dashlet/layout';
|
||||
|
||||
public function __construct(?string $sId = null)
|
||||
{
|
||||
parent::__construct($sId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Component\Dashlet;
|
||||
|
||||
|
||||
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
|
||||
|
||||
class DashletContainer extends UIContentBlock
|
||||
{
|
||||
public const BLOCK_CODE = 'ibo-dashlet';
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
namespace Combodo\iTop\Application\UI\Component\Dashlet;
|
||||
|
||||
|
||||
class DashletHeaderStatic extends DashletComponent
|
||||
class DashletHeaderStatic extends DashletContainer
|
||||
{
|
||||
public const BLOCK_CODE = 'ibo-dashlet-header-static';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'components/dashlet/dashletheaderstatic';
|
||||
|
||||
114
sources/application/UI/Layout/Dashboard/DashboardColumn.php
Normal file
114
sources/application/UI/Layout/Dashboard/DashboardColumn.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Layout\Dashboard;
|
||||
|
||||
|
||||
use Combodo\iTop\Application\UI\UIBlock;
|
||||
|
||||
class DashboardColumn extends UIBlock
|
||||
{
|
||||
public const BLOCK_CODE = 'ibo-dashboard-column';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'layouts/dashboard/column/layout';
|
||||
|
||||
/** @var UIBlock[] */
|
||||
protected $aUIBlocks;
|
||||
/** @var int */
|
||||
protected $iColumnIndex;
|
||||
/** @var int */
|
||||
protected $iCellIndex;
|
||||
/** @var bool */
|
||||
protected $bEditMode;
|
||||
/** @var bool */
|
||||
protected $bLastRow;
|
||||
|
||||
public function __construct(bool $bEditMode = false, bool $bLastRow = false)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->aUIBlocks = [];
|
||||
$this->iColumnIndex = 0;
|
||||
$this->iCellIndex = 0;
|
||||
$this->bEditMode = $bEditMode;
|
||||
$this->bLastRow = $bLastRow;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param UIBlock $oUIBlock
|
||||
*
|
||||
* @return DashboardColumn
|
||||
*/
|
||||
public function AddUIBlock(UIBlock $oUIBlock): DashboardColumn
|
||||
{
|
||||
$this->aUIBlocks[] = $oUIBlock;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function GetSubBlocks()
|
||||
{
|
||||
return $this->aUIBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function GetColumnIndex(): int
|
||||
{
|
||||
return $this->iColumnIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iColumnIndex
|
||||
*
|
||||
* @return DashboardColumn
|
||||
*/
|
||||
public function SetColumnIndex(int $iColumnIndex): DashboardColumn
|
||||
{
|
||||
$this->iColumnIndex = $iColumnIndex;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsEditMode(): bool
|
||||
{
|
||||
return $this->bEditMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bEditMode
|
||||
*
|
||||
* @return DashboardColumn
|
||||
*/
|
||||
public function SetEditMode(bool $bEditMode): DashboardColumn
|
||||
{
|
||||
$this->bEditMode = $bEditMode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function GetCellIndex(): int
|
||||
{
|
||||
return $this->iCellIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iCellIndex
|
||||
*
|
||||
* @return DashboardColumn
|
||||
*/
|
||||
public function SetCellIndex(int $iCellIndex): DashboardColumn
|
||||
{
|
||||
$this->iCellIndex = $iCellIndex;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
47
sources/application/UI/Layout/Dashboard/DashboardLayout.php
Normal file
47
sources/application/UI/Layout/Dashboard/DashboardLayout.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Layout\Dashboard;
|
||||
|
||||
use Combodo\iTop\Application\UI\UIBlock;
|
||||
|
||||
class DashboardLayout extends UIBlock
|
||||
{
|
||||
public const BLOCK_CODE = 'ibo-dashboard';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'layouts/dashboard/layout';
|
||||
|
||||
/** @var DashboardRow[] */
|
||||
protected $aDashboardRows;
|
||||
/** @var int */
|
||||
protected $iRows;
|
||||
|
||||
public function __construct(?string $sId = null)
|
||||
{
|
||||
parent::__construct($sId);
|
||||
$this->aDashboardRows = [];
|
||||
$this->iRows = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Combodo\iTop\Application\UI\Layout\Dashboard\DashboardRow $oDashboardRow
|
||||
*
|
||||
* @return DashboardLayout
|
||||
*/
|
||||
public function AddDashboardRow(DashboardRow $oDashboardRow): DashboardLayout
|
||||
{
|
||||
$oDashboardRow->SetRowIndex($this->iRows);
|
||||
$this->aDashboardRows[] = $oDashboardRow;
|
||||
$this->iRows++;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function GetSubBlocks()
|
||||
{
|
||||
return $this->aDashboardRows;
|
||||
}
|
||||
}
|
||||
69
sources/application/UI/Layout/Dashboard/DashboardRow.php
Normal file
69
sources/application/UI/Layout/Dashboard/DashboardRow.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2010-2020 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
|
||||
namespace Combodo\iTop\Application\UI\Layout\Dashboard;
|
||||
|
||||
use Combodo\iTop\Application\UI\UIBlock;
|
||||
|
||||
class DashboardRow extends UIBlock
|
||||
{
|
||||
public const BLOCK_CODE = 'ibo-dashboard-row';
|
||||
public const HTML_TEMPLATE_REL_PATH = 'layouts/dashboard/row/layout';
|
||||
|
||||
/** @var DashboardColumn[] */
|
||||
protected $aDashboardColumns;
|
||||
/** @var int */
|
||||
protected $iRowIndex;
|
||||
/** @var int */
|
||||
protected $iCols;
|
||||
|
||||
public function __construct(?string $sId = null)
|
||||
{
|
||||
parent::__construct($sId);
|
||||
$this->aDashboardColumns = [];
|
||||
$this->iRowIndex = 0;
|
||||
$this->iCols = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \Combodo\iTop\Application\UI\Layout\Dashboard\DashboardColumn $oDashboardColumn
|
||||
*
|
||||
* @return DashboardRow
|
||||
*/
|
||||
public function AddDashboardColumn(DashboardColumn $oDashboardColumn): DashboardRow
|
||||
{
|
||||
$oDashboardColumn->SetColumnIndex($this->iCols);
|
||||
$this->aDashboardColumns[] = $oDashboardColumn;
|
||||
$this->iCols++;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function GetSubBlocks()
|
||||
{
|
||||
return $this->aDashboardColumns;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function GetRowIndex(): int
|
||||
{
|
||||
return $this->iRowIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iRowIndex
|
||||
*
|
||||
* @return DashboardRow
|
||||
*/
|
||||
public function SetRowIndex(int $iRowIndex): DashboardRow
|
||||
{
|
||||
$this->iRowIndex = $iRowIndex;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
{# @copyright Copyright (C) 2010-2020 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
{# Content Block #}
|
||||
{% apply spaceless %}
|
||||
{% block iboContentBlockContainer %}
|
||||
|
||||
|
||||
21
templates/layouts/dashboard/column/layout.html.twig
Normal file
21
templates/layouts/dashboard/column/layout.html.twig
Normal file
@@ -0,0 +1,21 @@
|
||||
{# @copyright Copyright (C) 2010-2020 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
{# Dashboard Column #}
|
||||
{% apply spaceless %}
|
||||
{% if oUIBlock.IsEditMode() %}
|
||||
{% if oUIBlock.IsLastRow() %}
|
||||
{% set sCellClass = "layout_cell edit_mode layout_extension" %}
|
||||
{% else %}
|
||||
{% set sCellClass = "layout_cell edit_mode" %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set sCellClass = "dashboard" %}
|
||||
{% endif %}
|
||||
<div class="ibo-dashboard--grid-column ibo-dashboard--grid-cell {{ sCellClass }}"
|
||||
data-dashboard-grid-column-index="{{ oUIBlock.GetColumnIndex() }}"
|
||||
data-dashboard-grid-cell-index="{{ oUIBlock.GetCellIndex() }}">
|
||||
{% for oSubBlock in oUIBlock.GetSubBlocks() %}
|
||||
{{ render_block(oSubBlock, {aPage: aPage}) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endapply %}
|
||||
10
templates/layouts/dashboard/layout.html.twig
Normal file
10
templates/layouts/dashboard/layout.html.twig
Normal file
@@ -0,0 +1,10 @@
|
||||
{# @copyright Copyright (C) 2010-2020 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
{# Dashboard Layout #}
|
||||
{% apply spaceless %}
|
||||
<div class="ibo-dashboard--grid">
|
||||
{% for oSubBlock in oUIBlock.GetSubBlocks() %}
|
||||
{{ render_block(oSubBlock, {aPage: aPage}) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endapply %}
|
||||
10
templates/layouts/dashboard/row/layout.html.twig
Normal file
10
templates/layouts/dashboard/row/layout.html.twig
Normal file
@@ -0,0 +1,10 @@
|
||||
{# @copyright Copyright (C) 2010-2020 Combodo SARL #}
|
||||
{# @license http://opensource.org/licenses/AGPL-3.0 #}
|
||||
{# Dashboard Row #}
|
||||
{% apply spaceless %}
|
||||
<div class="ibo-dashboard--grid-row" data-dashboard-grid-row-index="{{ oUIBlock.GetRowIndex() }}">
|
||||
{% for oSubBlock in oUIBlock.GetSubBlocks() %}
|
||||
{{ render_block(oSubBlock, {aPage: aPage}) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endapply %}
|
||||
Reference in New Issue
Block a user