diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 7debcbd80..c887a7a76 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -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)', diff --git a/core/displayablegraph.class.inc.php b/core/displayablegraph.class.inc.php index 06b405543..25513f4c5 100644 --- a/core/displayablegraph.class.inc.php +++ b/core/displayablegraph.class.inc.php @@ -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("
\n"); - $oP->add( -<< -
-

$sSftShort$sSftShort

-
-EOF - ); - - $oP->add_ready_script( -<< .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(" "); - $idx++; - } - $oP->add("

"); - $oP->add("
"); - $oP->add("
\n"); - $oP->add("\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("
\n"); + $oP->add( + << +
+

$sSftShort$sSftShort

+
+EOF + ); + + $oP->add_ready_script( + << .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(" "); + $idx++; + } + if ($sLazyLoading) { + $sOnCLick = "Load(); $('#ReloadMovieBtn').attr('onclick','DoReload()');$('#ReloadMovieBtn').html('".Dict::S('UI:Button:Refresh')."');"; + $oP->add("

"); + } else { + $sOnCLick = "DoReload()"; + $oP->add("

"); + } + $oP->add("
"); + $oP->add("
\n"); + $oP->add("\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); + } } diff --git a/datamodels/2.x/itop-config-mgmt/en.dict.itop-config-mgmt.php b/datamodels/2.x/itop-config-mgmt/en.dict.itop-config-mgmt.php index b2e3139d6..0b5735fa9 100755 --- a/datamodels/2.x/itop-config-mgmt/en.dict.itop-config-mgmt.php +++ b/datamodels/2.x/itop-config-mgmt/en.dict.itop-config-mgmt.php @@ -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', )); diff --git a/datamodels/2.x/itop-config-mgmt/fr.dict.itop-config-mgmt.php b/datamodels/2.x/itop-config-mgmt/fr.dict.itop-config-mgmt.php index 60d9bb67e..7dd80cab1 100755 --- a/datamodels/2.x/itop-config-mgmt/fr.dict.itop-config-mgmt.php +++ b/datamodels/2.x/itop-config-mgmt/fr.dict.itop-config-mgmt.php @@ -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', )); diff --git a/js/simple_graph.js b/js/simple_graph.js index 96210d684..f633ec210 100644 --- a/js/simple_graph.js +++ b/js/simple_graph.js @@ -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) diff --git a/pages/UI.php b/pages/UI.php index cb66fb0e0..6535f389d 100644 --- a/pages/UI.php +++ b/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("

".MetaModel::GetRelationDescription($sOldRelation).' '.$oObj->GetName()."

\n"); $oP->add("
"); $oP->add(''); - /* - * 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("
\n"); - $oP->add("

".MetaModel::GetClassIcon($sListClass)." ".Dict::Format('UI:Search:Count_ObjectsOf_Class_Found', count($aObjects), Metamodel::GetName($sListClass))."

\n"); - $oP->add("
\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("
"); $oP->add(""); } @@ -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); }