mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 15:34:12 +01:00
N°4076 - Allow block parameters to change the behaviour of blocks on the page
This commit is contained in:
19
pages/UI.php
19
pages/UI.php
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -30,7 +30,7 @@ class NiceWebPage extends WebPage
|
||||
$this->m_sRootUrl = $this->GetAbsoluteUrlAppRoot();
|
||||
parent::__construct($s_title, $bPrintable);
|
||||
|
||||
$this->LoadTheme();
|
||||
$this->LoadTheme();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,4 +53,3 @@ class iTopWizardWebPage extends iTopWebPage
|
||||
parent::output();
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
$('#{{ oUIBlock.GetId() }}').global_search({
|
||||
init_opened: {{ oUIBlock.HasQuery()|var_export }}
|
||||
});
|
||||
Reference in New Issue
Block a user