mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°4479 - Impact analysis : Display and apply filter before display impact analysis graphical
This commit is contained in:
@@ -838,6 +838,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
),
|
||||
'impact_analysis_lazy_loading' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'In the impact analysis view: display the analysis or filter before display',
|
||||
'default' => false,
|
||||
'value' => '',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'url_validation_pattern' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)',
|
||||
|
||||
@@ -1435,79 +1435,20 @@ class DisplayableGraph extends SimpleGraph
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects, $sObjClass, $iObjKey, $sContextKey, $aContextParams = array())
|
||||
{
|
||||
$aContextDefs = static::GetContextDefinitions($sContextKey, true, $aContextParams);
|
||||
$aExcludedByClass = array();
|
||||
foreach($aExcludedObjects as $oObj)
|
||||
{
|
||||
if (!array_key_exists(get_class($oObj), $aExcludedByClass))
|
||||
{
|
||||
$aExcludedByClass[get_class($oObj)] = array();
|
||||
}
|
||||
$aExcludedByClass[get_class($oObj)][] = $oObj->GetKey();
|
||||
}
|
||||
$sSftShort = Dict::S('UI:ElementsDisplayed');
|
||||
$sSearchToggle = Dict::S('UI:Search:Toggle');
|
||||
$oP->add("<div class=\"not-printable\">\n");
|
||||
$oP->add(
|
||||
<<<EOF
|
||||
<div id="ds_flash" class="search_box">
|
||||
<form id="dh_flash" class="search_form_handler closed">
|
||||
<h2 class="sf_title"><span class="sft_long">$sSftShort</span><span class="sft_short">$sSftShort</span><span class="sft_toggler fas fa-caret-down pull-right" title="$sSearchToggle"></span></h2>
|
||||
<div id="dh_flash_criterion_outer" class="sf_criterion_area"><div class="sf_criterion_row">
|
||||
EOF
|
||||
);
|
||||
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$("#dh_flash > .sf_title").click( function() {
|
||||
$("#dh_flash").toggleClass('closed');
|
||||
});
|
||||
$('#ReloadMovieBtn').button().button('disable');
|
||||
EOF
|
||||
);
|
||||
$aSortedElements = array();
|
||||
foreach($aResults as $sClassIdx => $aObjects)
|
||||
{
|
||||
foreach($aObjects as $oCurrObj)
|
||||
{
|
||||
$sSubClass = get_class($oCurrObj);
|
||||
$aSortedElements[$sSubClass] = MetaModel::GetName($sSubClass);
|
||||
}
|
||||
}
|
||||
|
||||
asort($aSortedElements);
|
||||
$idx = 0;
|
||||
foreach($aSortedElements as $sSubClass => $sClassName)
|
||||
{
|
||||
$oP->add("<span style=\"padding-right:2em; white-space:nowrap;\"><input type=\"checkbox\" id=\"exclude_$idx\" name=\"excluded[]\" value=\"$sSubClass\" checked onChange=\"$('#ReloadMovieBtn').button('enable')\"><label for=\"exclude_$idx\"> ".MetaModel::GetClassIcon($sSubClass)." $sClassName</label></span> ");
|
||||
$idx++;
|
||||
}
|
||||
$oP->add("<p style=\"text-align:right\"><button type=\"button\" id=\"ReloadMovieBtn\" onClick=\"DoReload()\">".Dict::S('UI:Button:Refresh')."</button></p>");
|
||||
$oP->add("</div></div></form>");
|
||||
$oP->add("</div>\n");
|
||||
$oP->add("</div>\n"); // class="not-printable"
|
||||
|
||||
$aAdditionalContexts = array();
|
||||
foreach($aContextDefs as $sKey => $aDefinition)
|
||||
{
|
||||
$aAdditionalContexts[] = array('key' => $sKey, 'label' => Dict::S($aDefinition['dict']), 'oql' => $aDefinition['oql'], 'default' => (array_key_exists('default', $aDefinition) && ($aDefinition['default'] == 'yes')));
|
||||
}
|
||||
|
||||
$sDirection = utils::ReadParam('d', 'horizontal');
|
||||
function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects, $sObjClass, $iObjKey, $sContextKey, $aContextParams = array(), $sLazyLoading = false)
|
||||
{
|
||||
list($aExcludedByClass, $aAdditionalContexts) = $this->DisplayFiltering($sContextKey, $aContextParams, $aExcludedObjects, $oP, $aResults, $sLazyLoading);
|
||||
$iGroupingThreshold = utils::ReadParam('g', 5);
|
||||
|
||||
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/fraphael.js');
|
||||
$oP->add_linked_stylesheet(utils::GetAbsoluteUrlAppRoot().'css/jquery.contextMenu.css');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.contextMenu.js');
|
||||
$oP->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/simple_graph.js');
|
||||
|
||||
try
|
||||
{
|
||||
$this->InitFromGraphviz();
|
||||
$sExportAsPdfURL = '';
|
||||
$sExportAsPdfURL = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=relation_pdf&relation='.$sRelation.'&direction='.($this->bDirectionDown ? 'down' : 'up');
|
||||
$oAppcontext = new ApplicationContext();
|
||||
$sContext = $oAppContext->GetForLink();
|
||||
$sDrillDownURL = utils::GetAbsoluteUrlAppRoot().'pages/UI.php?operation=details&class=%1$s&id=%2$s&'.$sContext;
|
||||
$sExportAsDocumentURL = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php?operation=relation_attachment&relation='.$sRelation.'&direction='.($this->bDirectionDown ? 'down' : 'up');
|
||||
@@ -1586,7 +1527,14 @@ EOF
|
||||
// Export as Attachment requires GD (for building the PDF) AND a valid objclass/objkey couple
|
||||
unset($aParams['export_as_attachment']);
|
||||
}
|
||||
$oP->add_ready_script("$('#$sId').simple_graph(".json_encode($aParams).");");
|
||||
if ($oP->IsPrintableVersion() || !$sLazyLoading) {
|
||||
$oP->add_ready_script(" $('#$sId').simple_graph(".json_encode($aParams).");");
|
||||
} else {
|
||||
$oP->add_script("function Load(){var aExcluded = []; $('input[name^=excluded]').each( function() {if (!$(this).prop('checked')) { aExcluded.push($(this).val()); }} ); var params= $.extend(".json_encode($aParams).", {excluded_classes: aExcluded}); $('#$sId').simple_graph(params);}");
|
||||
$oP->add_ready_script("$('#impacted_objects_lists').html('".Dict::S('Relation:impacts/NoFilteredData')."');$('#impacted_groups').html('".Dict::S('Relation:impacts/NoFilteredData')."');");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
@@ -1618,5 +1566,86 @@ EOF
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sContextKey
|
||||
* @param array $aContextParams
|
||||
* @param array $aExcludedObjects
|
||||
* @param \WebPage $oP
|
||||
* @param array $aResults
|
||||
* @param bool $sLazyLoading
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
* @since 2.7.7 & 3.0.1
|
||||
*/
|
||||
protected function DisplayFiltering($sContextKey, $aContextParams, $aExcludedObjects, $oP, $aResults, $sLazyLoading)
|
||||
{
|
||||
$aContextDefs = static::GetContextDefinitions($sContextKey, true, $aContextParams);
|
||||
$aExcludedByClass = array();
|
||||
foreach ($aExcludedObjects as $oObj) {
|
||||
if (!array_key_exists(get_class($oObj), $aExcludedByClass)) {
|
||||
$aExcludedByClass[get_class($oObj)] = array();
|
||||
}
|
||||
$aExcludedByClass[get_class($oObj)][] = $oObj->GetKey();
|
||||
}
|
||||
$sSftShort = Dict::S('UI:ElementsDisplayed');
|
||||
$sSearchToggle = Dict::S('UI:Search:Toggle');
|
||||
$oP->add("<div class=\"not-printable\">\n");
|
||||
$oP->add(
|
||||
<<<EOF
|
||||
<div id="ds_flash" class="search_box">
|
||||
<form id="dh_flash" class="search_form_handler">
|
||||
<h2 class="sf_title"><span class="sft_long">$sSftShort</span><span class="sft_short">$sSftShort</span><span class="sft_toggler fas fa-caret-down pull-right" title="$sSearchToggle"></span></h2>
|
||||
<div id="dh_flash_criterion_outer" class="sf_criterion_area"><div class="sf_criterion_row">
|
||||
EOF
|
||||
);
|
||||
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
$("#dh_flash > .sf_title").click( function() {
|
||||
$("#dh_flash").toggleClass('closed');
|
||||
});
|
||||
$('#ReloadMovieBtn').button().button('disable');
|
||||
EOF
|
||||
);
|
||||
if ($sLazyLoading) {
|
||||
$oP->add_ready_script("$('#ReloadMovieBtn').button('enable');");
|
||||
} else {
|
||||
$oP->add_ready_script("$('#dh_flash').addClass('closed');");
|
||||
}
|
||||
$aSortedElements = array();
|
||||
foreach ($aResults as $sClassIdx => $aObjects) {
|
||||
foreach ($aObjects as $oCurrObj) {
|
||||
$sSubClass = get_class($oCurrObj);
|
||||
$aSortedElements[$sSubClass] = MetaModel::GetName($sSubClass);
|
||||
}
|
||||
}
|
||||
|
||||
asort($aSortedElements);
|
||||
$idx = 0;
|
||||
foreach ($aSortedElements as $sSubClass => $sClassName) {
|
||||
$oP->add("<span style=\"padding-right:2em; white-space:nowrap;\"><input type=\"checkbox\" id=\"exclude_$idx\" name=\"excluded[]\" value=\"$sSubClass\" checked onChange=\"$('#ReloadMovieBtn').button('enable')\"><label for=\"exclude_$idx\"> ".MetaModel::GetClassIcon($sSubClass)." $sClassName</label></span> ");
|
||||
$idx++;
|
||||
}
|
||||
if ($sLazyLoading) {
|
||||
$sOnCLick = "Load(); $('#ReloadMovieBtn').attr('onclick','DoReload()');$('#ReloadMovieBtn').html('".Dict::S('UI:Button:Refresh')."');";
|
||||
$oP->add("<p style=\"text-align:right\"><button type=\"button\" id=\"ReloadMovieBtn\" onClick=\"$sOnCLick\">".Dict::S('Relation:impacts/LoadData')."</button></p>");
|
||||
} else {
|
||||
$sOnCLick = "DoReload()";
|
||||
$oP->add("<p style=\"text-align:right\"><button type=\"button\" id=\"ReloadMovieBtn\" onClick=\"$sOnCLick\">".Dict::S('UI:Button:Refresh')."</button></p>");
|
||||
}
|
||||
$oP->add("</div></div></form>");
|
||||
$oP->add("</div>\n");
|
||||
$oP->add("</div>\n"); // class="not-printable"
|
||||
|
||||
$aAdditionalContexts = array();
|
||||
foreach ($aContextDefs as $sKey => $aDefinition) {
|
||||
$aAdditionalContexts[] = array('key' => $sKey, 'label' => Dict::S($aDefinition['dict']), 'oql' => $aDefinition['oql'], 'default' => (array_key_exists('default', $aDefinition) && ($aDefinition['default'] == 'yes')));
|
||||
}
|
||||
|
||||
return array($aExcludedByClass, $aAdditionalContexts);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Relation:depends on/Description' => 'Elements impacting',
|
||||
'Relation:depends on/DownStream' => 'Depends on...',
|
||||
'Relation:depends on/UpStream' => 'Impacts...',
|
||||
'Relation:impacts/LoadData' => 'Load data',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Relation:depends on/Description' => 'Eléments dont dépend',
|
||||
'Relation:depends on/DownStream' => 'Dépend de...',
|
||||
'Relation:depends on/UpStream' => 'Impacte...',
|
||||
'Relation:impacts/LoadData' => 'Charger les données',
|
||||
'Relation:impacts/NoFilteredData' => 'Veuillez sélectionner des objets dans l\'onglet Graph',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -722,18 +722,25 @@ $(function()
|
||||
}
|
||||
if (oData.lists)
|
||||
{
|
||||
this.refresh_lists(oData.lists);
|
||||
if (this.options.excluded_classes.length > 0) {
|
||||
var newList = {};
|
||||
$.each(oData.lists, function (index, listId) {
|
||||
if (me.options.excluded_classes.indexOf(index) < 0) {
|
||||
newList[index] = listId;
|
||||
}
|
||||
});
|
||||
me.refresh_lists(newList);
|
||||
} else {
|
||||
me.refresh_lists(oData.lists);
|
||||
}
|
||||
}
|
||||
if (this.element.is(':visible'))
|
||||
{
|
||||
this._updateBBox();
|
||||
this.auto_scale();
|
||||
this._reset_pan_and_zoom();
|
||||
this.draw();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.bRedrawNeeded = true;
|
||||
if (me.element.is(':visible')) {
|
||||
me._updateBBox();
|
||||
me.auto_scale();
|
||||
me._reset_pan_and_zoom();
|
||||
me.draw();
|
||||
} else {
|
||||
me.bRedrawNeeded = true;
|
||||
}
|
||||
},
|
||||
refresh_groups: function(aGroups)
|
||||
|
||||
32
pages/UI.php
32
pages/UI.php
@@ -287,6 +287,16 @@ function DisplayMultipleSelectionForm($oP, $oFilter, $sNextOperation, $oChecker,
|
||||
$oP->add_ready_script("$('#1 table.listResults').trigger('check_all');");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $oP
|
||||
* @param $aResults
|
||||
* @param $sRelation
|
||||
* @param $sDirection
|
||||
* @param $oObj
|
||||
* for operation : 'swf_navigator'
|
||||
*
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
function DisplayNavigatorListTab($oP, $aResults, $sRelation, $sDirection, $oObj)
|
||||
{
|
||||
$oP->SetCurrentTab('UI:RelationshipList');
|
||||
@@ -299,22 +309,7 @@ function DisplayNavigatorListTab($oP, $aResults, $sRelation, $sDirection, $oObj)
|
||||
$oP->add("<h1>".MetaModel::GetRelationDescription($sOldRelation).' '.$oObj->GetName()."</h1>\n");
|
||||
$oP->add("<div id=\"impacted_objects_lists\">");
|
||||
$oP->add('<img src="../images/indicator.gif">');
|
||||
/*
|
||||
* Content is rendered asynchronously via pages/ajax.render.php?operation=relation_lists
|
||||
*/
|
||||
/*
|
||||
$iBlock = 1; // Zero is not a valid blockid
|
||||
foreach($aResults as $sListClass => $aObjects)
|
||||
{
|
||||
$oSet = CMDBObjectSet::FromArray($sListClass, $aObjects);
|
||||
$oP->add("<div class=\"page_header\">\n");
|
||||
$oP->add("<h2>".MetaModel::GetClassIcon($sListClass)." <span class=\"hilite\">".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aObjects), Metamodel::GetName($sListClass))."</h2>\n");
|
||||
$oP->add("</div>\n");
|
||||
$oBlock = DisplayBlock::FromObjectSet($oSet, 'list');
|
||||
$oBlock->Display($oP, $iBlock++, array('table_id' => get_class($oObj).'_'.$sRelation.'_'.$sDirection.'_'.$sListClass));
|
||||
$oP->P(' '); // Some space ?
|
||||
}
|
||||
*/
|
||||
|
||||
$oP->add("</div>");
|
||||
$oP->add("</div>");
|
||||
}
|
||||
@@ -1903,6 +1898,7 @@ EOF
|
||||
$oP->SetCurrentTabContainer('Navigator');
|
||||
|
||||
$sFirstTab = MetaModel::GetConfig()->Get('impact_analysis_first_tab');
|
||||
$sLazyLoading = MetaModel::GetConfig()->Get('impact_analysis_lazy_loading');
|
||||
$sContextKey = "itop-config-mgmt/relation_context/$sClass/$sRelation/$sDirection";
|
||||
|
||||
// Check if the current object supports Attachments, similar to AttachmentPlugin::IsTargetObject
|
||||
@@ -1926,13 +1922,13 @@ EOF
|
||||
{
|
||||
DisplayNavigatorListTab($oP, $aResults, $sRelation, $sDirection, $oObj);
|
||||
$oP->SetCurrentTab('UI:RelationshipGraph');
|
||||
$oDisplayGraph->Display($oP, $aResults, $sRelation, $oAppContext, array(), $sClassForAttachment, $iIdForAttachment, $sContextKey, array('this' => $oObj));
|
||||
$oDisplayGraph->Display($oP, $aResults, $sRelation, $oAppContext, array(), $sClassForAttachment, $iIdForAttachment, $sContextKey, array('this' => $oObj),$sLazyLoading);
|
||||
DisplayNavigatorGroupTab($oP);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oP->SetCurrentTab('UI:RelationshipGraph');
|
||||
$oDisplayGraph->Display($oP, $aResults, $sRelation, $oAppContext, array(), $sClassForAttachment, $iIdForAttachment, $sContextKey, array('this' => $oObj));
|
||||
$oDisplayGraph->Display($oP, $aResults, $sRelation, $oAppContext, array(), $sClassForAttachment, $iIdForAttachment, $sContextKey, array('this' => $oObj),$sLazyLoading);
|
||||
DisplayNavigatorListTab($oP, $aResults, $sRelation, $sDirection, $oObj);
|
||||
DisplayNavigatorGroupTab($oP);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user