N°2847 - Rework of the global iTopWebPage layout (Part II)

- Optimize TWIG templates includes (don't pass context to autonomous components)
- Preliminary work of the top bar and breadcrumbs features
- Removal of images dedicated to the breadcrumbs feature
This commit is contained in:
Molkobain
2020-07-17 17:01:29 +02:00
parent 6f9565d979
commit 8efd8008fc
34 changed files with 8309 additions and 201 deletions

View File

@@ -696,7 +696,8 @@ class DisplayBlock
'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()), 'breadcrumb_label' => MetaModel::GetName($this->m_oSet->GetClass()),
'breadcrumb_max_count' => utils::GetConfig()->Get('breadcrumb.max_count'), 'breadcrumb_max_count' => utils::GetConfig()->Get('breadcrumb.max_count'),
'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(), 'breadcrumb_instance_id' => MetaModel::GetConfig()->GetItopInstanceid(),
'breadcrumb_icon' => utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png', 'breadcrumb_icon' => 'fas fa-search',
'breadcrumb_icon_type' => iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES,
)); ));
$oPage->add_ready_script("$('body').trigger('update_history.itop', [$seventAttachedData])"); $oPage->add_ready_script("$('body').trigger('update_history.itop', [$seventAttachedData])");

View File

@@ -35,6 +35,13 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
/** @var string DEFAULT_APP_ICON_SHAPE */ /** @var string DEFAULT_APP_ICON_SHAPE */
const DEFAULT_APP_ICON_SHAPE = self::ENUM_APP_ICON_SHAPE_FULL; const DEFAULT_APP_ICON_SHAPE = self::ENUM_APP_ICON_SHAPE_FULL;
/** @var string ENUM_BREADCRUMB_ENTRY_ICON_TYPE_IMAGE */
const ENUM_BREADCRUMB_ENTRY_ICON_TYPE_IMAGE = 'image';
/** @var string ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES */
const ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES = 'css_classes';
/** @var string DEFAULT_BREADCRUMB_ENTRY_ICON_TYPE */
const DEFAULT_BREADCRUMB_ENTRY_ICON_TYPE = self::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_IMAGE;
/** @var array Default and branding filenames for the app. icon in the backoffice */ /** @var array Default and branding filenames for the app. icon in the backoffice */
protected static $aAppIconFilenames = [ protected static $aAppIconFilenames = [
self::ENUM_APP_ICON_SHAPE_SQUARE => [ self::ENUM_APP_ICON_SHAPE_SQUARE => [
@@ -58,6 +65,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
protected $sBreadCrumbEntryDescription; protected $sBreadCrumbEntryDescription;
protected $sBreadCrumbEntryUrl; protected $sBreadCrumbEntryUrl;
protected $sBreadCrumbEntryIcon; protected $sBreadCrumbEntryIcon;
protected $sBreadCrumbEntryIconType;
protected $oCtx; protected $oCtx;
/** /**
@@ -126,7 +134,6 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->add_linked_script('js/ajaxfileupload.js'); $this->add_linked_script('js/ajaxfileupload.js');
$this->add_linked_script('js/jquery.mousewheel.js'); $this->add_linked_script('js/jquery.mousewheel.js');
$this->add_linked_script('js/jquery.magnific-popup.min.js'); $this->add_linked_script('js/jquery.magnific-popup.min.js');
$this->add_linked_script('js/breadcrumb.js');
$this->add_linked_script('js/moment-with-locales.min.js'); $this->add_linked_script('js/moment-with-locales.min.js');
$this->add_linked_script('js/showdown.min.js'); $this->add_linked_script('js/showdown.min.js');
$this->add_linked_script('js/newsroom_menu.js'); $this->add_linked_script('js/newsroom_menu.js');
@@ -715,9 +722,12 @@ JS
* @param string $sLabel Label of the breadcrumb item * @param string $sLabel Label of the breadcrumb item
* @param string $sDescription More information, displayed as a tooltip * @param string $sDescription More information, displayed as a tooltip
* @param string $sUrl Specify a URL if the current URL as perceived on the browser side is not relevant * @param string $sUrl Specify a URL if the current URL as perceived on the browser side is not relevant
* @param string $sIcon Icon (relative or absolute) path that will be displayed next to the label * @param string $sIcon Image URL (relative or absolute) or CSS classes (eg. "fas fa-wrench") of the icon that will be displayed next to the label
* @param string $sIconType Type of the icon, must be set according to the $sIcon value. See class constants ENUM_BREADCRUMB_ENTRY_ICON_TYPE_XXX
*
* @see static::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_IMAGE, static::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES
*/ */
public function SetBreadCrumbEntry($sId, $sLabel, $sDescription, $sUrl = '', $sIcon = '') public function SetBreadCrumbEntry($sId, $sLabel, $sDescription, $sUrl = '', $sIcon = '', $sIconType = self::DEFAULT_BREADCRUMB_ENTRY_ICON_TYPE)
{ {
$this->bBreadCrumbEnabled = true; $this->bBreadCrumbEnabled = true;
$this->sBreadCrumbEntryId = $sId; $this->sBreadCrumbEntryId = $sId;
@@ -725,6 +735,7 @@ JS
$this->sBreadCrumbEntryDescription = $sDescription; $this->sBreadCrumbEntryDescription = $sDescription;
$this->sBreadCrumbEntryUrl = $sUrl; $this->sBreadCrumbEntryUrl = $sUrl;
$this->sBreadCrumbEntryIcon = $sIcon; $this->sBreadCrumbEntryIcon = $sIcon;
$this->sBreadCrumbEntryIconType = $sIconType;
} }
/** /**
@@ -822,7 +833,7 @@ JS
* @return string * @return string
* @since 2.8.0 * @since 2.8.0
*/ */
public function GetApplicationRevisionNumber() protected function GetApplicationRevisionNumber()
{ {
if (ITOP_REVISION == 'svn') if (ITOP_REVISION == 'svn')
{ {
@@ -849,7 +860,7 @@ JS
* @throws \Exception * @throws \Exception
* @since 2.8.0 * @since 2.8.0
*/ */
public function GetApplicationIconUrl($sShape = self::DEFAULT_APP_ICON_SHAPE) protected function GetApplicationIconUrl($sShape = self::DEFAULT_APP_ICON_SHAPE)
{ {
$sIconDefaultFilename = static::$aAppIconFilenames[$sShape]['default']; $sIconDefaultFilename = static::$aAppIconFilenames[$sShape]['default'];
$sIconBrandingFilename = static::$aAppIconFilenames[$sShape]['branding']; $sIconBrandingFilename = static::$aAppIconFilenames[$sShape]['branding'];
@@ -874,7 +885,7 @@ JS
* @throws \DictExceptionMissingString * @throws \DictExceptionMissingString
* @since 2.8.0 * @since 2.8.0
*/ */
public function GetNavigationMenuData() protected function GetNavigationMenuData()
{ {
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
@@ -888,6 +899,83 @@ JS
]; ];
} }
/**
* Return the top bar data (global search, breadcrumbs, ...)
*
* @return array
* @throws \ConfigException
* @throws \CoreException
* @since 2.8.0
*/
protected function GetTopBarData()
{
$aData = [
'sId' => 'ibo-top-bar',
'aComponents' => [
'aBreadCrumbs' => $this->GetBreadCrumbsData(),
],
];
return $aData;
}
/**
* Return the breadcrumbs data (iTop instance ID, new entry, ...)
*
* @return array
* @throws \ConfigException
* @throws \CoreException
* @since 2.8.0
*/
protected function GetBreadCrumbsData()
{
$aData = [
'sId' => 'ibo-breadcrumbs',
];
$iBreadCrumbMaxCount = utils::GetConfig()->Get('breadcrumb.max_count');
if ($iBreadCrumbMaxCount > 1)
{
$oConfig = MetaModel::GetConfig();
$siTopInstanceId = $oConfig->GetItopInstanceid();
if ($this->bBreadCrumbEnabled)
{
// Default entry values
if (is_null($this->sBreadCrumbEntryId))
{
$this->sBreadCrumbEntryId = $this->s_title;
$this->sBreadCrumbEntryLabel = $this->s_title;
$this->sBreadCrumbEntryDescription = $this->s_title;
$this->sBreadCrumbEntryUrl = '';
$this->sBreadCrumbEntryIcon = 'fas fa-wrench';
$this->sBreadCrumbEntryIconType = static::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES;
}
$aNewEntry = array(
'id' => $this->sBreadCrumbEntryId,
'url' => $this->sBreadCrumbEntryUrl,
'label' => utils::HtmlEntities($this->sBreadCrumbEntryLabel),
'description' => utils::HtmlEntities($this->sBreadCrumbEntryDescription),
'icon' => $this->sBreadCrumbEntryIcon,
'icon_type' => $this->sBreadCrumbEntryIconType,
);
}
else
{
$aNewEntry = null;
}
$aData['aWidgetOptions'] = [
'itop_instance_id' => $siTopInstanceId,
'max_count' => $iBreadCrumbMaxCount,
'new_entry' => $aNewEntry,
];
}
return $aData;
}
/** /**
* Handles the "newsroom" menu at the top-right of the screen * Handles the "newsroom" menu at the top-right of the screen
*/ */
@@ -1060,6 +1148,9 @@ EOF
// - Navigation menu // - Navigation menu
$aData['aLayouts']['aNavigationMenu'] = $this->GetNavigationMenuData(); $aData['aLayouts']['aNavigationMenu'] = $this->GetNavigationMenuData();
// - Top bar
$aData['aLayouts']['aTopBar'] = $this->GetTopBarData();
$oTwigEnv = TwigHelper::GetTwigEnvironment(APPROOT.'templates/'); $oTwigEnv = TwigHelper::GetTwigEnvironment(APPROOT.'templates/');
$sTemplateRelPath = 'pages/backoffice/layout'; $sTemplateRelPath = 'pages/backoffice/layout';

View File

@@ -1031,7 +1031,7 @@ class OQLMenuNode extends MenuNode
//$iCount = $oBlock->GetDisplayedCount(); //$iCount = $oBlock->GetDisplayedCount();
$sPageId = "ui-search-".$oSearch->GetClass(); $sPageId = "ui-search-".$oSearch->GetClass();
$sLabel = MetaModel::GetName($oSearch->GetClass()); $sLabel = MetaModel::GetName($oSearch->GetClass());
$oPage->SetBreadCrumbEntry($sPageId, $sLabel, $sTitle, '', '../images/breadcrumb-search.png'); $oPage->SetBreadCrumbEntry($sPageId, $sLabel, $sTitle, '', 'fas fa-list', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
} }
} }
} }
@@ -1078,7 +1078,7 @@ class SearchMenuNode extends MenuNode
public function RenderContent(WebPage $oPage, $aExtraParams = array()) public function RenderContent(WebPage $oPage, $aExtraParams = array())
{ {
ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId()); ApplicationMenu::CheckMenuIdEnabled($this->GetMenuId());
$oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png'); $oPage->SetBreadCrumbEntry("menu-".$this->sMenuId, $this->GetTitle(), '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oSearch = new DBObjectSearch($this->sClass); $oSearch = new DBObjectSearch($this->sClass);
$aParams = array_merge(array('table_id' => 'Menu_'.utils::GetSafeId($this->GetMenuId())), $aExtraParams); $aParams = array_merge(array('table_id' => 'Menu_'.utils::GetSafeId($this->GetMenuId())), $aExtraParams);
@@ -1315,13 +1315,13 @@ class DashboardMenuNode extends MenuNode
} }
if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId()) if ($this->sMenuId == ApplicationMenu::GetDefaultMenuId())
{ {
$sIcon = '../images/breadcrumb_home.png'; $sIcon = 'fas fa-home';
} }
else else
{ {
$sIcon = '../images/breadcrumb-dashboard.png'; $sIcon = 'fas fa-chart-pie';
} }
$oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon); $oPage->SetBreadCrumbEntry("ui-dashboard-".$this->sMenuId, $this->GetTitle(), $sDescription, '', $sIcon, iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
} }
} }
else else

View File

@@ -16,3 +16,4 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
*/ */
@import "breadcrumbs";

View File

@@ -0,0 +1,74 @@
/*!
* Copyright (C) 2013-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
$ibo-breadcrumbs--item--text-color: $ibo-color-grey-800 !default;
$ibo-breadcrumbs--item-icon--margin-x: 8px !default;
$ibo-breadcrumbs--item-icon--max-width: 16px !default;
$ibo-breadcrumbs--item-icon--text-color: $ibo-color-grey-600 !default;
$ibo-breadcrumbs--item-separator--margin-x: 12px !default;
$ibo-breadcrumbs--item-separator--text-color: $ibo-color-grey-500 !default;
.ibo-breadcrumbs{
display: flex;
align-items: center;
* {
display: flex;
align-items: center;
}
}
.ibo-breadcrumbs--item{
color: $ibo-breadcrumbs--item--text-color;
@extend %ibo-font-ral-nor-100;
&:not(:last-child){
&::after{
content: '\f054';
margin: 0 $ibo-breadcrumbs--item-separator--margin-x;
color: $ibo-breadcrumbs--item-separator--text-color;
@extend %fa-solid-base;
}
&:hover{
.ibo-breadcrumbs--item-icon{
> *{
opacity: 1;
filter: none;
}
}
}
}
}
.ibo-breadcrumbs--item-icon{
margin-right: $ibo-breadcrumbs--item-icon--margin-x;
@extend %ibo-font-ral-nor-150;
transition: all 0.1s linear;
> span{
color: $ibo-breadcrumbs--item-icon--text-color;
opacity: 0.6;
}
> img{
height: auto;
max-width: $ibo-breadcrumbs--item-icon--max-width;
opacity: 0.3;
filter: grayscale(100%);
}
}

View File

@@ -17,13 +17,15 @@
*/ */
/* SCSS variables (can be overloaded) */ /* SCSS variables (can be overloaded) */
$ibo-top-bar-height: 54px !default;
$ibo-top-bar-padding-left: 16px !default; /* Should be align with the page content padding-left */ $ibo-top-bar-padding-left: 16px !default; /* Should be align with the page content padding-left */
$ibo-top-bar-padding-right: 16px !default; $ibo-top-bar-padding-right: 16px !default;
$ibo-top-bar-padding-y: 16px !default; $ibo-top-bar-padding-y: 0px !default;
$ibo-top-bar-background-color: $ibo-color-white-100 !default; $ibo-top-bar-background-color: $ibo-color-white-100 !default;
/* CSS variables (can be changed directly from the browser) */ /* CSS variables (can be changed directly from the browser) */
:root{ :root{
--ibo-top-bar-height: #{$ibo-top-bar-height};
--ibo-top-bar-padding-left: #{$ibo-top-bar-padding-left}; --ibo-top-bar-padding-left: #{$ibo-top-bar-padding-left};
--ibo-top-bar-padding-right: #{$ibo-top-bar-padding-right}; --ibo-top-bar-padding-right: #{$ibo-top-bar-padding-right};
--ibo-top-bar-padding-y: #{$ibo-top-bar-padding-y}; --ibo-top-bar-padding-y: #{$ibo-top-bar-padding-y};
@@ -32,6 +34,11 @@ $ibo-top-bar-background-color: $ibo-color-white-100 !default;
.ibo-top-bar{ .ibo-top-bar{
display: flex; display: flex;
align-items: center; align-items: center;
height: var(--ibo-top-bar-height);
padding: var(--ibo-top-bar-padding-y) var(--ibo-top-bar-padding-right) var(--ibo-top-bar-padding-y) var(--ibo-top-bar-padding-left); padding: var(--ibo-top-bar-padding-y) var(--ibo-top-bar-padding-right) var(--ibo-top-bar-padding-y) var(--ibo-top-bar-padding-left);
background-color: var(--ibo-top-bar-background-color); background-color: var(--ibo-top-bar-background-color);
.ibo-breadcrumbs{
flex-grow: 1; /* Occupy as much width as possible */
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -18,4 +18,5 @@
@import "typography"; @import "typography";
@import "elevation"; @import "elevation";
@import "misc"; @import "misc";
@import "font-icon";

View File

@@ -0,0 +1,56 @@
/*!
* Copyright (C) 2013-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
/******************************************************************************************************************************/
/* NOTE: Those helpers allow to easily use an icon from libs. like FontAwesome or FontCombodo within a CSS rule (eg. ::after) */
/* To use it, simply "@extend %fa-regular-base" in a rule and put the desired icon "content: '\f054'" */
/******************************************************************************************************************************/
%fa-regular-base{
font-family: "Font Awesome 5 Free";
font-weight: 400;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
}
%fa-solid-base{
font-family: "Font Awesome 5 Free";
font-weight: 900;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
}
%fc-regular-base{
display: inline-block;
font-family: CombodoRegular;
font-style: normal;
font-variant: normal;
font-weight: normal;
text-rendering: auto;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

View File

@@ -30,7 +30,7 @@ LoginWebPage::DoLogin(true); // Check user rights and prompt if needed (must be
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$oPage = new iTopWebPage(Dict::S('iTopHub:InstalledExtensions')); $oPage = new iTopWebPage(Dict::S('iTopHub:InstalledExtensions'));
$oPage->SetBreadCrumbEntry('ui-hub-myextensions', Dict::S('Menu:iTopHub:MyExtensions'), Dict::S('Menu:iTopHub:MyExtensions+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oPage->SetBreadCrumbEntry('ui-hub-myextensions', Dict::S('Menu:iTopHub:MyExtensions'), Dict::S('Menu:iTopHub:MyExtensions+'), '', 'fas fa-puzzle-piece', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
function DisplayExtensionInfo(Webpage $oPage, iTopExtension $oExtension) function DisplayExtensionInfo(Webpage $oPage, iTopExtension $oExtension)
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 526 B

View File

@@ -1,10 +1,27 @@
//iTop Form field /*
* Copyright (C) 2013-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
; ;
$(function() $(function()
{ {
// the widget definition, where 'itop' is the namespace, // the widget definition, where 'itop' is the namespace,
// 'breadcrumb' the widget name // 'breadcrumbs' the widget name
$.widget( 'itop.breadcrumb', $.widget( 'itop.breadcrumbs',
{ {
// default options // default options
options: options:
@@ -19,17 +36,17 @@ $(function()
{ {
var me = this; var me = this;
this.element this.element.addClass('ibo-breadcrumbs');
.addClass('breadcrumb');
if(typeof(Storage) !== "undefined") // Check that storage API is available
if(typeof(Storage) !== 'undefined')
{ {
$(window).bind( 'hashchange', function(e) $(window).bind('hashchange', function(e)
{ {
me.RefreshLatestEntry(); me.RefreshLatestEntry();
}); });
aBreadCrumb = this._Read(); aBreadCrumb = this._readDataFromStorage();
if (this.options.new_entry !== null) { if (this.options.new_entry !== null) {
var sUrl = this.options.new_entry.url; var sUrl = this.options.new_entry.url;
@@ -46,72 +63,57 @@ $(function()
label: this.options.new_entry.label, label: this.options.new_entry.label,
description: this.options.new_entry.description, description: this.options.new_entry.description,
icon: this.options.new_entry.icon, icon: this.options.new_entry.icon,
icon_type: this.options.new_entry.icon_type,
url: sUrl url: sUrl
}); });
// Keep only the last <max_count> items // Keep only the last <max_count> items
aBreadCrumb = aBreadCrumb.slice(-(this.options.max_count)); aBreadCrumb = aBreadCrumb.slice(-(this.options.max_count));
} }
this._Write(aBreadCrumb); this._writeDataToStorage(aBreadCrumb);
var sBreadCrumbHtml = '';
for (iEntry in aBreadCrumb) for (iEntry in aBreadCrumb)
{ {
//if (iEntry >= iDisplayableItems) break; // skip the current page var sBreadcrumbsItemHtml = '';
var oEntry = aBreadCrumb[iEntry]; var oEntry = aBreadCrumb[iEntry];
if (oEntry['label'].length > 0) if (oEntry['label'].length > 0)
{ {
var sIconSpec = ''; var sIconSpec = '';
if (oEntry['icon'].length > 0) if (oEntry['icon_type'] === 'css_classes')
{ {
sIconSpec = '<span class="icon"><img src="'+oEntry['icon']+'"/></span>'; sIconSpec = '<span class="ibo-breadcrumbs--item-icon"><span class="'+oEntry['icon']+'"/></span></span>';
} }
else if (oEntry['icon'].length > 0)
{
sIconSpec = '<span class="ibo-breadcrumbs--item-icon"><img src="'+oEntry['icon']+'"/></span>';
}
var sTitle = oEntry['description']; var sTitle = oEntry['description'];
if (sTitle.length == 0) { if (sTitle.length == 0) {
sTitle = oEntry['label']; sTitle = oEntry['label'];
} }
if ((this.options.new_entry !== null) && (iEntry == aBreadCrumb.length - 1)) if ((this.options.new_entry !== null) && (iEntry == aBreadCrumb.length - 1))
{ {
// Last entry is the current page // Last entry is the current page
sBreadCrumbHtml += '<div class="breadcrumb-item breadcrumb-current" breadcrumb-entry="'+iEntry+'" title="'+sTitle+'">'+sIconSpec+'<span class="truncate">'+oEntry['label']+'</span></div>'; sBreadcrumbsItemHtml += '<span class="ibo-breadcrumbs--item--is-current" data-breadcrumb-entry-number="'+iEntry+'" title="'+sTitle+'">'+sIconSpec+'<span class="ibo-breadcrumbs--item-label">'+oEntry['label']+'</span></span>';
} }
else else
{ {
var sSanitizedUrl = StripArchiveArgument(oEntry['url']); var sSanitizedUrl = StripArchiveArgument(oEntry['url']);
sBreadCrumbHtml += '<div class="breadcrumb-item"><a class="breadcrumb-link" breadcrumb-entry="'+iEntry+'" href="'+sSanitizedUrl+'" title="'+sTitle+'">'+sIconSpec+'<span class="truncate">'+oEntry['label']+'</span></a></div>'; sBreadcrumbsItemHtml += '<a class="ibo-breadcrumbs--item" data-breadcrumb-entry-number="'+iEntry+'" href="'+sSanitizedUrl+'" title="'+sTitle+'">'+sIconSpec+'<span class="truncate">'+oEntry['label']+'</span></a>';
} }
} }
this.element.append(sBreadcrumbsItemHtml);
} }
$('#itop-breadcrumb').html(sBreadCrumbHtml);
} }
else
{
// Sorry! No Web Storage support..
//$('#itop-breadcrumb').html('<span style="display:none;">Session storage not available for the current browser</span>');
}
},
// called when created, and later when changing options
_refresh: function()
{
}, },
// events bound via _bind are removed automatically // events bound via _bind are removed automatically
// revert other modifications here // revert other modifications here
_destroy: function() _destroy: function()
{ {
this.element this.element.removeClass('ibo-breadcrumbs');
.removeClass('breadcrumb');
}, },
// _setOptions is called with a hash of all options that are changing _readDataFromStorage: function()
// always refresh when changing options
_setOptions: function()
{
this._superApply(arguments);
},
// _setOption is called for each individual option that is changing
_setOption: function( key, value )
{
this._super( key, value );
},
_Read: function()
{ {
var sBreadCrumbStorageKey = this.options.itop_instance_id + 'breadcrumb-v1'; var sBreadCrumbStorageKey = this.options.itop_instance_id + 'breadcrumb-v1';
var aBreadCrumb = []; var aBreadCrumb = [];
@@ -122,7 +124,7 @@ $(function()
} }
return aBreadCrumb; return aBreadCrumb;
}, },
_Write: function(aBreadCrumb) _writeDataToStorage: function(aBreadCrumb)
{ {
var sBreadCrumbStorageKey = this.options.itop_instance_id + 'breadcrumb-v1'; var sBreadCrumbStorageKey = this.options.itop_instance_id + 'breadcrumb-v1';
sBreadCrumbData = JSON.stringify(aBreadCrumb); sBreadCrumbData = JSON.stringify(aBreadCrumb);
@@ -131,11 +133,11 @@ $(function()
// Refresh the latest entry (navigating to a tab) // Refresh the latest entry (navigating to a tab)
RefreshLatestEntry: function(sRefreshHrefTo) RefreshLatestEntry: function(sRefreshHrefTo)
{ {
aBreadCrumb = this._Read(); var aBreadCrumb = this._readDataFromStorage();
var iDisplayableItems = aBreadCrumb.length; var iDisplayableItems = aBreadCrumb.length;
if (this.options.new_entry !== null) { if (this.options.new_entry !== null) {
if (sRefreshHrefTo == undefined) if (sRefreshHrefTo === undefined)
{ {
sRefreshHrefTo = window.location.href; sRefreshHrefTo = window.location.href;
} }
@@ -144,8 +146,7 @@ $(function()
aBreadCrumb[aBreadCrumb.length - 1].url = sRefreshHrefTo; aBreadCrumb[aBreadCrumb.length - 1].url = sRefreshHrefTo;
$('#itop-breadcrumb .breadcrumb-current:last-of-type a').attr('href', sRefreshHrefTo); $('#itop-breadcrumb .breadcrumb-current:last-of-type a').attr('href', sRefreshHrefTo);
} }
this._Write(aBreadCrumb); this._writeDataToStorage(aBreadCrumb);
}, },
}); });
}); });

View File

@@ -202,7 +202,7 @@ $(function()
} }
$('#itop-breadcrumb') $('#ibo-breadcrumbs')
.breadcrumb('destroy') .breadcrumb('destroy')
.breadcrumb({ .breadcrumb({
itop_instance_id: oData['breadcrumb_instance_id'], itop_instance_id: oData['breadcrumb_instance_id'],
@@ -212,6 +212,7 @@ $(function()
"label": oData['breadcrumb_label'], "label": oData['breadcrumb_label'],
"url": sNewUrl, "url": sNewUrl,
'icon': oData['breadcrumb_icon'], 'icon': oData['breadcrumb_icon'],
'icon_type': oData['breadcrumb_icon_type'],
'description': '' 'description': ''
} }
}); });

View File

@@ -190,11 +190,13 @@ function SetObjectBreadCrumbEntry(DBObject $oObj, WebPage $oPage)
{ {
$sClass = get_class($oObj); // get the leaf class $sClass = get_class($oObj); // get the leaf class
$sIcon = MetaModel::GetClassIcon($sClass, false); $sIcon = MetaModel::GetClassIcon($sClass, false);
$sIconType = iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_IMAGE;
if ($sIcon == '') if ($sIcon == '')
{ {
$sIcon = utils::GetAbsoluteUrlAppRoot().'images/breadcrumb_object.png'; $sIcon = 'fas fa-cube';
$sIconType = iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES;
} }
$oPage->SetBreadCrumbEntry("ui-details-$sClass-".$oObj->GetKey(), $oObj->Get('friendlyname'), MetaModel::GetName($sClass).': '.$oObj->Get('friendlyname'), '', $sIcon); $oPage->SetBreadCrumbEntry("ui-details-$sClass-".$oObj->GetKey(), $oObj->Get('friendlyname'), MetaModel::GetName($sClass).': '.$oObj->Get('friendlyname'), '', $sIcon, $sIconType);
} }
/** /**
@@ -239,7 +241,7 @@ function DisplaySearchSet($oP, $oFilter, $bSearchForm = true, $sBaseClass = '',
//$iCount = $oBlock->GetDisplayedCount(); //$iCount = $oBlock->GetDisplayedCount();
$sPageId = "ui-search-".$oFilter->GetClass(); $sPageId = "ui-search-".$oFilter->GetClass();
$sLabel = MetaModel::GetName($oFilter->GetClass()); $sLabel = MetaModel::GetName($oFilter->GetClass());
$oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', '../images/breadcrumb-search.png'); $oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
} }
} }
} }
@@ -631,7 +633,7 @@ try
$sPageId = "ui-global-search"; $sPageId = "ui-global-search";
$sLabel = Dict::S('UI:SearchResultsTitle'); $sLabel = Dict::S('UI:SearchResultsTitle');
$sDescription = Dict::S('UI:SearchResultsTitle+'); $sDescription = Dict::S('UI:SearchResultsTitle+');
$oP->SetBreadCrumbEntry($sPageId, $sLabel, $sDescription, '', utils::GetAbsoluteUrlAppRoot().'images/breadcrumb-search.png'); $oP->SetBreadCrumbEntry($sPageId, $sLabel, $sDescription, '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->add("<div style=\"padding: 10px;\">\n"); $oP->add("<div style=\"padding: 10px;\">\n");
$oP->add("<div class=\"header_message\" id=\"full_text_progress\" style=\"position: fixed; background-color: #cccccc; opacity: 0.7; padding: 1.5em;\">\n"); $oP->add("<div class=\"header_message\" id=\"full_text_progress\" style=\"position: fixed; background-color: #cccccc; opacity: 0.7; padding: 1.5em;\">\n");
$oP->add('<img id="full_text_indicator" src="../images/indicator.gif">&nbsp;<span style="padding: 1.5em;">'.Dict::Format('UI:Search:Ongoing', htmlentities($sFullText, ENT_QUOTES, 'UTF-8')).'</span>'); $oP->add('<img id="full_text_indicator" src="../images/indicator.gif">&nbsp;<span style="padding: 1.5em;">'.Dict::Format('UI:Search:Ongoing', htmlentities($sFullText, ENT_QUOTES, 'UTF-8')).'</span>');

View File

@@ -48,7 +48,7 @@ $sOQLClause = utils::ReadParam('oql_clause', '', false, 'raw_data');
$sFilter = utils::ReadParam('filter', '', false, 'raw_data'); $sFilter = utils::ReadParam('filter', '', false, 'raw_data');
$sOperation = utils::ReadParam('operation', ''); $sOperation = utils::ReadParam('operation', '');
$oP->SetBreadCrumbEntry('ui-tool-universalsearch', Dict::S('Menu:UniversalSearchMenu'), Dict::S('Menu:UniversalSearchMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oP->SetBreadCrumbEntry('ui-tool-universalsearch', Dict::S('Menu:UniversalSearchMenu'), Dict::S('Menu:UniversalSearchMenu+'), '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
@@ -117,7 +117,7 @@ if ($oFilter != null)
//$iCount = $oBlock->GetDisplayedCount(); //$iCount = $oBlock->GetDisplayedCount();
$sPageId = "ui-search-".$oFilter->GetClass(); $sPageId = "ui-search-".$oFilter->GetClass();
$sLabel = MetaModel::GetName($oFilter->GetClass()); $sLabel = MetaModel::GetName($oFilter->GetClass());
$oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', '../images/breadcrumb-search.png'); $oP->SetBreadCrumbEntry($sPageId, $sLabel, '', '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
// Menu node // Menu node
$sFilter = $oFilter->ToOQL(); $sFilter = $oFilter->ToOQL();

View File

@@ -243,7 +243,7 @@ try
case 'errors': case 'errors':
$sTitle = 'Audit Errors'; $sTitle = 'Audit Errors';
$oP->SetBreadCrumbEntry('ui-tool-auditerrors', $sTitle, '', '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oP->SetBreadCrumbEntry('ui-tool-auditerrors', $sTitle, '', '', 'fas fa-stethoscope', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$iCategory = utils::ReadParam('category', ''); $iCategory = utils::ReadParam('category', '');
$iRuleIndex = utils::ReadParam('rule', 0); $iRuleIndex = utils::ReadParam('rule', 0);
@@ -268,7 +268,7 @@ try
case 'audit': case 'audit':
default: default:
$oP->SetBreadCrumbEntry('ui-tool-audit', Dict::S('Menu:Audit'), Dict::S('UI:Audit:InteractiveAudit'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oP->SetBreadCrumbEntry('ui-tool-audit', Dict::S('Menu:Audit'), Dict::S('UI:Audit:InteractiveAudit'), '', 'fas fa-stethoscope', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->add('<div class="page_header"><h1>'.Dict::S('UI:Audit:InteractiveAudit').'</h1><img style="margin-top: -20px; margin-right: 10px; float: right;" src="../images/clean.png"/></div>'); $oP->add('<div class="page_header"><h1>'.Dict::S('UI:Audit:InteractiveAudit').'</h1><img style="margin-top: -20px; margin-right: 10px; float: right;" src="../images/clean.png"/></div>');
$oAuditFilter = new DBObjectSearch('AuditCategory'); $oAuditFilter = new DBObjectSearch('AuditCategory');
$oCategoriesSet = new DBObjectSet($oAuditFilter); $oCategoriesSet = new DBObjectSet($oAuditFilter);

View File

@@ -33,7 +33,7 @@ try
$iStep = utils::ReadParam('step', 1); $iStep = utils::ReadParam('step', 1);
$oPage = new iTopWebPage(Dict::S('UI:Title:BulkImport')); $oPage = new iTopWebPage(Dict::S('UI:Title:BulkImport'));
$oPage->SetBreadCrumbEntry('ui-tool-bulkimport', Dict::S('Menu:CSVImportMenu'), Dict::S('UI:Title:BulkImport+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oPage->SetBreadCrumbEntry('ui-tool-bulkimport', Dict::S('Menu:CSVImportMenu'), Dict::S('UI:Title:BulkImport+'), '', 'fas fa-file-import', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
/** /**
* Helper function to build a select from the list of valid classes for a given action * Helper function to build a select from the list of valid classes for a given action

View File

@@ -35,7 +35,7 @@ $oP->add('<div class="page_header" style="padding:0.5em;">');
$oP->add('<h1>'.dict::S('UI:NotificationsMenu:Title').'</h1>'); $oP->add('<h1>'.dict::S('UI:NotificationsMenu:Title').'</h1>');
$oP->add('</div>'); $oP->add('</div>');
$oP->SetBreadCrumbEntry('ui-tool-notifications', Dict::S('Menu:NotificationsMenu'), Dict::S('Menu:NotificationsMenu+'), '', '../images/bell.png'); $oP->SetBreadCrumbEntry('ui-tool-notifications', Dict::S('Menu:NotificationsMenu'), Dict::S('Menu:NotificationsMenu+'), '', 'fas fa-bell', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->StartCollapsibleSection(Dict::S('UI:NotificationsMenu:Help'), true, 'notifications-home'); $oP->StartCollapsibleSection(Dict::S('UI:NotificationsMenu:Help'), true, 'notifications-home');
$oP->add('<div style="padding: 1em; font-size:10pt;background:#E8F3CF;margin-top: 0.25em;">'); $oP->add('<div style="padding: 1em; font-size:10pt;background:#E8F3CF;margin-top: 0.25em;">');

View File

@@ -507,7 +507,7 @@ try
case 'display': case 'display':
default: default:
$oPage->SetBreadCrumbEntry('ui-tool-preferences', Dict::S('UI:Preferences'), Dict::S('UI:Preferences'), '', $oPage->SetBreadCrumbEntry('ui-tool-preferences', Dict::S('UI:Preferences'), Dict::S('UI:Preferences'), '',
utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); 'fas fa-user-cog', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
DisplayPreferences($oPage); DisplayPreferences($oPage);
} }
} }

View File

@@ -92,7 +92,7 @@ $sOperation = utils::ReadParam('operation', 'menu');
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$oP = new iTopWebPage(Dict::S('UI:RunQuery:Title')); $oP = new iTopWebPage(Dict::S('UI:RunQuery:Title'));
$oP->SetBreadCrumbEntry('ui-tool-runquery', Dict::S('Menu:RunQueriesMenu'), Dict::S('Menu:RunQueriesMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oP->SetBreadCrumbEntry('ui-tool-runquery', Dict::S('Menu:RunQueriesMenu'), Dict::S('Menu:RunQueriesMenu+'), '', 'fas fa-terminal', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
// Main program // Main program
$sExpression = utils::ReadParam('expression', '', false, 'raw_data'); $sExpression = utils::ReadParam('expression', '', false, 'raw_data');
@@ -208,7 +208,7 @@ EOF
} }
} }
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?'.implode('&', $aArgs); $sUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?'.implode('&', $aArgs);
$oP->SetBreadCrumbEntry($sPageId, $sLabel, $oFilter->ToOQL(true), $sUrl, '../images/breadcrumb-search.png'); $oP->SetBreadCrumbEntry($sPageId, $sLabel, $oFilter->ToOQL(true), $sUrl, 'fas fa-terminal', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->p(''); $oP->p('');
$oP->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false, 'runQuery'); $oP->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false, 'runQuery');

View File

@@ -1134,7 +1134,7 @@ $oPage = new iTopWebPage(Dict::S('UI:Schema:Title'));
$oPage->no_cache(); $oPage->no_cache();
$oPage->SetBreadCrumbEntry('ui-tool-datamodel', Dict::S('Menu:DataModelMenu'), Dict::S('Menu:DataModelMenu+'), '', $oPage->SetBreadCrumbEntry('ui-tool-datamodel', Dict::S('Menu:DataModelMenu'), Dict::S('Menu:DataModelMenu+'), '',
utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); 'fas fa-book', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oPage->add_script( $oPage->add_script(
<<<EOF <<<EOF
var autocompleteClassLabelAndCode = []; var autocompleteClassLabelAndCode = [];

View File

@@ -52,7 +52,7 @@ try
$oP->add('<h1>'.dict::S('UI:TagAdminMenu:Title').'</h1>'); $oP->add('<h1>'.dict::S('UI:TagAdminMenu:Title').'</h1>');
$oP->add('</div>'); $oP->add('</div>');
$oP->SetBreadCrumbEntry('ui-tool-tag-admin', Dict::S('Menu:TagAdminMenu'), Dict::S('Menu:TagAdminMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oP->SetBreadCrumbEntry('ui-tool-tag-admin', Dict::S('Menu:TagAdminMenu'), Dict::S('Menu:TagAdminMenu+'), '', 'fas fa-tags', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$sSearchHeaderForceDropdown = '<select id="select_class" name="class" onChange="this.form.submit();">'; $sSearchHeaderForceDropdown = '<select id="select_class" name="class" onChange="this.form.submit();">';
$aClassLabels = array(); $aClassLabels = array();

View File

@@ -0,0 +1,11 @@
<div id="{{ aBreadCrumbs.sId }}" class="ibo-breadcrumbs"></div>
{# TODO: Move this to a dedicated script file #}
{% if aBreadCrumbs.aWidgetOptions is defined %}
<script type="text/javascript" src="js/components/breadcrumbs.js"></script>
<script type="text/javascript">
setTimeout(function(){
$('#{{ aBreadCrumbs.sId }}').breadcrumbs({{ aBreadCrumbs.aWidgetOptions|json_encode|raw }});
}, 500);
</script>
{% endif %}

View File

@@ -1,8 +1,8 @@
<nav {% if sId is defined %}id="{{ sId }}"{% endif%} class="ibo-navigation-menu"> <nav id="{{ aNavigationMenu.sId }}" class="ibo-navigation-menu">
<div class="ibo-navigation-menu--body"> <div class="ibo-navigation-menu--body">
<div class="ibo-navigation-menu--top-part"> <div class="ibo-navigation-menu--top-part">
<a class="ibo-navigation-menu--square-company-logo" title="{{ sAppRevisionNumber }}" href="{{ sAppIconLink }}"> <a class="ibo-navigation-menu--square-company-logo" title="{{ aNavigationMenu.sAppRevisionNumber }}" href="{{ aNavigationMenu.sAppIconLink }}">
<img src="{{ sAppSquareIconUrl }}" alt="{{ 'UI:Layout:NavigationMenu:CompanyLogo:AltText'|dict_s }}" /> <img src="{{ aNavigationMenu.sAppSquareIconUrl }}" alt="{{ 'UI:Layout:NavigationMenu:CompanyLogo:AltText'|dict_s }}" />
</a> </a>
<a class="ibo-navigation-menu--toggler" data-role="ibo-navigation-menu--toggler" title="{{ 'UI:Layout:NavigationMenu:Toggler:Tooltip'|dict_s }}" href="#"> <a class="ibo-navigation-menu--toggler" data-role="ibo-navigation-menu--toggler" title="{{ 'UI:Layout:NavigationMenu:Toggler:Tooltip'|dict_s }}" href="#">
<span class="ibo-navigation-menu--toggler-icon"> <span class="ibo-navigation-menu--toggler-icon">
@@ -13,8 +13,8 @@
</a> </a>
</div> </div>
<div class="ibo-navigation-menu--middle-part"> <div class="ibo-navigation-menu--middle-part">
{% for aMenuGroup in aMenuGroups %} {% for aMenuGroup in aNavigationMenu.aMenuGroups %}
{% include 'layouts/navigation-menu/menu-group.html.twig' with aMenuGroup %} {{ include('layouts/navigation-menu/menu-group.html.twig', { aMenuGroup: aMenuGroup }, false) }}
{% endfor %} {% endfor %}
</div> </div>
<div class="ibo-navigation-menu--bottom-part"> <div class="ibo-navigation-menu--bottom-part">
@@ -29,8 +29,8 @@
<span class="ibo-navigation-menu--menu-filter-hotkey">{{ 'UI:Layout:NavigationMenu:MenuFilter:Input:Hotkey'|dict_s }}</span> <span class="ibo-navigation-menu--menu-filter-hotkey">{{ 'UI:Layout:NavigationMenu:MenuFilter:Input:Hotkey'|dict_s }}</span>
</div> </div>
<div class="ibo-navigation-menu--menu-groups"> <div class="ibo-navigation-menu--menu-groups">
{% for aMenuGroup in aMenuGroups %} {% for aMenuGroup in aNavigationMenu.aMenuGroups %}
{% include 'layouts/navigation-menu/menu-nodes.html.twig' with aMenuGroup %} {{ include('layouts/navigation-menu/menu-nodes.html.twig', { aMenuGroup: aMenuGroup }, false) }}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
@@ -40,6 +40,6 @@
<script type="text/javascript" src="js/layouts/navigation-menu.js"></script> <script type="text/javascript" src="js/layouts/navigation-menu.js"></script>
<script type="text/javascript"> <script type="text/javascript">
setTimeout(function(){ setTimeout(function(){
$('#{{ sId }}').navigation_menu(); $('#{{ aNavigationMenu.sId }}').navigation_menu();
}, 500); }, 500);
</script> </script>

View File

@@ -5,10 +5,10 @@
{% else %} {% else %}
<span class="ibo-navigation-menu--menu-node-title">{{ aMenuNode.sTitle }}</span> <span class="ibo-navigation-menu--menu-node-title">{{ aMenuNode.sTitle }}</span>
{% endif %} {% endif %}
{% if aMenuNode.aChildNodes is defined and aMenuNode.aChildNodes|length > 0 %} {% if aMenuNode.aSubMenuNodes is defined and aMenuNode.aSubMenuNodes|length > 0 %}
<ul> <ul>
{% for aSubMenuNode in aMenuGroup.aSubMenuNodes %} {% for aSubMenuNode in aMenuNode.aSubMenuNodes %}
{% include 'layouts/navigation-menu/menu-node.html.twig' with aSubMenuNode %} {{ include('layouts/navigation-menu/menu-node.html.twig', { aMenuNode: aSubMenuNode }, false) }}
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}

View File

@@ -2,7 +2,7 @@
<h2 class="ibo-navigation-menu--menu-nodes-title">{{ aMenuGroup.sTitle }}</h2> <h2 class="ibo-navigation-menu--menu-nodes-title">{{ aMenuGroup.sTitle }}</h2>
<ul> <ul>
{% for aMenuNode in aMenuGroup.aSubMenuNodes %} {% for aMenuNode in aMenuGroup.aSubMenuNodes %}
{% include 'layouts/navigation-menu/menu-node.html.twig' with aMenuNode %} {{ include('layouts/navigation-menu/menu-node.html.twig', { aMenuNode: aMenuNode }, false) }}
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>

View File

@@ -0,0 +1,3 @@
<nav id="{{ aTopBar.sId }}" class="ibo-top-bar">
{{ include('components/breadcrumbs/layout.html.twig', { aBreadCrumbs: aTopBar.aComponents.aBreadCrumbs }, false) }}
</nav>

View File

@@ -36,11 +36,9 @@
{% endblock %} {% endblock %}
</head> </head>
<body data-gui-type="backoffice"> <body data-gui-type="backoffice">
{% include 'layouts/navigation-menu/layout.html.twig' with aLayouts.aNavigationMenu %} {{ include('layouts/navigation-menu/layout.html.twig', { aNavigationMenu: aLayouts.aNavigationMenu }, false) }}
<div id="ibo-page-container"> <div id="ibo-page-container">
<nav id="ibo-top-bar" class="ibo-top-bar"> {{ include('layouts/top-bar/layout.html.twig', { aTopBar: aLayouts.aTopBar }, false) }}
<span>item</span><span>item</span><span>item</span><span>item</span><span>item</span><span>item</span><span>item</span><span>item</span>
</nav>
<main id="ibo-page-content"> <main id="ibo-page-content">
<div>item</div> <div>item</div>
<div> <div>

View File

@@ -98,7 +98,7 @@ $sOperation = utils::ReadParam('operation', 'menu');
$oAppContext = new ApplicationContext(); $oAppContext = new ApplicationContext();
$oP = new iTopWebPage(Dict::S('UI:RunQuery:Title')); $oP = new iTopWebPage(Dict::S('UI:RunQuery:Title'));
$oP->SetBreadCrumbEntry('ui-tool-runquery', Dict::S('Menu:RunQueriesMenu'), Dict::S('Menu:RunQueriesMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oP->SetBreadCrumbEntry('ui-tool-runquery', Dict::S('Menu:RunQueriesMenu'), Dict::S('Menu:RunQueriesMenu+'), '', 'fas fa-terminal', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
// Main program // Main program
$sExpression = utils::ReadParam('expression', '', false, 'raw_data'); $sExpression = utils::ReadParam('expression', '', false, 'raw_data');
@@ -213,7 +213,7 @@ EOF
} }
} }
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?'.implode('&', $aArgs); $sUrl = utils::GetAbsoluteUrlAppRoot().'pages/run_query.php?'.implode('&', $aArgs);
$oP->SetBreadCrumbEntry($sPageId, $sLabel, $oFilter->ToOQL(true), $sUrl, '../images/breadcrumb-search.png'); $oP->SetBreadCrumbEntry($sPageId, $sLabel, $oFilter->ToOQL(true), $sUrl, 'fas fa-terminal', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
$oP->p(''); $oP->p('');
$oP->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false, 'runQuery'); $oP->StartCollapsibleSection(Dict::S('UI:RunQuery:MoreInfo'), false, 'runQuery');

View File

@@ -375,7 +375,7 @@ EOF
else else
{ {
$oP = new iTopWebPage('iTop Export'); $oP = new iTopWebPage('iTop Export');
$oP->SetBreadCrumbEntry('ui-tool-export', Dict::S('Menu:ExportMenu'), Dict::S('Menu:ExportMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png'); $oP->SetBreadCrumbEntry('ui-tool-export', Dict::S('Menu:ExportMenu'), Dict::S('Menu:ExportMenu+'), '', 'fas fa-file-export', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
} }
if ($sExpression === null) if ($sExpression === null)