\n");
- $oP->add_ready_script("$('#1 table.listResults').trigger('check_all');");
+ }
+
+ $oForm = new Form();
+ $oForm->SetAction('./UI.php');
+ $oForm->AddSubBlock(InputFactory::MakeForHidden('operation', $sNextOperation));
+ $oForm->AddSubBlock(InputFactory::MakeForHidden('class', $oFilter->GetClass()));
+ $oForm->AddSubBlock(InputFactory::MakeForHidden('filter', utils::HtmlEntities($oFilter->Serialize())));
+ $oForm->AddSubBlock(InputFactory::MakeForHidden('transaction_id', utils::GetNewTransactionId()));
+ foreach ($aExtraFormParams as $sName => $sValue) {
+ $oForm->AddSubBlock(InputFactory::MakeForHidden($sName, $sValue));
+ }
+ $oForm->AddSubBlock($oAppContext->GetForFormBlock());
+ $oDisplayBlock = new DisplayBlock($oFilter, 'list', false);
+ $oForm->AddSubBlock($oDisplayBlock->GetDisplay($oP, 1, $aExtraParams));
+ $oForm->AddSubBlock(ButtonFactory::MakeNeutral(Dict::S('UI:Button:Cancel'), 'cancel')->SetOnClickJsCode('window.history.back()'));
+ $oForm->AddSubBlock(ButtonFactory::MakeForPrimaryAction(Dict::S('UI:Button:Next'), 'next', Dict::S('UI:Button:Next'), true));
+
+ $oP->AddUiBlock($oForm);
+ $oP->add_ready_script("$('#1 table.listResults').trigger('check_all');");
}
function DisplayNavigatorListTab($oP, $aResults, $sRelation, $sDirection, $oObj)
diff --git a/sources/application/TwigBase/Twig/Extension.php b/sources/application/TwigBase/Twig/Extension.php
index 2db2f9515..d98be035c 100644
--- a/sources/application/TwigBase/Twig/Extension.php
+++ b/sources/application/TwigBase/Twig/Extension.php
@@ -87,8 +87,8 @@ class Extension
);
// Filter to sanitize an XML / HTML identifier
- // Usage in twig: {{ 'identifier:to-sanitize' }}
- $oTwigEnv->addFilter(new Twig_SimpleFilter('sanitize_identifier', function($sString) {
+ // Usage in twig: {{ 'identifier:to-sanitize'|sanitize_identifier }}
+ $oTwigEnv->addFilter(new Twig_SimpleFilter('sanitize_identifier', function ($sString) {
return utils::Sanitize($sString, '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
})
);
@@ -114,18 +114,23 @@ class Extension
$oTwigEnv->addFilter(new Twig_SimpleFilter('add_module_version', function ($sUrl, $sModuleName) {
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
- if (strpos($sUrl, '?') === false)
- {
+ if (strpos($sUrl, '?') === false) {
$sUrl = $sUrl."?moduleversion=".$sModuleVersion;
- }
- else
- {
+ } else {
$sUrl = $sUrl."&moduleversion=".$sModuleVersion;
}
return $sUrl;
}));
+ // Filter to sanitize a string (escape ')
+ // Usage in twig: {{ 'string'|escape_quotes }}
+ $oTwigEnv->addFilter(new Twig_SimpleFilter('escape_for_js_string', function ($sString) {
+ return str_replace(["'", "\n"], ["\\'", " "], $sString);
+ })
+ );
+
+
// Function to check our current environment
// Usage in twig: {% if is_development_environment() %}
$oTwigEnv->addFunction(new Twig_SimpleFunction('is_development_environment', function () {
diff --git a/sources/application/UI/Component/DataTable/DataTable.php b/sources/application/UI/Component/DataTable/DataTable.php
index a678ac83b..9bfaa03a8 100644
--- a/sources/application/UI/Component/DataTable/DataTable.php
+++ b/sources/application/UI/Component/DataTable/DataTable.php
@@ -8,6 +8,7 @@ namespace Combodo\iTop\Application\UI\Component\DataTable;
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
+use DataTableConfig;
/**
* Class DataTable
@@ -35,6 +36,7 @@ class DataTableBlock extends UIContentBlock
public function __construct(?string $sId = null)
{
parent::__construct($sId);
+ $this->AddDeferredBlock(new DataTableConfig($this));
}
/**
diff --git a/sources/application/UI/Component/DataTable/DataTableConfig/DataTableConfig.php b/sources/application/UI/Component/DataTable/DataTableConfig/DataTableConfig.php
new file mode 100644
index 000000000..ca0e96bf3
--- /dev/null
+++ b/sources/application/UI/Component/DataTable/DataTableConfig/DataTableConfig.php
@@ -0,0 +1,43 @@
+oDataTable = $oDataTable;
+ }
+
+ /**
+ * @return \Combodo\iTop\Application\UI\Component\DataTable\DataTableBlock
+ */
+ private function GetDataTable(): DataTableBlock
+ {
+ return $this->oDataTable;
+ }
+
+ public function GetOption(string $sOption)
+ {
+ return $this->GetDataTable()->GetOption($sOption);
+ }
+
+ public function GetTableId()
+ {
+ return $this->GetDataTable()->GetId();
+ }
+
+}
\ No newline at end of file
diff --git a/sources/application/UI/Component/DataTable/DataTableFactory.php b/sources/application/UI/Component/DataTable/DataTableFactory.php
index c4a730da0..4a4560d54 100644
--- a/sources/application/UI/Component/DataTable/DataTableFactory.php
+++ b/sources/application/UI/Component/DataTable/DataTableFactory.php
@@ -10,7 +10,6 @@ use ApplicationException;
use appUserPreferences;
use AttributeLinkedSet;
use cmdbAbstractObject;
-use CMDBObjectSet;
use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\FormTable\FormTable;
use Combodo\iTop\Application\UI\Component\DataTable\StaticTable\StaticTable;
use Combodo\iTop\Application\UI\Component\Panel\PanelFactory;
@@ -35,7 +34,7 @@ class DataTableFactory
/**
* @param \WebPage $oPage
* @param string $sListId
- * @param \CMDBObjectSet $oSet
+ * @param \DBObjectSet $oSet
* @param array $aExtraParams
*
* @return \Combodo\iTop\Application\UI\Component\Panel\Panel
@@ -50,7 +49,7 @@ class DataTableFactory
* @throws \OQLException
* @throws \ReflectionException
*/
- public static function MakeForResult(WebPage $oPage, string $sListId, CMDBObjectSet $oSet, $aExtraParams = array())
+ public static function MakeForResult(WebPage $oPage, string $sListId, DBObjectSet $oSet, $aExtraParams = array())
{
$oPanel = PanelFactory::MakeForClass($oSet->GetClass(), "Result")->AddCSSClasses('ibo-datatable-panel');
$oDataTable = DataTableFactory::MakeForRendering($sListId, $oSet, $aExtraParams);
@@ -101,7 +100,7 @@ class DataTableFactory
* Make a basis Panel component
*
* @param string $sListId
- * @param \CMDBObjectSet $oSet
+ * @param \DBObjectSet $oSet
* @param array $aExtraParams
*
* @return DataTableBlock
@@ -112,7 +111,7 @@ class DataTableFactory
* @throws \DictExceptionMissingString
* @throws \MySQLException
*/
- public static function MakeForRendering(string $sListId, CMDBObjectSet $oSet, $aExtraParams = array())
+ public static function MakeForRendering(string $sListId, DBObjectSet $oSet, $aExtraParams = array())
{
$oDataTable = new DataTableBlock('datatable_'.$sListId);
///////////////////////////////////////////////////
@@ -474,7 +473,6 @@ class DataTableFactory
$aColumnDefinition = [];
$aSortOrder=[];
- $aSortDatable=[];
$iIndexColumn=0;
if($sSelectMode!="") {
$iIndexColumn++;
diff --git a/sources/application/UI/Layout/PageContent/PageContent.php b/sources/application/UI/Layout/PageContent/PageContent.php
index 5cc7e578f..04d3cdf91 100644
--- a/sources/application/UI/Layout/PageContent/PageContent.php
+++ b/sources/application/UI/Layout/PageContent/PageContent.php
@@ -225,7 +225,8 @@ class PageContent extends UIBlock implements iUIContentBlock {
*
* @inheritDoc
*/
- public function GetSubBlocks(): array {
+ public function GetSubBlocks(): array
+ {
$aSubBlocks = [];
foreach ($this->GetContentAreas() as $oContentArea) {
$aSubBlocks = array_merge($aSubBlocks, $oContentArea->GetSubBlocks());
@@ -233,4 +234,90 @@ class PageContent extends UIBlock implements iUIContentBlock {
return $aSubBlocks;
}
+
+ public function GetDeferredBlocks(): array
+ {
+ $aSubBlocks = [];
+ foreach ($this->GetContentAreas() as $oContentArea) {
+ $aSubBlocks = array_merge($aSubBlocks, $oContentArea->GetDeferredBlocks());
+ }
+
+ return $aSubBlocks;
+ }
+
+ /**
+ * Add the $oDeferredBlock directly in the main area
+ *
+ * @inheritDoc
+ */
+ public function AddDeferredBlock(iUIBlock $oDeferredBlock)
+ {
+ $this->AddDeferredBlockToContentArea(static::ENUM_CONTENT_AREA_MAIN, $oDeferredBlock);
+
+ return $this;
+ }
+
+ /**
+ * Remove a specified subBlock from all the areas
+ *
+ * @param string $sId
+ *
+ * @return $this
+ */
+ public function RemoveDeferredBlock(string $sId)
+ {
+ foreach ($this->GetContentAreas() as $oContentArea) {
+ $oContentArea->RemoveDeferredBlock($sId);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Check if the specified subBlock is within one of all the areas
+ *
+ * @param string $sId
+ *
+ * @return bool
+ */
+ public function HasDeferredBlock(string $sId): bool
+ {
+ foreach ($this->GetContentAreas() as $oContentArea) {
+ if ($oContentArea->HasDeferredBlock($sId)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get a specific subBlock within all the areas
+ *
+ * @inheritDoc
+ */
+ public function GetDeferredBlock(string $sId): ?iUIBlock
+ {
+ foreach ($this->GetContentAreas() as $oContentArea) {
+ $oDeferredBlock = $oContentArea->GetDeferredBlock($sId);
+ if (!is_null($oDeferredBlock)) {
+ return $oDeferredBlock;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Set the MAIN AREA subBlocks
+ *
+ * @inheritDoc
+ * @return $this|\Combodo\iTop\Application\UI\Layout\iUIContentBlock
+ */
+ public function SetDeferredBlocks(array $aDeferredBlocks): iUIContentBlock
+ {
+ $this->SetContentAreaDeferredBlocks(self::ENUM_CONTENT_AREA_MAIN, $aDeferredBlocks);
+
+ return $this;
+ }
}
diff --git a/sources/application/UI/Layout/UIContentBlock.php b/sources/application/UI/Layout/UIContentBlock.php
index 8633744d6..f7be3593a 100644
--- a/sources/application/UI/Layout/UIContentBlock.php
+++ b/sources/application/UI/Layout/UIContentBlock.php
@@ -33,6 +33,8 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
protected $aDataAttributes;
/** @var array */
protected $aSubBlocks;
+ /** @var array */
+ protected $aDeferredBlocks;
/**
* UIContentBlock constructor.
@@ -45,6 +47,7 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
parent::__construct($sName);
$this->aSubBlocks = [];
+ $this->aDeferredBlocks = [];
$this->aDataAttributes = [];
$this->SetCSSClasses($sContainerClass);
}
@@ -52,7 +55,8 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
/**
* @inheritDoc
*/
- public function AddHtml(string $sHtml) {
+ public function AddHtml(string $sHtml)
+ {
$oBlock = new Html($sHtml);
$this->AddSubBlock($oBlock);
@@ -62,7 +66,8 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
/**
* @inheritDoc
*/
- public function AddSubBlock(iUIBlock $oSubBlock) {
+ public function AddSubBlock(iUIBlock $oSubBlock)
+ {
$this->aSubBlocks[$oSubBlock->GetId()] = $oSubBlock;
return $this;
@@ -71,7 +76,8 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
/**
* @inheritDoc
*/
- public function RemoveSubBlock(string $sId) {
+ public function RemoveSubBlock(string $sId)
+ {
if ($this->HasSubBlock($sId)) {
unset($this->aSubBlocks[$sId]);
}
@@ -82,28 +88,32 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
/**
* @inheritDoc
*/
- public function HasSubBlock(string $sId): bool {
+ public function HasSubBlock(string $sId): bool
+ {
return array_key_exists($sId, $this->aSubBlocks);
}
/**
* @inheritDoc
*/
- public function GetSubBlock(string $sId): ?iUIBlock {
+ public function GetSubBlock(string $sId): ?iUIBlock
+ {
return isset($this->aSubBlocks[$sId]) ? $this->aSubBlocks[$sId] : null;
}
/**
* @inheritDoc
*/
- public function GetSubBlocks(): array {
+ public function GetSubBlocks(): array
+ {
return $this->aSubBlocks;
}
/**
* @inheritDoc
*/
- public function SetSubBlocks(array $aSubBlocks) {
+ public function SetSubBlocks(array $aSubBlocks)
+ {
foreach ($aSubBlocks as $oSubBlock) {
$this->AddSubBlock($oSubBlock);
}
@@ -114,7 +124,8 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
/**
* @return string
*/
- public function GetCSSClasses(): string {
+ public function GetCSSClasses(): string
+ {
return implode(' ', $this->aCSSClasses);
}
@@ -123,7 +134,8 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
*
* @return UIContentBlock
*/
- public function SetCSSClasses(string $sCSSClasses) {
+ public function SetCSSClasses(string $sCSSClasses)
+ {
$this->aCSSClasses = [];
$this->AddCSSClasses($sCSSClasses);
@@ -135,7 +147,8 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
*
* @return $this
*/
- public function AddCSSClasses(string $sCSSClasses) {
+ public function AddCSSClasses(string $sCSSClasses)
+ {
foreach (explode(' ', $sCSSClasses) as $sCSSClass) {
if (!empty($sCSSClass)) {
$this->aCSSClasses[$sCSSClass] = $sCSSClass;
@@ -177,4 +190,62 @@ class UIContentBlock extends UIBlock implements iUIContentBlock
return $this;
}
+ /**
+ * @inheritDoc
+ */
+ public function AddDeferredBlock(iUIBlock $oDeferredBlock)
+ {
+ $this->aDeferredBlocks[$oDeferredBlock->GetId()] = $oDeferredBlock;
+
+ return $this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function RemoveDeferredBlock(string $sId)
+ {
+ if ($this->HasDeferredBlock($sId)) {
+ unset($this->aDeferredBlocks[$sId]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function HasDeferredBlock(string $sId): bool
+ {
+ return array_key_exists($sId, $this->aDeferredBlocks);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function GetDeferredBlock(string $sId): ?iUIBlock
+ {
+ return isset($this->aDeferredBlocks[$sId]) ? $this->aDeferredBlocks[$sId] : null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function GetDeferredBlocks(): array
+ {
+ return $this->aDeferredBlocks;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function SetDeferredBlocks(array $aDeferredBlocks)
+ {
+ foreach ($aDeferredBlocks as $oDeferredBlock) {
+ $this->AddDeferredBlock($oDeferredBlock);
+ }
+
+ return $this;
+ }
+
}
diff --git a/sources/application/UI/Layout/iUIContentBlock.php b/sources/application/UI/Layout/iUIContentBlock.php
index 8012f05eb..fec141e34 100644
--- a/sources/application/UI/Layout/iUIContentBlock.php
+++ b/sources/application/UI/Layout/iUIContentBlock.php
@@ -79,4 +79,59 @@ interface iUIContentBlock {
* @return $this
*/
public function SetSubBlocks(array $aSubBlocks);
+
+
+ /**
+ * Add $oDeferredBlock, replacing any block with the same ID
+ *
+ * @param \Combodo\iTop\Application\UI\iUIBlock $oDeferredBlock
+ *
+ * @return $this
+ */
+ public function AddDeferredBlock(iUIBlock $oDeferredBlock);
+
+ /**
+ * Remove the sub block identified by $sId.
+ * Note that if no sub block matches the ID, it proceeds silently.
+ *
+ * @param string $sId ID of the sub block to remove
+ *
+ * @return $this
+ */
+ public function RemoveDeferredBlock(string $sId);
+
+ /**
+ * Return true if there is a sub block identified by $sId
+ *
+ * @param string $sId
+ *
+ * @return bool
+ */
+ public function HasDeferredBlock(string $sId): bool;
+
+ /**
+ * Return the sub block identified by $sId or null if not found
+ *
+ * @param string $sId
+ *
+ * @return \Combodo\iTop\Application\UI\iUIBlock|null
+ */
+ public function GetDeferredBlock(string $sId): ?iUIBlock;
+
+ /**
+ * Return an array of all the sub blocks
+ *
+ * @return \Combodo\iTop\Application\UI\iUIBlock[]
+ */
+ public function GetDeferredBlocks(): array;
+
+ /**
+ * Set all sub blocks at once, replacing all existing ones
+ *
+ * @param \Combodo\iTop\Application\UI\iUIBlock[] $aDeferredBlocks
+ *
+ * @return $this
+ */
+ public function SetDeferredBlocks(array $aDeferredBlocks);
+
}
diff --git a/sources/application/UI/UIBlock.php b/sources/application/UI/UIBlock.php
index 4be3baa0f..163261cd4 100644
--- a/sources/application/UI/UIBlock.php
+++ b/sources/application/UI/UIBlock.php
@@ -106,14 +106,16 @@ abstract class UIBlock implements iUIBlock
/**
* @inheritDoc
*/
- public static function GetCssTemplateRelPath() {
+ public static function GetCssTemplateRelPath()
+ {
return static::CSS_TEMPLATE_REL_PATH;
}
/**
* @inheritDoc
*/
- public static function GetCssFilesRelPaths() {
+ public static function GetCssFilesRelPaths()
+ {
return static::CSS_FILES_REL_PATH;
}
@@ -123,14 +125,16 @@ abstract class UIBlock implements iUIBlock
* @return string
* @see static::BLOCK_CODE
*/
- public function GetBlockCode() {
+ public function GetBlockCode()
+ {
return static::BLOCK_CODE;
}
/**
* @inheritDoc
*/
- public function GetId() {
+ public function GetId()
+ {
return $this->sId;
}
@@ -138,7 +142,17 @@ abstract class UIBlock implements iUIBlock
* @inheritDoc
* @return \Combodo\iTop\Application\UI\iUIBlock[]
*/
- public function GetSubBlocks() {
+ public function GetSubBlocks()
+ {
+ return [];
+ }
+
+ /**
+ * @inheritDoc
+ * @return \Combodo\iTop\Application\UI\iUIBlock[]
+ */
+ public function GetDeferredBlocks(): array
+ {
return [];
}
@@ -146,7 +160,8 @@ abstract class UIBlock implements iUIBlock
* @inheritDoc
* @throws \Exception
*/
- public function GetJsFilesUrlRecursively(bool $bAbsoluteUrl = false) {
+ public function GetJsFilesUrlRecursively(bool $bAbsoluteUrl = false)
+ {
return $this->GetFilesUrlRecursively(static::ENUM_BLOCK_FILES_TYPE_JS, $bAbsoluteUrl);
}
@@ -154,7 +169,8 @@ abstract class UIBlock implements iUIBlock
* @inheritDoc
* @throws \Exception
*/
- public function GetCssFilesUrlRecursively(bool $bAbsoluteUrl = false) {
+ public function GetCssFilesUrlRecursively(bool $bAbsoluteUrl = false)
+ {
return $this->GetFilesUrlRecursively(static::ENUM_BLOCK_FILES_TYPE_CSS, $bAbsoluteUrl);
}
@@ -162,7 +178,8 @@ abstract class UIBlock implements iUIBlock
* @return array
* @throws \Exception
*/
- public function GetJsTemplateRelPathRecursively(): array {
+ public function GetJsTemplateRelPathRecursively(): array
+ {
return $this->GetUrlRecursively(static::ENUM_BLOCK_FILES_TYPE_JS, static::ENUM_BLOCK_FILES_TYPE_TEMPLATE, false);
}
@@ -170,7 +187,8 @@ abstract class UIBlock implements iUIBlock
* @return array
* @throws \Exception
*/
- public function GetCssTemplateRelPathRecursively(): array {
+ public function GetCssTemplateRelPathRecursively(): array
+ {
return $this->GetUrlRecursively(static::ENUM_BLOCK_FILES_TYPE_CSS, static::ENUM_BLOCK_FILES_TYPE_TEMPLATE, false);
}
diff --git a/sources/application/UI/iUIBlock.php b/sources/application/UI/iUIBlock.php
index ec0c6fa94..d10649291 100644
--- a/sources/application/UI/iUIBlock.php
+++ b/sources/application/UI/iUIBlock.php
@@ -86,6 +86,14 @@ interface iUIBlock {
*/
public function GetSubBlocks();
+ /**
+ * Return an array of iUIBlock to add at the end of the page
+ * Must be an associative array ( => )
+ *
+ * @return \Combodo\iTop\Application\UI\iUIBlock[]
+ */
+ public function GetDeferredBlocks(): array;
+
/**
* Return an array of the JS files URL necessary for the block and all its sub blocks.
* URLs are relative unless the $bAbsolutePath is set to true.
diff --git a/sources/application/UI/tUIContentAreas.php b/sources/application/UI/tUIContentAreas.php
index a16671b9d..770d91036 100644
--- a/sources/application/UI/tUIContentAreas.php
+++ b/sources/application/UI/tUIContentAreas.php
@@ -63,7 +63,8 @@ trait tUIContentAreas {
*
* @return $this
*/
- protected function SetContentAreaBlocks(string $sAreaId, array $aBlocks) {
+ protected function SetContentAreaBlocks(string $sAreaId, array $aBlocks)
+ {
if (!isset($this->aContentAreasBlocks[$sAreaId])) {
$this->aContentAreasBlocks[$sAreaId] = new UIContentBlock($sAreaId);
}
@@ -73,6 +74,25 @@ trait tUIContentAreas {
return $this;
}
+ /**
+ * Set all block for a content area at once, replacing all existing ones.
+ *
+ * @param string $sAreaId
+ * @param \Combodo\iTop\Application\UI\iUIBlock[] $aBlocks
+ *
+ * @return $this
+ */
+ protected function SetContentAreaDeferredBlocks(string $sAreaId, array $aBlocks)
+ {
+ if (!isset($this->aContentAreasBlocks[$sAreaId])) {
+ $this->aContentAreasBlocks[$sAreaId] = new UIContentBlock($sAreaId);
+ }
+
+ $this->aContentAreasBlocks[$sAreaId]->SetDeferredBlocks($aBlocks);
+
+ return $this;
+ }
+
/**
* Return all blocks from the $sAreaId content area
*
@@ -81,7 +101,8 @@ trait tUIContentAreas {
* @return \Combodo\iTop\Application\UI\iUIBlock[]
* @throws \Combodo\iTop\Application\UI\UIException
*/
- protected function GetContentAreaBlocks(string $sAreaId): array {
+ protected function GetContentAreaBlocks(string $sAreaId): array
+ {
if (!array_key_exists($sAreaId, $this->aContentAreasBlocks)) {
throw new UIException($this, Dict::Format('UIBlock:Error:CannotGetBlocks', $sAreaId, $this->GetId()));
}
@@ -98,7 +119,8 @@ trait tUIContentAreas {
*
* @return $this
*/
- protected function AddBlockToContentArea(string $sAreaId, iUIBlock $oBlock) {
+ protected function AddBlockToContentArea(string $sAreaId, iUIBlock $oBlock)
+ {
if (!array_key_exists($sAreaId, $this->aContentAreasBlocks)) {
$this->aContentAreasBlocks[$sAreaId] = new UIContentBlock($sAreaId);
}
@@ -108,6 +130,26 @@ trait tUIContentAreas {
return $this;
}
+ /**
+ * Add $oBlock to the $sAreaId content area.
+ * Note that if the area doesn't exist yet, it is created. Also if a block with the same ID already exists, it will be replaced.
+ *
+ * @param string $sAreaId
+ * @param \Combodo\iTop\Application\UI\iUIBlock $oBlock
+ *
+ * @return $this
+ */
+ protected function AddDeferredBlockToContentArea(string $sAreaId, iUIBlock $oBlock)
+ {
+ if (!array_key_exists($sAreaId, $this->aContentAreasBlocks)) {
+ $this->aContentAreasBlocks[$sAreaId] = new UIContentBlock($sAreaId);
+ }
+
+ $this->aContentAreasBlocks[$sAreaId]->AddDeferredBlock($oBlock);
+
+ return $this;
+ }
+
/**
* Remove the $sBlockId from the $sAreaId content area.
* Note that if the $sBlockId or the $sAreaId do not exist, it proceeds silently.
diff --git a/sources/application/WebPage/AjaxPage.php b/sources/application/WebPage/AjaxPage.php
index 5ec1737f2..b999d250e 100644
--- a/sources/application/WebPage/AjaxPage.php
+++ b/sources/application/WebPage/AjaxPage.php
@@ -165,11 +165,12 @@ EOF
}
$this->outputCollapsibleSectionInit();
- $this->RenderInlineTemplatesRecursively($this->oContentLayout);
+ $this->RenderInlineScriptsAndCSSRecursively($this->oContentLayout);
$aData = [];
$aData['oLayout'] = $this->oContentLayout;
+ $aData['aDeferredBlocks'] = $this->GetDeferredBlocks($this->oContentLayout);
$aData['aPage'] = [
'sAbsoluteUrlAppRoot' => addslashes(utils::GetAbsoluteUrlAppRoot()),
@@ -341,7 +342,7 @@ EOF
/**
* @inheritDoc
*/
- public function add_at_the_end($s_html, $sId = '')
+ public function add_at_the_end($s_html, $sId = null)
{
if ($sId != '') {
$this->add_script("$('#{$sId}').remove();"); // Remove any previous instance of the same Id
diff --git a/sources/application/WebPage/WebPage.php b/sources/application/WebPage/WebPage.php
index 1d0016463..da8be2def 100644
--- a/sources/application/WebPage/WebPage.php
+++ b/sources/application/WebPage/WebPage.php
@@ -18,9 +18,11 @@
*/
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
+use Combodo\iTop\Application\UI\Component\Html\Html;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenu;
use Combodo\iTop\Application\UI\Component\PopoverMenu\PopoverMenuFactory;
use Combodo\iTop\Application\UI\iUIBlock;
+use Combodo\iTop\Application\UI\Layout\iUIContentBlock;
use Combodo\iTop\Application\UI\Layout\UIContentBlock;
use Combodo\iTop\Renderer\BlockRenderer;
@@ -69,7 +71,7 @@ class WebPage implements Page
protected $bPrintable;
protected $bHasCollapsibleSection;
protected $bAddJSDict;
- /** @var \Combodo\iTop\Application\UI\Layout\iUIContentBlock $oContentLayout */
+ /** @var iUIContentBlock $oContentLayout */
protected $oContentLayout;
protected $sTemplateRelPath;
@@ -170,9 +172,9 @@ class WebPage implements Page
* @param string $s_html
* @param string $sId
*/
- public function add_at_the_end($s_html, $sId = '')
+ public function add_at_the_end($s_html, $sId = null)
{
- $this->s_deferred_content .= $s_html;
+ $this->oContentLayout->AddDeferredBlock(new Html($s_html, $sId));
}
/**
@@ -711,7 +713,7 @@ class WebPage implements Page
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
- public function RenderInlineTemplatesRecursively(iUIBlock $oBlock): void
+ public function RenderInlineScriptsAndCSSRecursively(iUIBlock $oBlock): void
{
$oBlockRenderer = new BlockRenderer($oBlock);
$sInlineScript = trim($oBlockRenderer->RenderJsInline());
@@ -725,8 +727,23 @@ class WebPage implements Page
}
foreach ($oBlock->GetSubBlocks() as $oSubBlock) {
- $this->RenderInlineTemplatesRecursively($oSubBlock);
+ $this->RenderInlineScriptsAndCSSRecursively($oSubBlock);
}
+
+ foreach ($oBlock->GetDeferredBlocks() as $oSubBlock) {
+ $this->RenderInlineScriptsAndCSSRecursively($oSubBlock);
+ }
+ }
+
+ public function GetDeferredBlocks(iUIBlock $oBlock): array
+ {
+ $aDeferredBlocks = $oBlock->GetDeferredBlocks();
+
+ foreach ($oBlock->GetSubBlocks() as $oSubBlock) {
+ $aDeferredBlocks = array_merge($aDeferredBlocks, $this->GetDeferredBlocks($oSubBlock));
+ }
+
+ return $aDeferredBlocks;
}
/**
@@ -745,6 +762,7 @@ class WebPage implements Page
$aData = [];
$aData['oLayout'] = $this->oContentLayout;
+ $aData['aDeferredBlocks'] = $this->GetDeferredBlocks($this->oContentLayout);
// CSS files
foreach ($this->oContentLayout->GetCssFilesUrlRecursively(true) as $sFileAbsUrl) {
@@ -756,7 +774,7 @@ class WebPage implements Page
}
// Inline Templates
- $this->RenderInlineTemplatesRecursively($this->oContentLayout);
+ $this->RenderInlineScriptsAndCSSRecursively($this->oContentLayout);
// Base structure of data to pass to the TWIG template
$aData['aPage'] = [
diff --git a/sources/application/WebPage/iTopWebPage.php b/sources/application/WebPage/iTopWebPage.php
index 3f6ff1bc6..06d01493f 100644
--- a/sources/application/WebPage/iTopWebPage.php
+++ b/sources/application/WebPage/iTopWebPage.php
@@ -401,7 +401,7 @@ JS
}
});
docWidth = $(document).width();
- $('#ModalDlg').dialog({ autoOpen: false, modal: true, width: 0.8*docWidth, height: 'auto', maxHeight: $(window).height() - 50 }); // JQuery UI dialogs
+ // $('#ModalDlg').dialog({ autoOpen: false, modal: true, width: 0.8*docWidth, height: 'auto', maxHeight: $(window).height() - 50 }); // JQuery UI dialogs
ShowDebug();
$('#logOffBtn>ul').popupmenu();
@@ -770,14 +770,14 @@ EOF;
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
- public function RenderInlineTemplatesRecursively(iUIBlock $oBlock): void
+ public function RenderInlineScriptsAndCSSRecursively(iUIBlock $oBlock): void
{
$oBlockRenderer = new BlockRenderer($oBlock);
$this->add_init_script($oBlockRenderer->RenderJsInline());
$this->add_style($oBlockRenderer->RenderCssInline());
foreach ($oBlock->GetSubBlocks() as $oSubBlock) {
- $this->RenderInlineTemplatesRecursively($oSubBlock);
+ $this->RenderInlineScriptsAndCSSRecursively($oSubBlock);
}
}
@@ -839,6 +839,10 @@ EOF;
$aData['aLayouts']['oTopBar'] = $this->GetTopBarLayout();
// - Prepare content
$aData['aLayouts']['oPageContent'] = $this->GetContentLayout();
+ $aData['aDeferredBlocks'] = array_merge($this->GetDeferredBlocks($this->GetContentLayout()),
+ $this->GetDeferredBlocks($this->GetNavigationMenuLayout()),
+ $this->GetDeferredBlocks($this->GetTopBarLayout()));
+
// - Retrieve layouts linked files
// Note: Adding them now instead of in the template allow us to remove duplicates and lower the browser parsing time
/** @var \Combodo\iTop\Application\UI\UIBlock|string $oLayout */
@@ -856,7 +860,7 @@ EOF;
$this->add_linked_script($sFileAbsUrl);
}
- $this->RenderInlineTemplatesRecursively($oLayout);
+ $this->RenderInlineScriptsAndCSSRecursively($oLayout);
}
// Components
diff --git a/templates/components/datatable/config/layout.html.twig b/templates/components/datatable/config/layout.html.twig
new file mode 100644
index 000000000..9c0bce28d
--- /dev/null
+++ b/templates/components/datatable/config/layout.html.twig
@@ -0,0 +1,44 @@
+
+
+
+
\ No newline at end of file
diff --git a/templates/components/datatable/layout.html.twig b/templates/components/datatable/layout.html.twig
index a8e180670..f3c4df683 100644
--- a/templates/components/datatable/layout.html.twig
+++ b/templates/components/datatable/layout.html.twig
@@ -1,62 +1,17 @@
{% for oSubBlock in oUIBlock.GetSubBlocks() %}{{ render_block(oSubBlock, {aPage: aPage}) }}{% endfor %}
{% if oUIBlock.GetOptions()["select_mode"] is defined %}
-
-
+
+
{% endif %}
-
-
- {% if oUIBlock.GetOptions()["select_mode"] is defined %}
-
- {% endif %}
- {% for aColumn in oUIBlock.GetDisplayColumns() %}
-
{{ aColumn["attribute_label"] }}
- {% endfor %}
-
+
+
+ {% if oUIBlock.GetOptions()["select_mode"] is defined %}
+
+ {% endif %}
+ {% for aColumn in oUIBlock.GetDisplayColumns() %}
+