mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-23 02:28:44 +02:00
A little bit of polishing on the impact analysis feature...
SVN:trunk[3630]
This commit is contained in:
@@ -282,22 +282,45 @@ class DisplayableNode extends GraphNode
|
||||
{
|
||||
if (count($aGroupProps['nodes']) >= $iThresholdCount)
|
||||
{
|
||||
$oNewNode = new DisplayableGroupNode($oGraph, $this->GetId().'::'.(($sStatus == 'reached') ? '_reached': ''));
|
||||
$oNewNode->SetProperty('label', 'x'.$aGroupProps['count']);
|
||||
$oNewNode->SetProperty('icon_url', $aGroupProps['icon_url']);
|
||||
$oNewNode->SetProperty('class', $sClass);
|
||||
$oNewNode->SetProperty('is_reached', ($sStatus == 'reached'));
|
||||
$oNewNode->SetProperty('count', $aGroupProps['count']);
|
||||
$sNewId = $this->GetId().'::'.(($sStatus == 'reached') ? '_reached': '');
|
||||
$oNewNode = $oGraph->GetNode($sNewId);
|
||||
if ($oNewNode == null)
|
||||
{
|
||||
$oNewNode = new DisplayableGroupNode($oGraph, $sNewId);
|
||||
$oNewNode->SetProperty('label', 'x'.$aGroupProps['count']);
|
||||
$oNewNode->SetProperty('icon_url', $aGroupProps['icon_url']);
|
||||
$oNewNode->SetProperty('class', $sClass);
|
||||
$oNewNode->SetProperty('is_reached', ($sStatus == 'reached'));
|
||||
$oNewNode->SetProperty('count', $aGroupProps['count']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oNewNode->SetProperty('count', $oNewNode->GetProperty('count')+$aGroupProps['count']);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$oIncomingEdge = new DisplayableEdge($oGraph, $this->GetId().'-'.$oNewNode->GetId(), $this, $oNewNode);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// Ignore this redundant egde
|
||||
}
|
||||
|
||||
$oIncomingEdge = new DisplayableEdge($oGraph, $this->GetId().'-'.$oNewNode->GetId(), $this, $oNewNode);
|
||||
|
||||
foreach($aGroupProps['nodes'] as $oNode)
|
||||
{
|
||||
foreach($oNode->GetIncomingEdges() as $oEdge)
|
||||
{
|
||||
if ($oEdge->GetSourceNode()->GetId() !== $this->GetId())
|
||||
{
|
||||
$oNewEdge = new DisplayableEdge($oGraph, $oEdge->GetId().'::'.$sClass, $oEdge->GetSourceNode(), $oNewNode);
|
||||
try
|
||||
{
|
||||
$oNewEdge = new DisplayableEdge($oGraph, $oEdge->GetId().'::'.$sClass, $oEdge->GetSourceNode(), $oNewNode);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
// ignore this edge
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($oNode->GetOutgoingEdges() as $oEdge)
|
||||
@@ -825,7 +848,6 @@ class DisplayableGraph extends SimpleGraph
|
||||
{
|
||||
throw new Exception($sDot);
|
||||
}
|
||||
$sDot = preg_replace('/.*label=.*,/', '', $sDot); // Get rid of label lines since they may contain weird characters than can break the split and pattern matching below
|
||||
|
||||
$aChunks = explode(";", $sDot);
|
||||
foreach($aChunks as $sChunk)
|
||||
@@ -975,7 +997,7 @@ class DisplayableGraph extends SimpleGraph
|
||||
$yMin = $aRemainingArea['ymin'];
|
||||
$yMax = $aRemainingArea['ymax'];
|
||||
|
||||
//$oPdf->Rect($xMin, $yMin, $xMax - $xMin, $yMax - $yMin, 'D', array(), array(225, 225, 225));
|
||||
//$oPdf->Rect($xMin, $yMin, $xMax - $xMin, $yMax - $yMin, 'D', array(), array(225, 50, 50));
|
||||
|
||||
$fPageW = $xMax - $xMin;
|
||||
$fPageH = $yMax - $yMin;
|
||||
@@ -1093,7 +1115,7 @@ class DisplayableGraph extends SimpleGraph
|
||||
$yMax = $yPos - $fPadding;
|
||||
}
|
||||
|
||||
return array('xmin' => $fMaxWidth + $fIconSize + 4*$fPadding, 'xmax' => $xMax, 'ymin' => $yMin, 'ymax' => $yMax);
|
||||
return array('xmin' => $xMin + $fMaxWidth + $fIconSize + 4*$fPadding, 'xmax' => $xMax, 'ymin' => $yMin, 'ymax' => $yMax);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1403,10 +1403,11 @@ abstract class MetaModel
|
||||
$aQueries[$sRemoteClass]['down'][$sLocalClass]['sQueryUp'] = $aNeighbourData['sQueryUp'];
|
||||
$aQueries[$sRemoteClass]['down'][$sLocalClass]['sDirection'] = 'both';
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Legacy definition of the relation '$sRelCode/$sRevertCode', defined on $sLocalClass (relation: $sRevertCode, inherited to $sClass), missing the counterpart query on class $sRemoteClass ($sRelCode)");
|
||||
}
|
||||
// Be silent in order to transparently support legacy data models where the counterpart query does not always exist
|
||||
//else
|
||||
//{
|
||||
// throw new Exception("Legacy definition of the relation '$sRelCode/$sRevertCode', defined on $sLocalClass (relation: $sRevertCode, inherited to $sClass), missing the counterpart query on class $sRemoteClass ($sRelCode)");
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class RelationObjectNode extends GraphNode
|
||||
/**
|
||||
* Formatting for GraphViz
|
||||
*/
|
||||
public function GetDotAttributes()
|
||||
public function GetDotAttributes($bNoLabel = false)
|
||||
{
|
||||
$sDot = parent::GetDotAttributes();
|
||||
if ($this->GetProperty('developped', false))
|
||||
@@ -114,7 +114,7 @@ class RelationRedundancyNode extends GraphNode
|
||||
/**
|
||||
* Formatting for GraphViz
|
||||
*/
|
||||
public function GetDotAttributes()
|
||||
public function GetDotAttributes($bNoLabel = false)
|
||||
{
|
||||
$sDisplayThreshold = sprintf('%.1f', $this->GetProperty('threshold'));
|
||||
$sDot = 'shape=doublecircle,fillcolor=indianred,fontcolor=papayawhip,label="'.$sDisplayThreshold.'"';
|
||||
|
||||
@@ -128,10 +128,14 @@ class GraphNode extends GraphElement
|
||||
$oGraph->_AddNode($this);
|
||||
}
|
||||
|
||||
public function GetDotAttributes()
|
||||
public function GetDotAttributes($bNoLabel = false)
|
||||
{
|
||||
$sLabel = addslashes($this->GetProperty('label', $this->GetId()));
|
||||
$sDot = 'label="'.$sLabel.'"';
|
||||
$sDot = '';
|
||||
if (!$bNoLabel)
|
||||
{
|
||||
$sLabel = addslashes($this->GetProperty('label', $this->GetId()));
|
||||
$sDot = 'label="'.$sLabel.'"';
|
||||
}
|
||||
return $sDot;
|
||||
}
|
||||
|
||||
@@ -264,10 +268,14 @@ class GraphEdge extends GraphElement
|
||||
return $this->oSinkNode;
|
||||
}
|
||||
|
||||
public function GetDotAttributes()
|
||||
public function GetDotAttributes($bNoLabel = false)
|
||||
{
|
||||
$sLabel = addslashes($this->GetProperty('label', ''));
|
||||
$sDot = 'label="'.$sLabel.'"';
|
||||
$sDot = '';
|
||||
if (!$bNoLabel)
|
||||
{
|
||||
$sLabel = addslashes($this->GetProperty('label', ''));
|
||||
$sDot = 'label="'.$sLabel.'"';
|
||||
}
|
||||
return $sDot;
|
||||
}
|
||||
}
|
||||
@@ -443,9 +451,10 @@ class SimpleGraph
|
||||
|
||||
/**
|
||||
* Get the description of the graph as a text string in the graphviz 'dot' language
|
||||
* @param $bNoLabel bool Whether or not to include the labels in the dot file
|
||||
* @return string
|
||||
*/
|
||||
public function GetDotDescription()
|
||||
public function GetDotDescription($bNoLabel = false)
|
||||
{
|
||||
$sDot =
|
||||
<<<EOF
|
||||
@@ -464,12 +473,12 @@ EOF
|
||||
|
||||
foreach($oIterator as $key => $oNode)
|
||||
{
|
||||
$sDot .= "\t\"".$oNode->GetId()."\" [ ".$oNode->GetDotAttributes()." ];\n";
|
||||
$sDot .= "\t\"".$oNode->GetId()."\" [ ".$oNode->GetDotAttributes($bNoLabel)." ];\n";
|
||||
if (count($oNode->GetOutgoingEdges()) > 0)
|
||||
{
|
||||
foreach($oNode->GetOutgoingEdges() as $oEdge)
|
||||
{
|
||||
$sDot .= "\t\"".$oNode->GetId()."\" -> \"".$oEdge->GetSinkNode()->GetId()."\" [ ".$oEdge->GetDotAttributes()." ];\n";
|
||||
$sDot .= "\t\"".$oNode->GetId()."\" -> \"".$oEdge->GetSinkNode()->GetId()."\" [ ".$oEdge->GetDotAttributes($bNoLabel)." ];\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,7 +565,7 @@ EOF
|
||||
@mkdir(APPROOT."data/tmp");
|
||||
}
|
||||
$sXdotFilePath = tempnam(APPROOT."data/tmp", 'xdot-');
|
||||
$sDotDescription = $this->GetDotDescription();
|
||||
$sDotDescription = $this->GetDotDescription(true); // true => don't put (localized) labels in the file, since it makes it harder to parse
|
||||
$sDotFilePath = tempnam(APPROOT."data/tmp", 'dot-');
|
||||
|
||||
$rFile = @fopen($sDotFilePath, "w");
|
||||
@@ -572,13 +581,14 @@ EOF
|
||||
$sHtml .= "<p><b>Error:</b></p>";
|
||||
$sHtml .= "<p>The command: <pre>$CommandLine</pre> returned $iRetCode</p>";
|
||||
$sHtml .= "<p>The output of the command is:<pre>\n".implode("\n", $aOutput)."</pre></p>";
|
||||
IssueLog::Error($sHtml);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml = '<pre>'.file_get_contents($sXdotFilePath).'</pre>';
|
||||
@unlink($sImageFilePath);
|
||||
@unlink($sXdotFilePath);
|
||||
}
|
||||
@unlink($sXdotFilePath);
|
||||
@unlink($sDotFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes der letzten sieben Tage nach Typ',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Changes der letzten sieben Tage nach Status',
|
||||
'Tickets:Related:OpenChanges' => 'Open changes~~',
|
||||
'Tickets:Related:RecentChanges' => 'Recent changes~~',
|
||||
'Tickets:Related:RecentChanges' => 'Recent changes (72h)~~',
|
||||
'Class:Change/Attribute:changemanager_email' => 'Change Manager Email',
|
||||
'Class:Change/Attribute:changemanager_email+' => '',
|
||||
'Class:Change/Attribute:parent_name' => 'Parent Change ref',
|
||||
|
||||
@@ -47,7 +47,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes by domain for the last 7 days',
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Changes by status for the last 7 days',
|
||||
'Tickets:Related:OpenChanges' => 'Open changes',
|
||||
'Tickets:Related:RecentChanges' => 'Recent changes',
|
||||
'Tickets:Related:RecentChanges' => 'Recent changes (72h)',
|
||||
));
|
||||
|
||||
// Dictionnay conventions
|
||||
|
||||
@@ -126,6 +126,6 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'UI-ChangeManagementOverview-ChangeByStatus-last-7-days' => 'Changements par statut',
|
||||
'UI:ChangeMgmtMenuOverview:Title' => 'Tableau de bord des changements pour les 7 derniers jours',
|
||||
'Tickets:Related:OpenChanges' => 'Changements en cours',
|
||||
'Tickets:Related:RecentChanges' => 'Changements récents',
|
||||
'Tickets:Related:RecentChanges' => 'Changements récents (72h)',
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -269,10 +269,10 @@ $(function()
|
||||
this.options.ymax = -9999;
|
||||
for(var k in this.aNodes)
|
||||
{
|
||||
this.options.xmin = Math.min(this.aNodes[k].x + this.aNodes[k].tx, this.options.xmin);
|
||||
this.options.xmax = Math.max(this.aNodes[k].x + this.aNodes[k].tx, this.options.xmax);
|
||||
this.options.ymin = Math.min(this.aNodes[k].y + this.aNodes[k].ty, this.options.ymin);
|
||||
this.options.ymax = Math.max(this.aNodes[k].y + this.aNodes[k].ty, this.options.ymax);
|
||||
this.options.xmin = Math.min(this.aNodes[k].x + this.aNodes[k].tx - this.aNodes[k].width/2, this.options.xmin);
|
||||
this.options.xmax = Math.max(this.aNodes[k].x + this.aNodes[k].tx + this.aNodes[k].width/2, this.options.xmax);
|
||||
this.options.ymin = Math.min(this.aNodes[k].y + this.aNodes[k].ty - this.aNodes[k].width/2, this.options.ymin);
|
||||
this.options.ymax = Math.max(this.aNodes[k].y + this.aNodes[k].ty + this.aNodes[k].width/2, this.options.ymax);
|
||||
}
|
||||
},
|
||||
_get_edge_path: function(oEdge)
|
||||
@@ -617,8 +617,10 @@ $(function()
|
||||
this.element.closest('.ui-tabs').tabs({ heightStyle: "fill" });
|
||||
this._close_all_tooltips();
|
||||
this.oPaper.rect(0, 0, this.element.width(), this.element.height()).attr({fill: '#000', opacity: 0.4, 'stroke-width': 0});
|
||||
$('#'+sId+'_refresh_btn').button('disable');
|
||||
$.post(sUrl, {excluded_classes: this.options.excluded_classes, g: this.options.grouping_threshold, sources: this.options.sources, excluded: this.options.excluded, contexts: aContexts, context_key: this.options.context_key }, function(data) {
|
||||
me.load(data);
|
||||
$('#'+sId+'_refresh_btn').button('enable');
|
||||
}, 'json');
|
||||
},
|
||||
export_as_attachment: function()
|
||||
@@ -665,13 +667,22 @@ $(function()
|
||||
$.post(sUrl, oParams, function(data) {
|
||||
var sDownloadLink = GetAbsoluteUrlAppRoot()+'pages/ajax.render.php?operation=download_document&class=Attachment&id='+data.att_id+'&field=contents';
|
||||
var sIcon = GetAbsoluteUrlModulesRoot()+'itop-attachments/icons/pdf.png';
|
||||
$('#attachments').append('<div class="attachment" id="display_attachment_'+data.att_id+'"><a data-preview="false" href="'+sDownloadLink+'"><img src="'+sIcon+'"><br/>'+sTitle+'.pdf<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveAttachment('+data.att_id+');"/></div>');
|
||||
if (jTab != null)
|
||||
{
|
||||
var re = /^([^(]+)\(([0-9]+)\)(.*)$/;
|
||||
var aParts = re.exec(sTabText);
|
||||
var iPrevCount = parseInt(aParts[2], 10);
|
||||
jTab.find('span').html(aParts[1]+'('+(1 + iPrevCount)+')'+aParts[3]);
|
||||
if (aParts == null)
|
||||
{
|
||||
// First attachment
|
||||
$('#attachments').html('<div class="attachment" id="display_attachment_'+data.att_id+'"><a data-preview="false" href="'+sDownloadLink+'"><img src="'+sIcon+'"><br/>'+sTitle+'.pdf<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveAttachment('+data.att_id+');"/></div>');
|
||||
jTab.find('span').html(sTabText +' (1)');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#attachments').append('<div class="attachment" id="display_attachment_'+data.att_id+'"><a data-preview="false" href="'+sDownloadLink+'"><img src="'+sIcon+'"><br/>'+sTitle+'.pdf<input id="attachment_'+data.att_id+'" type="hidden" name="attachments[]" value="'+data.att_id+'"/></a><br/><input type="button" class="btn_hidden" value="{$sDeleteBtn}" onClick="RemoveAttachment('+data.att_id+');"/></div>');
|
||||
var iPrevCount = parseInt(aParts[2], 10);
|
||||
jTab.find('span').html(aParts[1]+'('+(1 + iPrevCount)+')'+aParts[3]);
|
||||
}
|
||||
}
|
||||
}, 'json');
|
||||
return false;
|
||||
@@ -691,15 +702,15 @@ $(function()
|
||||
return sTooltipContent;
|
||||
},
|
||||
items: '.popupMenuTarget',
|
||||
tooltipClass: 'tooltip-simple-graph',
|
||||
position: {
|
||||
my: "center bottom-10",
|
||||
at: "center top",
|
||||
at: "center top",
|
||||
using: function( position, feedback ) {
|
||||
$(this).css( position );
|
||||
$( "<div>" )
|
||||
.addClass( "arrow" )
|
||||
.addClass( feedback.vertical )
|
||||
.addClass( feedback.horizontal )
|
||||
.appendTo( this );
|
||||
}
|
||||
}
|
||||
@@ -739,6 +750,11 @@ $(function()
|
||||
var sDataId = $(this).attr('data-id');
|
||||
$('.popupMenuTarget[data-id="'+sDataId+'"]').tooltip('close');
|
||||
});
|
||||
this.element.on("click", ":not(.tooltip-simple-graph *,.tooltip-simple-graph)", function(){
|
||||
$('.popupMenuTarget').each(function (i) {
|
||||
$(this).tooltip("close");
|
||||
});
|
||||
});
|
||||
},
|
||||
_get_tooltip_content: function(sNodeId)
|
||||
{
|
||||
|
||||
@@ -1851,6 +1851,7 @@ EOF
|
||||
}
|
||||
|
||||
$oPage->get_tcpdf()->AddPage();
|
||||
$oPage->get_tcpdf()->SetFont('dejavusans', '', 10, '', true); // Reset the font size to its default
|
||||
$oPage->add('<div class="page_header"><h1>'.Dict::S('UI:RelationshipList').'</h1></div>');
|
||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||
foreach($aResults as $sListClass => $aObjects)
|
||||
|
||||
Reference in New Issue
Block a user