N°4076 - Allow block parameters to change the behaviour of blocks on the page

This commit is contained in:
Eric
2021-07-26 17:20:22 +02:00
parent bfcfcdd4cc
commit 344cce9fdd
11 changed files with 126 additions and 77 deletions

View File

@@ -547,31 +547,24 @@ try
// Save search to history
// - Prepare icon
$sQueryIconUrl = null;
if(!empty($sClassName))
{
if(!empty($sClassName)) {
$sQueryIconUrl = MetaModel::GetClassIcon($sClassName, false);
}
// - Prepare label
$sQueryLabel = null;
if($sQuery !== $sFullText)
{
if ($sQuery !== $sFullText) {
$sQueryLabel = $sFullText;
}
GlobalSearchHelper::AddQueryToHistory($sQuery, $sQueryIconUrl, $sQueryLabel);
$oP->GetTopBarLayout()
->GetGlobalSearch()
->SetQuery($sQuery)
->SetLastQueries(GlobalSearchHelper::GetLastQueries());
$oP->AddBlockParam('global_search.query', $sQuery);
// Check the needle length
$iMinLenth = MetaModel::GetConfig()->Get('full_text_needle_min');
foreach ($aFullTextNeedles as $sNeedle)
{
if (strlen($sNeedle) < $iMinLenth)
{
foreach ($aFullTextNeedles as $sNeedle) {
if (strlen($sNeedle) < $iMinLenth) {
$oP->p(Dict::Format('UI:Search:NeedleTooShort', $sNeedle, $iMinLenth));
$key = array_search($sNeedle, $aFullTextNeedles);
if($key!== false)
if ($key !== false)
{
unset($aFullTextNeedles[$key]);
}

View File

@@ -65,6 +65,7 @@ abstract class Controller
private $m_aLinkedStylesheets;
private $m_aSaas;
private $m_aAjaxTabs;
private $m_aBlockParams;
/** @var string */
private $m_sAccessTokenConfigParamId = null;
@@ -76,21 +77,19 @@ abstract class Controller
*/
public function __construct($sViewPath, $sModuleName = 'core')
{
$this->m_aLinkedScripts = array();
$this->m_aLinkedStylesheets = array();
$this->m_aSaas = array();
$this->m_aAjaxTabs = array();
$this->m_aDefaultParams = array();
$this->m_aLinkedScripts = [];
$this->m_aLinkedStylesheets = [];
$this->m_aSaas = [];
$this->m_aAjaxTabs = [];
$this->m_aDefaultParams = [];
$this->m_aBlockParams = [];
$this->SetViewPath($sViewPath);
$this->SetModuleName($sModuleName);
if ($sModuleName != 'core')
{
try
{
$this->m_aDefaultParams = array('sIndexURL' => utils::GetAbsoluteUrlModulePage($this->m_sModule, 'index.php'));
if ($sModuleName != 'core') {
try {
$this->m_aDefaultParams = ['sIndexURL' => utils::GetAbsoluteUrlModulePage($this->m_sModule, 'index.php')];
}
catch (Exception $e)
{
catch (Exception $e) {
IssueLog::Error($e->getMessage());
}
}
@@ -392,6 +391,9 @@ abstract class Controller
foreach ($this->m_aSaas as $sSaasRelPath) {
$this->AddSaasToPage($sSaasRelPath);
}
foreach ($this->m_aBlockParams as $sKey => $value) {
$this->SetBlockParamToPage($sKey, $value);
}
$this->OutputPage();
}
@@ -550,13 +552,20 @@ abstract class Controller
*/
public function AddAjaxTab($sCode, $sURL, $bCache = true, $sLabel = null)
{
if (is_null($sLabel))
{
if (is_null($sLabel)) {
$sLabel = Dict::S($sCode);
}
$this->m_aAjaxTabs[$sCode] = array('label' => $sLabel, 'url' => $sURL, 'cache' => $bCache);
}
/**
* @param array $aBlockParams
*/
public function AddBlockParams(array $aBlockParams)
{
$this->m_aBlockParams = $aBlockParams;
}
/**
* @param $aParams
* @param $sName
@@ -595,7 +604,7 @@ abstract class Controller
switch ($sPageType)
{
case self::ENUM_PAGE_TYPE_HTML:
$this->m_oPage = new iTopWebPage($this->GetOperationTitle());
$this->m_oPage = new iTopWebPage($this->GetOperationTitle(), false);
$this->m_oPage->add_xframe_options();
break;
@@ -679,6 +688,11 @@ abstract class Controller
$this->m_oPage->AddAjaxTab($sCode, $sURL, $bCache, $sTitle);
}
public function SetBlockParamToPage(string $sKey, $value)
{
$this->m_oPage->SetBlockParam($sKey, $value);
}
/**
* @throws \Exception
*/

View File

@@ -70,8 +70,8 @@ class GlobalSearch extends UIBlock implements iKeyboardShortcut
$this->SetEndpoint(static::DEFAULT_ENDPOINT_REL_URL);
$this->SetQuery('');
$this->SetLastQueries($aLastQueries);
$this->bShowHistory = (bool) MetaModel::GetConfig()->Get('global_search.show_history');
$this->iMaxHistoryResults = (int) MetaModel::GetConfig()->Get('global_search.max_history_results');
$this->bShowHistory = (bool)MetaModel::GetConfig()->Get('global_search.show_history');
$this->iMaxHistoryResults = (int)MetaModel::GetConfig()->Get('global_search.max_history_results');
}
/**

View File

@@ -41,6 +41,7 @@ class TopBarFactory
* @param array|null $aBreadcrumbsEntry Current breadcrumbs entry to add
*
* @return \Combodo\iTop\Application\UI\Base\Layout\TopBar\TopBar
* @throws \ConfigException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
@@ -49,18 +50,15 @@ class TopBarFactory
{
$oTopBar = new TopBar(TopBar::BLOCK_CODE);
if (utils::GetConfig()->Get('quick_create.enabled') === true)
{
if (utils::GetConfig()->Get('quick_create.enabled') === true) {
$oTopBar->SetQuickCreate(QuickCreateFactory::MakeFromUserHistory());
}
if (utils::GetConfig()->Get('global_search.enabled') === true)
{
if (utils::GetConfig()->Get('global_search.enabled') === true) {
$oTopBar->SetGlobalSearch(GlobalSearchFactory::MakeFromUserHistory());
}
if(utils::GetConfig()->Get('breadcrumb.enabled') === true)
{
if (utils::GetConfig()->Get('breadcrumb.enabled') === true) {
$oBreadcrumbs = new Breadcrumbs($aBreadcrumbsEntry, Breadcrumbs::BLOCK_CODE);
$oTopBar->SetBreadcrumbs($oBreadcrumbs);

View File

@@ -177,25 +177,27 @@ class AjaxPage extends WebPage implements iTabbedPage
$aData['aPage'] = [
'sAbsoluteUrlAppRoot' => addslashes(utils::GetAbsoluteUrlAppRoot()),
'sTitle' => $this->s_title,
'aMetadata' => [
'sTitle' => $this->s_title,
'aMetadata' => [
'sCharset' => static::PAGES_CHARSET,
'sLang' => $this->GetLanguageForMetadata(),
],
'aCssFiles' => $this->a_linked_stylesheets,
'aCssInline' => $this->a_styles,
'aJsFiles' => $this->a_linked_scripts,
'aJsInlineLive' => $this->a_scripts,
'aCssFiles' => $this->a_linked_stylesheets,
'aCssInline' => $this->a_styles,
'aJsFiles' => $this->a_linked_scripts,
'aJsInlineLive' => $this->a_scripts,
'aJsInlineOnDomReady' => $this->GetReadyScripts(),
'aJsInlineOnInit' => $this->a_init_scripts,
'bEscapeContent' => ($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'),
'aJsInlineOnInit' => $this->a_init_scripts,
'bEscapeContent' => ($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline'),
// TODO 3.0.0: TEMP, used while developping, remove it.
'sSanitizedContent' => utils::FilterXSS($this->s_content),
'sDeferredContent' => utils::FilterXSS(addslashes(str_replace("\n", '', $this->s_deferred_content))),
'sCapturedOutput' => utils::FilterXSS($s_captured_output),
'sPromiseId' => $this->sPromiseId
'sSanitizedContent' => utils::FilterXSS($this->s_content),
'sDeferredContent' => utils::FilterXSS(addslashes(str_replace("\n", '', $this->s_deferred_content))),
'sCapturedOutput' => utils::FilterXSS($s_captured_output),
'sPromiseId' => $this->sPromiseId,
];
$aData['aBlockParams'] = $this->GetBlockParams();
$oTwigEnv = TwigHelper::GetTwigEnvironment(BlockRenderer::TWIG_BASE_PATH, BlockRenderer::TWIG_ADDITIONAL_PATHS);
// Render final TWIG into global HTML
$oKpi = new ExecutionKPI();

View File

@@ -30,7 +30,7 @@ class NiceWebPage extends WebPage
$this->m_sRootUrl = $this->GetAbsoluteUrlAppRoot();
parent::__construct($s_title, $bPrintable);
$this->LoadTheme();
$this->LoadTheme();
}
/**

View File

@@ -99,6 +99,8 @@ class WebPage implements Page
protected $a_styles;
/** @var array Stylesheets linked (external) to the page through URIs */
protected $a_linked_stylesheets;
/** @var array Parameters to be used by page blocks */
protected $aBlockParams;
protected $a_headers;
protected $a_base;
protected $iNextId;
@@ -133,7 +135,7 @@ class WebPage implements Page
* @param string $s_title
* @param bool $bPrintable
*/
public function __construct($s_title, $bPrintable = false)
public function __construct(string $s_title, bool $bPrintable = false)
{
$this->s_title = $s_title;
$this->s_content = "";
@@ -146,8 +148,8 @@ class WebPage implements Page
$this->InitializeDictEntries();
$this->InitializeStyles();
$this->InitializeLinkedStylesheets();
$this->a_headers = array();
$this->a_base = array('href' => '', 'target' => '');
$this->a_headers = [];
$this->a_base = ['href' => '', 'target' => ''];
$this->iNextId = 0;
$this->iTransactionId = 0;
$this->sContentType = '';
@@ -155,7 +157,8 @@ class WebPage implements Page
$this->sContentFileName = '';
$this->bTrashUnexpectedOutput = false;
$this->s_OutputFormat = utils::ReadParam('output_format', 'html');
$this->a_OutputOptions = array();
$this->a_OutputOptions = [];
$this->aBlockParams = [];
$this->bHasCollapsibleSection = false;
$this->bPrintable = $bPrintable;
$this->bAddJSDict = true;
@@ -1168,24 +1171,26 @@ JS;
// Base structure of data to pass to the TWIG template
$aData['aPage'] = [
'sAbsoluteUrlAppRoot' => addslashes(utils::GetAbsoluteUrlAppRoot()),
'sTitle' => $this->s_title,
'aMetadata' => [
'sTitle' => $this->s_title,
'aMetadata' => [
'sCharset' => static::PAGES_CHARSET,
'sLang' => $this->GetLanguageForMetadata(),
'sLang' => $this->GetLanguageForMetadata(),
],
'aCssFiles' => $this->a_linked_stylesheets,
'aCssInline' => $this->a_styles,
'aJsInlineEarly' => $this->a_early_scripts,
'aJsFiles' => $this->a_linked_scripts,
'aJsInlineLive' => $this->a_scripts,
'aCssFiles' => $this->a_linked_stylesheets,
'aCssInline' => $this->a_styles,
'aJsInlineEarly' => $this->a_early_scripts,
'aJsFiles' => $this->a_linked_scripts,
'aJsInlineLive' => $this->a_scripts,
'aJsInlineOnDomReady' => $this->GetReadyScripts(),
'aJsInlineOnInit' => $this->a_init_scripts,
'aJsInlineOnInit' => $this->a_init_scripts,
// TODO 3.0.0: TEMP, used while developing, remove it.
'sCapturedOutput' => utils::FilterXSS($s_captured_output),
'sDeferredContent' => utils::FilterXSS($this->s_deferred_content),
'sCapturedOutput' => utils::FilterXSS($s_captured_output),
'sDeferredContent' => utils::FilterXSS($this->s_deferred_content),
];
$aData['aBlockParams'] = $this->GetBlockParams();
if ($this->a_base['href'] != '') {
$aData['aPage']['aMetadata']['sBaseUrl'] = $this->a_base['href'];
}
@@ -1602,4 +1607,25 @@ EOD
{
return $this->sTemplateRelPath;
}
/**
* @return array
*/
public function GetBlockParams(): array
{
return $this->aBlockParams;
}
/**
* @param string $sKey
* @param $value
*
* @return $this
*/
public function SetBlockParam(string $sKey, $value)
{
$this->aBlockParams[$sKey] = $value;
return $this;
}
}

View File

@@ -72,7 +72,11 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
* @param string $sTitle
* @param bool $bPrintable
*
* @throws \Exception
* @throws \ConfigException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \DictExceptionMissingString
* @throws \MySQLException
*/
public function __construct($sTitle, $bPrintable = false)
{
@@ -102,10 +106,9 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->add_header("Content-type: text/html; charset=".self::PAGES_CHARSET);
$this->no_cache();
$this->add_xframe_options();
if (!$this->IsPrintableVersion())
{
if (!$this->IsPrintableVersion()) {
$this->PrepareLayout();
} else{
} else {
$oPrintHeader = $this->OutputPrintable();
$this->AddUiBlock($oPrintHeader);
}
@@ -800,16 +803,18 @@ HTML;
// Base structure of data to pass to the TWIG template
$aData['aPage'] = [
'sAbsoluteUrlAppRoot' => $sAbsoluteUrlAppRoot,
'sTitle' => $this->s_title,
'sFaviconUrl' => $sFaviconUrl,
'aMetadata' => [
'sTitle' => $this->s_title,
'sFaviconUrl' => $sFaviconUrl,
'aMetadata' => [
'sCharset' => static::PAGES_CHARSET,
'sLang' => $sMetadataLanguage,
'sLang' => $sMetadataLanguage,
],
'oPrintHeader' => $oPrintHeader,
'isPrintable' => $this->IsPrintableVersion(),
'oPrintHeader' => $oPrintHeader,
'isPrintable' => $this->IsPrintableVersion(),
];
$aData['aBlockParams'] = $this->GetBlockParams();
// Base tag
// Note: We might consider to put the app_root_url parameter here, but that would need a BIG rework on iTop AND the extensions to replace all the "../images|js|css/xxx.yyy"...
if (!empty($this->a_base['href'])) {
@@ -1167,4 +1172,17 @@ EOF
return $oBlock;
}
public function SetBlockParam(string $sKey, $value)
{
$oGlobalSearch = $this->GetTopBarLayout()->GetGlobalSearch();
$sGlobalSearchId = $oGlobalSearch->GetId();
switch ($sKey) {
case "$sGlobalSearchId.sQuery":
$oGlobalSearch->SetQuery($value);
break;
}
return parent::SetBlockParam($sKey, $value); // TODO: Change the autogenerated stub
}
}

View File

@@ -53,4 +53,3 @@ class iTopWizardWebPage extends iTopWebPage
parent::output();
}
}
?>

View File

@@ -1,7 +1,7 @@
<div id="{{ oUIBlock.GetId() }}"
{# Note: The "ibo-is-opened" class is put there and not through the JS widget to avoid visual glitches #}
{# Otherwise it would open only when the DOM is ready and the JS widget instantiated #}
class="ibo-global-search {% if oUIBlock.HasQuery() %}ibo-is-opened{% endif %}"
class="ibo-global-search"
data-role="ibo-global-search">
<form action="{{ oUIBlock.GetEndpoint() }}" method="get" class="ibo-global-search--head" data-role="ibo-global-search--head">
<a href="#" class="ibo-global-search--icon" data-role="ibo-global-search--icon"

View File

@@ -1,3 +1,2 @@
$('#{{ oUIBlock.GetId() }}').global_search({
init_opened: {{ oUIBlock.HasQuery()|var_export }}
});