#185 Navigation Breadcrumb - Beta version

- Any page has a breadcrumb (except if POST and a number of pages like "new object")
- Added Home + Menu buttons showed when the left pane is closed
- Configuration: breadcrumb.max_count (0 to disable)


SVN:trunk[4022]
This commit is contained in:
Romain Quetiez
2016-05-03 15:06:14 +00:00
parent dd41dc05f5
commit 668e822fc6
15 changed files with 312 additions and 83 deletions

View File

@@ -37,6 +37,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
private $m_sMessage;
private $m_sInitScript;
protected $m_oTabs;
protected $bBreadCrumbEnabled;
protected $sBreadCrumbEntryId;
protected $sBreadCrumbEntryLabel;
protected $sBreadCrumbEntryDescription;
@@ -50,11 +51,15 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
ApplicationContext::SetUrlMakerClass('iTopStandardURLMaker');
$this->sBreadCrumbEntryId = null;
$this->sBreadCrumbEntryLabel = null;
$this->sBreadCrumbEntryDescription = null;
$this->sBreadCrumbEntryUrl = null;
$this->sBreadCrumbEntryIcon = '';
if ((count($_POST) == 0) || (array_key_exists('loginop', $_POST)))
{
// Create a breadcrumb entry for the current page, but get its title as late as possible (page title could be changed later)
$this->bBreadCrumbEnabled = true;
}
else
{
$this->bBreadCrumbEnabled = false;
}
$this->m_sMenu = "";
$this->m_sMessage = '';
@@ -107,45 +112,44 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
}
}
protected function PrepareLayout()
protected function IsMenuPaneVisible()
{
$bForceMenuPane = utils::ReadParam('force_menu_pane', null);
$sInitClosed = '';
if (($bForceMenuPane !== null) && ($bForceMenuPane == 0))
{
$sInitClosed = 'initClosed: true,';
}
$this->add_script(
<<<EOF
function ShowAboutBox()
{
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', {operation: 'about_box'}, function(data){
$('body').append(data);
});
return false;
}
EOF
);
$bLeftPaneOpen = true;
if (MetaModel::GetConfig()->Get('demo_mode'))
{
// Leave the pane opened
}
else
{
if (utils::ReadParam('force_menu_pane', null) === 0)
{
$bLeftPaneOpen = false;
}
elseif (appUserPreferences::GetPref('menu_pane', 'open') == 'closed')
{
$bLeftPaneOpen = false;
}
}
return $bLeftPaneOpen;
}
protected function PrepareLayout()
{
$bLeftPaneOpen = true;
if (MetaModel::GetConfig()->Get('demo_mode'))
{
// No pin button
$sConfigureWestPane = '';
}
else
{
$sConfigureWestPane =
<<<EOF
if (GetUserPreference('menu_pane', 'open') == 'closed')
{
myLayout.close('west');
}
myLayout.addPinBtn( "#tPinMenu", "west" );
EOF;
}
$sInitClosed = $this->IsMenuPaneVisible() ? '' : 'initClosed: true,';
$sJSDisconnectedMessage = json_encode(Dict::S('UI:DisconnectedDlgMessage'));
$sJSTitle = json_encode(Dict::S('UI:DisconnectedDlgTitle'));
$sJSLoginAgain = json_encode(Dict::S('UI:LoginAgain'));
@@ -172,11 +176,12 @@ EOF;
paneSize = GetUserPreference('menu_size', 300)
myLayout = $('body').layout({
west : {
$sInitClosed minSize: 200, size: paneSize, spacing_open: 16, spacing_close: 16, slideTrigger_open: "mouseover", hideTogglerOnSlide: true, enableCursorHotkey: false,
$sInitClosed minSize: 200, size: paneSize, spacing_open: 16, spacing_close: 16, slideTrigger_open: "click", hideTogglerOnSlide: true, enableCursorHotkey: false,
onclose_end: function(name, elt, state, options, layout)
{
if (state.isSliding == false)
{
$('.menu-pane-exclusive').show();
SetUserPreference('menu_pane', 'closed', true);
}
},
@@ -192,6 +197,7 @@ EOF;
{
if (state.isSliding == false)
{
$('.menu-pane-exclusive').hide();
SetUserPreference('menu_pane', 'open', true);
}
}
@@ -570,6 +576,7 @@ EOF
*/
public function SetBreadCrumbEntry($sId, $sLabel, $sDescription, $sUrl = '', $sIcon = '')
{
$this->bBreadCrumbEnabled = true;
$this->sBreadCrumbEntryId = $sId;
$this->sBreadCrumbEntryLabel = $sLabel;
$this->sBreadCrumbEntryDescription = $sDescription;
@@ -577,6 +584,19 @@ EOF
$this->sBreadCrumbEntryIcon = $sIcon;
}
/**
* State that there will be no breadcrumb item for the current page
*/
public function DisableBreadCrumb()
{
$this->bBreadCrumbEnabled = false;
$this->sBreadCrumbEntryId = null;
$this->sBreadCrumbEntryLabel = null;
$this->sBreadCrumbEntryDescription = null;
$this->sBreadCrumbEntryUrl = null;
$this->sBreadCrumbEntryIcon = null;
}
public function AddToMenu($sHtml)
{
$this->m_sMenu .= $sHtml;
@@ -701,9 +721,6 @@ EOF
'selectedList' => 1,
);
$sJSMultiselectOptions = json_encode($aMultiselectOptions);
$siTopInstanceId = json_encode(APPROOT);
$sNewEntry = is_null($this->sBreadCrumbEntryId) ? 'null' : json_encode(array('id' => $this->sBreadCrumbEntryId, 'url' => $this->sBreadCrumbEntryUrl, 'label' => htmlentities($this->sBreadCrumbEntryLabel, ENT_QUOTES, 'UTF-8'), 'description' => htmlentities($this->sBreadCrumbEntryDescription, ENT_QUOTES, 'UTF-8'), 'icon' => $this->sBreadCrumbEntryIcon));
$this->add_ready_script(
<<<EOF
// Since the event is only triggered when the hash changes, we need to trigger
@@ -715,12 +732,38 @@ EOF
$('.multiselect').multiselect($sJSMultiselectOptions);
$('#itop-breadcrumb').breadcrumb({itop_instance_id: $siTopInstanceId, new_entry: $sNewEntry});
FixSearchFormsDisposition();
EOF
);
$iBreadCrumbMaxCount = utils::GetConfig()->Get('breadcrumb.max_count');
if ($iBreadCrumbMaxCount > 1)
{
$siTopInstanceId = json_encode(APPROOT);
if ($this->bBreadCrumbEnabled)
{
if (is_null($this->sBreadCrumbEntryId))
{
$this->sBreadCrumbEntryId = $this->s_title;
$this->sBreadCrumbEntryLabel = $this->s_title;
$this->sBreadCrumbEntryDescription = $this->s_title;
$this->sBreadCrumbEntryUrl = '';
$this->sBreadCrumbEntryIcon = utils::GetAbsoluteUrlAppRoot().'images/wrench.png';
}
$sNewEntry = json_encode(array('id' => $this->sBreadCrumbEntryId, 'url' => $this->sBreadCrumbEntryUrl, 'label' => htmlentities($this->sBreadCrumbEntryLabel, ENT_QUOTES, 'UTF-8'), 'description' => htmlentities($this->sBreadCrumbEntryDescription, ENT_QUOTES, 'UTF-8'), 'icon' => $this->sBreadCrumbEntryIcon));
}
else
{
$sNewEntry = 'null';
}
$this->add_ready_script(
<<<EOF
$('#itop-breadcrumb').breadcrumb({itop_instance_id: $siTopInstanceId, new_entry: $sNewEntry, max_count: $iBreadCrumbMaxCount});
EOF
);
}
if ($this->GetOutputFormat() == 'html')
{
foreach($this->a_headers as $s_header)
@@ -1009,8 +1052,18 @@ EOF
$sHtml .= ' <div id="top-bar" class="ui-helper-clearfix" style="width:100%">';
$sHtml .= self::FilterXSS($sApplicationBanner);
$GoHomeInitialStyle = $this->IsMenuPaneVisible() ? 'display: none;' : '';
$sHtml .= ' <table id="top-bar-table">';
$sHtml .= ' <tr>';
$sHtml .= ' <td id="open-left-pane" class="menu-pane-exclusive" style="'.$GoHomeInitialStyle.'" onclick="$(\'body\').layout().open(\'west\');">';
$sHtml .= ' <img src="../images/menu.png">';
$sHtml .= ' </td>';
$sHtml .= ' <td id="go-home" class="menu-pane-exclusive" style="'.$GoHomeInitialStyle.'">';
$sHtml .= ' <a href="'.utils::GetAbsoluteUrlAppRoot().'pages/UI.php"><img src="../images/home.png"></a>';
$sHtml .= ' </td>';
$sHtml .= ' <td class="top-bar-spacer menu-pane-exclusive" style="'.$GoHomeInitialStyle.'">';
$sHtml .= ' </td>';
$sHtml .= ' <td id="top-bar-table-breadcrumb">';
$sHtml .= ' <div id="itop-breadcrumb"></div>';
$sHtml .= ' </td>';

View File

@@ -906,6 +906,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => true,
),
'breadcrumb.max_count' => array(
'type' => 'integer',
'description' => 'Maximum number of items kept in the history breadcrumb. Set it to 0 to entirely disable the breadcrumb.',
'default' => 8,
'value' => 8,
'source_of_value' => '',
'show_in_conf_sample' => false,
),
);
public function IsProperty($sPropCode)

View File

@@ -2202,6 +2202,32 @@ span.refresh-button {
#top-bar-table {
width: 100%;
padding-left: 5px;
}
#top-bar-table #open-left-pane {
text-align: center;
width: 40px !important;
cursor: pointer;
}
#top-bar-table #go-home {
text-align: center;
width: 40px !important;
}
#top-bar-table #go-home a {
text-decoration: none;
color: #555555;
font-size: 9pt;
padding: 0;
background: none;
display: inline-block;
line-height: 55px;
width: 100%;
}
#top-bar-table .top-bar-spacer {
width: 35px !important;
}
#top-bar-table #top-bar-table-search {
@@ -2213,13 +2239,16 @@ span.refresh-button {
overflow: hidden;
float: left;
background: #f1f1f1;
margin-left: -20px;
}
#itop-breadcrumb ul {
display: inline;
}
#itop-breadcrumb li {
list-style: none;
float: left;
margin: 0 22px 6px 0;
margin: 0 22px 0px 0;
}
#itop-breadcrumb li .icon img {
height: 15px;
@@ -2231,11 +2260,6 @@ span.refresh-button {
filter: url("data:image/svg+xml;utf8,<svg version='1.1' xmlns='http://www.w3.org/2000/svg' height='0'><filter id='greyscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' /></filter></svg>#greyscale");
opacity: 0.5;
}
#itop-breadcrumb li:hover .icon img {
-webkit-filter: none;
filter: none;
opacity: 1;
}
#itop-breadcrumb li a {
text-decoration: none;
color: #555555;
@@ -2243,6 +2267,11 @@ span.refresh-button {
padding: 0;
background: none;
}
#itop-breadcrumb li a:hover .icon img {
-webkit-filter: none;
filter: none;
opacity: 1;
}
#itop-breadcrumb li a span.truncate {
max-width: 200px;
white-space: nowrap;
@@ -2266,6 +2295,20 @@ span.refresh-button {
#itop-breadcrumb li:last-child a::after {
display: none;
}
#itop-breadcrumb li .itop-breadcrumb-current {
text-decoration: none;
color: #555555;
font-size: 9pt;
padding: 0;
background: none;
}
#itop-breadcrumb li .itop-breadcrumb-current span.truncate {
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
.ui-datepicker-buttonpane, .ui-timepicker-div {

View File

@@ -1622,6 +1622,37 @@ span.refresh-button {
#top-bar-table {
width: 100%;
padding-left: 5px;
$top-button-width: 40px;
$top-button-heigth: 55px;
$top-button-spacer: 35px;
#open-left-pane {
text-align: center;
width: $top-button-width !important;
cursor: pointer;
}
#go-home {
text-align: center;
width: $top-button-width !important;
a {
text-decoration: none;
color: #555;
font-size: 9pt;
padding: 0;
background: none;
// Make the whole cell clickable
display: inline-block;
line-height: $top-button-heigth;
width: 100%;
}
}
.top-bar-spacer{
width: $top-button-spacer !important;
}
#top-bar-table-search{
width: 347px;
}
@@ -1631,12 +1662,15 @@ span.refresh-button {
overflow: hidden;
float: left;
background: $frame-background-color;
margin-left: -20px;
ul {
display: inline;
}
li{
list-style: none;
float: left;
margin: 0 22px 6px 0;
margin: 0 22px 0px 0;
.icon img{
height: 15px;
@@ -1652,18 +1686,19 @@ span.refresh-button {
opacity: 0.5;
}
&:hover .icon img{
-webkit-filter: none;
filter: none;
opacity: 1;
}
a{
text-decoration: none;
color: #555;
font-size: 9pt;
padding: 0;
background: none;
&:hover .icon img{
-webkit-filter: none;
filter: none;
opacity: 1;
}
span.truncate
{
// Ellipsis
@@ -1693,6 +1728,24 @@ span.refresh-button {
&:last-child a::after{
display: none;
}
.itop-breadcrumb-current{
text-decoration: none;
color: #555;
font-size: 9pt;
padding: 0;
background: none;
span.truncate
{
// Ellipsis
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
}
}
}
}
.ui-datepicker-buttonpane, .ui-timepicker-div {

BIN
images/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

BIN
images/menu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

BIN
images/wrench.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

View File

@@ -11,6 +11,7 @@ $(function()
{
itop_instance_id: '',
new_entry: null,
max_count: 8
},
// the constructor
@@ -23,14 +24,12 @@ $(function()
if(typeof(Storage) !== "undefined")
{
var sBreadCrumbStorageKey = this.options.itop_instance_id + 'breadcrumb-v1';
var aBreadCrumb = [];
var sBreadCrumbData = sessionStorage.getItem(sBreadCrumbStorageKey);
if (sBreadCrumbData !== null)
$(window).bind( 'hashchange', function(e)
{
aBreadCrumb = JSON.parse(sBreadCrumbData);
}
var iDisplayableItems = aBreadCrumb.length;
me._RefreshLatestEntry();
});
aBreadCrumb = this._Read();
if (this.options.new_entry !== null) {
var sUrl = this.options.new_entry.url;
@@ -49,13 +48,10 @@ $(function()
icon: this.options.new_entry.icon,
url: sUrl
});
// Keep only the last N items
aBreadCrumb = aBreadCrumb.slice(-8);
// Do not show the last = current item
iDisplayableItems = aBreadCrumb.length - 1;
// Keep only the last <max_count> items
aBreadCrumb = aBreadCrumb.slice(-(this.options.max_count));
}
sBreadCrumbData = JSON.stringify(aBreadCrumb);
sessionStorage.setItem(sBreadCrumbStorageKey, sBreadCrumbData);
this._Write(aBreadCrumb);
var sBreadCrumbHtml = '<ul>';
for (iEntry in aBreadCrumb)
{
@@ -72,7 +68,15 @@ $(function()
if (sTitle.length == 0) {
sTitle = oEntry['label'];
}
sBreadCrumbHtml += '<li><a class="itop-breadcrumb-link" breadcrumb-entry="'+iEntry+'" href="'+oEntry['url']+'" title="'+sTitle+'">'+sIconSpec+'<span class="truncate">'+oEntry['label']+'</span></a></li>';
if ((this.options.new_entry !== null) && (iEntry == aBreadCrumb.length - 1))
{
// Last entry is the current page
sBreadCrumbHtml += '<li><div class="itop-breadcrumb-current" breadcrumb-entry="'+iEntry+'" title="'+sTitle+'">'+sIconSpec+'<span class="truncate">'+oEntry['label']+'</span></div></li>';
}
else
{
sBreadCrumbHtml += '<li><a class="itop-breadcrumb-link" breadcrumb-entry="'+iEntry+'" href="'+oEntry['url']+'" title="'+sTitle+'">'+sIconSpec+'<span class="truncate">'+oEntry['label']+'</span></a></li>';
}
}
}
sBreadCrumbHtml += '</ul>';
@@ -106,6 +110,36 @@ $(function()
_setOption: function( key, value )
{
this._super( key, value );
},
_Read: function()
{
var sBreadCrumbStorageKey = this.options.itop_instance_id + 'breadcrumb-v1';
var aBreadCrumb = [];
var sBreadCrumbData = sessionStorage.getItem(sBreadCrumbStorageKey);
if (sBreadCrumbData !== null)
{
aBreadCrumb = JSON.parse(sBreadCrumbData);
}
return aBreadCrumb;
},
_Write: function(aBreadCrumb)
{
var sBreadCrumbStorageKey = this.options.itop_instance_id + 'breadcrumb-v1';
sBreadCrumbData = JSON.stringify(aBreadCrumb);
sessionStorage.setItem(sBreadCrumbStorageKey, sBreadCrumbData);
},
// Refresh the latest entry (navigating to a tab)
_RefreshLatestEntry: function()
{
aBreadCrumb = this._Read();
var iDisplayableItems = aBreadCrumb.length;
if (this.options.new_entry !== null) {
// The current page is the last entry in the breadcrumb, let's refresh it
aBreadCrumb[aBreadCrumb.length - 1].url = window.location.href;
$('#itop-breadcrumb li:last-of-type a').attr('href', window.location.href);
}
this._Write(aBreadCrumb);
}
});
});

View File

@@ -319,7 +319,7 @@ try
$oP->add_linked_script("../js/linksdirectwidget.js");
$oP->add_linked_script("../js/extkeywidget.js");
$oP->add_linked_script("../js/jquery.blockUI.js");
break;
break;
}
switch($operation)
@@ -363,13 +363,19 @@ try
if (!is_null($oObj))
{
$sClass = get_class($oObj); // get the leaf class
$oP->SetBreadCrumbEntry("ui-details-$sClass-$id", $oObj->Get('friendlyname'), $sClass.': '.$oObj->Get('friendlyname'), '', MetaModel::GetClassIcon($sClass, false));
$sIcon = MetaModel::GetClassIcon($sClass, false);
if ($sIcon == '')
{
$sIcon = utils::GetAbsoluteUrlAppRoot().'images/breadcrumb_object.png';
}
$oP->SetBreadCrumbEntry("ui-details-$sClass-$id", $oObj->Get('friendlyname'), MetaModel::GetName($sClass).': '.$oObj->Get('friendlyname'), '', $sIcon);
DisplayDetails($oP, $sClass, $oObj, $id);
}
}
break;
case 'release_lock_and_details':
$oP->DisableBreadCrumb();
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
$oObj = MetaModel::GetObject($sClass, $id);
@@ -561,6 +567,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'modify': // Form to modify an object
$oP->DisableBreadCrumb();
$sClass = utils::ReadParam('class', '', false, 'class');
$id = utils::ReadParam('id', '');
if ( empty($sClass) || empty($id)) // TO DO: check that the class name is valid !
@@ -590,6 +597,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'select_for_modify_all': // Select the list of objects to be modified (bulk modify)
$oP->DisableBreadCrumb();
$oP->set_title(Dict::S('UI:ModifyAllPageTitle'));
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
if (empty($sFilter))
@@ -607,6 +615,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'form_for_modify_all': // Form to modify multiple objects (bulk modify)
$oP->DisableBreadCrumb();
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
$sClass = utils::ReadParam('class', '', false, 'class');
$oFullSetFilter = DBObjectSearch::unserialize($sFilter);
@@ -619,6 +628,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'preview_or_modify_all': // Preview or apply bulk modify
$oP->DisableBreadCrumb();
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
// TO DO: limit the search filter by the user context
$oFilter = DBObjectSearch::unserialize($sFilter); // TO DO : check that the filter is valid
@@ -643,6 +653,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'new': // Form to create a new object
$oP->DisableBreadCrumb();
$sClass = utils::ReadParam('class', '', false, 'class');
$sStateCode = utils::ReadParam('state', '');
$bCheckSubClass = utils::ReadParam('checkSubclass', true);
@@ -757,6 +768,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'apply_modify': // Applying the modifications to an existing object
$oP->DisableBreadCrumb();
$sClass = utils::ReadPostedParam('class', '');
$sClassLabel = MetaModel::GetName($sClass);
$id = utils::ReadPostedParam('id', '');
@@ -860,6 +872,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'select_for_deletion': // Select multiple objects for deletion
$oP->DisableBreadCrumb();
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
if (empty($sFilter))
{
@@ -876,6 +889,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'bulk_delete_confirmed': // Confirm bulk deletion of objects
$oP->DisableBreadCrumb();
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
if (!utils::IsTransactionValid($sTransactionId))
{
@@ -887,6 +901,7 @@ EOF
case 'delete':
case 'bulk_delete': // Actual bulk deletion (if confirmed)
$oP->DisableBreadCrumb();
$sClass = utils::ReadParam('class', '', false, 'class');
$sClassLabel = MetaModel::GetName($sClass);
$aObjects = array();
@@ -938,6 +953,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'apply_new': // Creation of a new object
$oP->DisableBreadCrumb();
$sClass = utils::ReadPostedParam('class', '', 'class');
$sClassLabel = MetaModel::GetName($sClass);
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
@@ -1008,6 +1024,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'select_bulk_stimulus': // Form displayed when applying a stimulus to many objects
$oP->DisableBreadCrumb();
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
$sStimulus = utils::ReadParam('stimulus', '');
$sState = utils::ReadParam('state', '');
@@ -1031,6 +1048,7 @@ EOF
break;
case 'bulk_stimulus':
$oP->DisableBreadCrumb();
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
$sStimulus = utils::ReadParam('stimulus', '');
$sState = utils::ReadParam('state', '');
@@ -1196,6 +1214,7 @@ EOF
break;
case 'bulk_apply_stimulus':
$oP->DisableBreadCrumb();
$bPreviewMode = utils::ReadPostedParam('preview_mode', false);
$sFilter = utils::ReadPostedParam('filter', '', false, 'raw_data');
$sStimulus = utils::ReadPostedParam('stimulus', '');
@@ -1329,6 +1348,7 @@ EOF
break;
case 'stimulus': // Form displayed when applying a stimulus (state change)
$oP->DisableBreadCrumb();
$sClass = utils::ReadParam('class', '', false, 'class');
$id = utils::ReadParam('id', '');
$sStimulus = utils::ReadParam('stimulus', '');
@@ -1351,6 +1371,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'apply_stimulus': // Actual state change
$oP->DisableBreadCrumb();
$sClass = utils::ReadPostedParam('class', '');
$id = utils::ReadPostedParam('id', '');
$sTransactionId = utils::ReadPostedParam('transaction_id', '');
@@ -1489,14 +1510,19 @@ EOF
$sRelation = utils::ReadParam('relation', 'impact');
$sDirection = utils::ReadParam('direction', 'down');
$iGroupingThreshold = utils::ReadParam('g', 5);
$oObj = MetaModel::GetObject($sClass, $id);
$iMaxRecursionDepth = MetaModel::GetConfig()->Get('relations_max_depth', 20);
$aSourceObjects = array($oObj);
$oP->set_title(MetaModel::GetRelationDescription($sRelation).' '.$oObj->GetName());
if ($sRelation == 'depends on')
$sPageId = "ui-relation-graph-".$sClass.'::'.$id;
$sLabel = $oObj->GetName().' '.MetaModel::GetRelationLabel($sRelation);
$sDescription = MetaModel::GetRelationDescription($sRelation).' '.$oObj->GetName();
$oP->SetBreadCrumbEntry($sPageId, $sLabel, $sDescription);
if ($sRelation == 'depends on')
{
$sRelation = 'impacts';
$sDirection = 'up';
@@ -1561,6 +1587,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'kill_lock':
$oP->DisableBreadCrumb();
$sClass = utils::ReadParam('class', '');
$id = utils::ReadParam('id', '');
iTopOwnershipLock::KillLock($sClass, $id);
@@ -1571,6 +1598,7 @@ EOF
///////////////////////////////////////////////////////////////////////////////////////////
case 'cancel': // An action was cancelled
$oP->DisableBreadCrumb();
$oP->set_title(Dict::S('UI:OperationCancelled'));
$oP->add('<h1>'.Dict::S('UI:OperationCancelled').'</h1>');
break;
@@ -1582,7 +1610,6 @@ EOF
$oMenuNode = ApplicationMenu::GetMenuNode(ApplicationMenu::GetMenuIndexById(ApplicationMenu::GetActiveNodeId()));
if (is_object($oMenuNode))
{
$oMenuNode->RenderContent($oP, $oAppContext->GetAsHash());
$oP->set_title($oMenuNode->GetLabel());
}

View File

@@ -54,6 +54,8 @@ $sOQLClause = utils::ReadParam('oql_clause', '', false, 'raw_data');
$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
$sOperation = utils::ReadParam('operation', '');
$oP->SetBreadCrumbEntry('ui-tool-universalsearch', Dict::S('Menu:UniversalSearchMenu'), Dict::S('Menu:UniversalSearchMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');
// First part: select the class to search for
$oP->add("<form>");
$oP->add(Dict::S('UI:UniversalSearch:LabelSelectTheClass')."<select style=\"width: 150px;\" id=\"select_class\" name=\"baseClass\" onChange=\"this.form.submit();\">");

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2015 Combodo SARL
// Copyright (C) 2010-2016 Combodo SARL
//
// This file is part of iTop.
//
@@ -19,7 +19,7 @@
/**
* Execute and shows the data quality audit
*
* @copyright Copyright (C) 2010-2015 Combodo SARL
* @copyright Copyright (C) 2010-2016 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
/**
@@ -156,10 +156,11 @@ try
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
$oP = new iTopWebPage(Dict::S('UI:Audit:Title'));
switch($operation)
{
case 'csv':
$oP->DisableBreadCrumb();
// Big result sets cause long OQL that cannot be passed (serialized) as a GET parameter
// Therefore we don't use the standard "search_oql" operation of UI.php to display the CSV
$iCategory = utils::ReadParam('category', '');
@@ -221,6 +222,8 @@ try
break;
case 'errors':
$sTitle = 'Audit Errors';
$oP->SetBreadCrumbEntry('ui-tool-auditerrors', $sTitle, '', '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');
$iCategory = utils::ReadParam('category', '');
$iRuleIndex = utils::ReadParam('rule', 0);
@@ -244,6 +247,7 @@ try
case 'audit':
default:
$oP->SetBreadCrumbEntry('ui-tool-audit', Dict::S('Menu:Audit'), Dict::S('UI:Audit:InteractiveAudit'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');
$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');
$oCategoriesSet = new DBObjectSet($oAuditFilter);

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
// Copyright (C) 2010-2016 Combodo SARL
//
// This file is part of iTop.
//
@@ -20,7 +20,7 @@
* CSV Import Page
* Wizard to import CSV (or TSV) data into the database
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @copyright Copyright (C) 2010-2016 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
try
@@ -39,7 +39,8 @@ try
$iStep = utils::ReadParam('step', 1);
$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');
/**
* Helper function to build a select from the list of valid classes for a given action
* @param string $sName The name of the select in the HTML form

View File

@@ -99,6 +99,7 @@ $sOperation = utils::ReadParam('operation', 'menu');
$oAppContext = new ApplicationContext();
$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');
// Main program
$sExpression = utils::ReadParam('expression', '', false, 'raw_data');

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2012 Combodo SARL
// Copyright (C) 2010-2016 Combodo SARL
//
// This file is part of iTop.
//
@@ -20,7 +20,7 @@
/**
* Presentation of the data model
*
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @copyright Copyright (C) 2010-2016 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -570,6 +570,8 @@ $operation = utils::ReadParam('operation', '');
$oPage = new iTopWebPage(Dict::S('UI:Schema:Title'));
$oPage->no_cache();
$oPage->SetBreadCrumbEntry('ui-tool-datamodel', Dict::S('Menu:DataModelMenu'), Dict::S('Menu:DataModelMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');
$operation = utils::ReadParam('operation', '');
switch($operation)

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2015 Combodo SARL
// Copyright (C) 2015-2016 Combodo SARL
//
// This file is part of iTop.
//
@@ -19,7 +19,7 @@
/**
* Export data specified by an OQL or a query phrasebook entry
*
* @copyright Copyright (C) 2015 Combodo SARL
* @copyright Copyright (C) 2015-2016 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
@@ -336,6 +336,7 @@ EOF
else
{
$oP = new iTopWebPage('iTop Export');
$oP->SetBreadCrumbEntry('ui-tool-export', Dict::S('Menu:ExportMenu'), Dict::S('Menu:ExportMenu+'), '', utils::GetAbsoluteUrlAppRoot().'images/wrench.png');
}
if ($sExpression === null)