mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
FE: more defensive network topology hierarchy check #1308
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
@@ -565,14 +565,27 @@ function getChildren(node, list, path, visited = [])
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
function getHierarchy()
|
function getHierarchy()
|
||||||
{
|
{
|
||||||
|
let internetNode = null;
|
||||||
|
|
||||||
for(i in deviceListGlobal)
|
for(i in deviceListGlobal)
|
||||||
{
|
{
|
||||||
if(deviceListGlobal[i].devMac == 'Internet')
|
if(deviceListGlobal[i].devMac == 'Internet')
|
||||||
{
|
{
|
||||||
return (getChildren(deviceListGlobal[i], deviceListGlobal, ''))
|
internetNode = deviceListGlobal[i];
|
||||||
|
|
||||||
|
return (getChildren(internetNode, deviceListGlobal, ''))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!internetNode) {
|
||||||
|
showModalOk(
|
||||||
|
getString('Network_Configuration_Error'),
|
||||||
|
getString('Network_Root_Not_Configured')
|
||||||
|
);
|
||||||
|
console.error("getHierarchy(): Internet node not found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -671,8 +684,6 @@ function handleNodeClick(el)
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
var myTree;
|
var myTree;
|
||||||
|
|
||||||
|
|
||||||
var emSize;
|
var emSize;
|
||||||
var nodeHeight;
|
var nodeHeight;
|
||||||
// var sizeCoefficient = 1.4
|
// var sizeCoefficient = 1.4
|
||||||
@@ -689,140 +700,139 @@ function emToPx(em, element) {
|
|||||||
|
|
||||||
function initTree(myHierarchy)
|
function initTree(myHierarchy)
|
||||||
{
|
{
|
||||||
// calculate the drawing area based on teh tree width and available screen size
|
if(myHierarchy && myHierarchy.type !== "")
|
||||||
|
|
||||||
let baseFontSize = parseFloat($('html').css('font-size'));
|
|
||||||
let treeAreaHeight = ($(window).height() - 155); ;
|
|
||||||
// calculate the font size of the leaf nodes to fit everything into the tree area
|
|
||||||
leafNodesCount == 0 ? 1 : leafNodesCount;
|
|
||||||
|
|
||||||
emSize = pxToEm((treeAreaHeight/(leafNodesCount)).toFixed(2));
|
|
||||||
|
|
||||||
let screenWidthEm = pxToEm($('.networkTable').width()-15);
|
|
||||||
|
|
||||||
// init the drawing area size
|
|
||||||
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${emToPx(screenWidthEm)}px`)
|
|
||||||
|
|
||||||
if(myHierarchy.type == "")
|
|
||||||
{
|
{
|
||||||
showModalOk(getString('Network_Configuration_Error'), getString('Network_Root_Not_Configured'))
|
// calculate the drawing area based on the tree width and available screen size
|
||||||
|
let baseFontSize = parseFloat($('html').css('font-size'));
|
||||||
|
let treeAreaHeight = ($(window).height() - 155); ;
|
||||||
|
|
||||||
return;
|
// calculate the font size of the leaf nodes to fit everything into the tree area
|
||||||
}
|
leafNodesCount == 0 ? 1 : leafNodesCount;
|
||||||
|
|
||||||
// handle canvas and node size if only a few nodes
|
emSize = pxToEm((treeAreaHeight/(leafNodesCount)).toFixed(2));
|
||||||
emSize > 1 ? emSize = 1 : emSize = emSize;
|
|
||||||
|
|
||||||
let nodeHeightPx = emToPx(emSize*1);
|
let screenWidthEm = pxToEm($('.networkTable').width()-15);
|
||||||
let nodeWidthPx = emToPx(screenWidthEm / (parentNodesCount));
|
|
||||||
|
|
||||||
// handle if only a few nodes
|
// init the drawing area size
|
||||||
nodeWidthPx > 160 ? nodeWidthPx = 160 : nodeWidthPx = nodeWidthPx;
|
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${emToPx(screenWidthEm)}px`)
|
||||||
|
|
||||||
console.log(Treeviz);
|
// handle canvas and node size if only a few nodes
|
||||||
|
emSize > 1 ? emSize = 1 : emSize = emSize;
|
||||||
|
|
||||||
myTree = Treeviz.create({
|
let nodeHeightPx = emToPx(emSize*1);
|
||||||
htmlId: "networkTree",
|
let nodeWidthPx = emToPx(screenWidthEm / (parentNodesCount));
|
||||||
renderNode: nodeData => {
|
|
||||||
|
|
||||||
(!emptyArr.includes(nodeData.data.port )) ? port = nodeData.data.port : port = "";
|
// handle if only a few nodes
|
||||||
|
nodeWidthPx > 160 ? nodeWidthPx = 160 : nodeWidthPx = nodeWidthPx;
|
||||||
|
|
||||||
(port == "" || port == 0 || port == 'None' ) ? portBckgIcon = `<i class="fa fa-wifi"></i>` : portBckgIcon = `<i class="fa fa-ethernet"></i>`;
|
console.log(Treeviz);
|
||||||
|
|
||||||
portHtml = (port == "" || port == 0 || port == 'None' ) ? "   " : port;
|
myTree = Treeviz.create({
|
||||||
|
htmlId: "networkTree",
|
||||||
|
renderNode: nodeData => {
|
||||||
|
|
||||||
// Build HTML for individual nodes in the network diagram
|
(!emptyArr.includes(nodeData.data.port )) ? port = nodeData.data.port : port = "";
|
||||||
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ?
|
|
||||||
`<div class="netIcon">
|
|
||||||
${atob(nodeData.data.icon)}
|
|
||||||
</div>` : "";
|
|
||||||
devicePort = `<div class="netPort"
|
|
||||||
style="width:${emSize}em;height:${emSize}em">
|
|
||||||
${portHtml}</div>
|
|
||||||
<div class="portBckgIcon"
|
|
||||||
style="margin-left:-${emSize*0.7}em;">
|
|
||||||
${portBckgIcon}
|
|
||||||
</div>`;
|
|
||||||
collapseExpandIcon = nodeData.data.hiddenChildren ?
|
|
||||||
"square-plus" : "square-minus";
|
|
||||||
|
|
||||||
// generate +/- icon if node has children nodes
|
(port == "" || port == 0 || port == 'None' ) ? portBckgIcon = `<i class="fa fa-wifi"></i>` : portBckgIcon = `<i class="fa fa-ethernet"></i>`;
|
||||||
collapseExpandHtml = nodeData.data.hasChildren ?
|
|
||||||
`<div class="netCollapse"
|
|
||||||
style="font-size:${nodeHeightPx/2}px;top:${Math.floor(nodeHeightPx / 4)}px"
|
|
||||||
data-mytreepath="${nodeData.data.path}"
|
|
||||||
data-mytreemac="${nodeData.data.mac}">
|
|
||||||
<i class="fa fa-${collapseExpandIcon} pointer"></i>
|
|
||||||
</div>` : "";
|
|
||||||
|
|
||||||
selectedNodeMac = $(".nav-tabs-custom .active a").attr('data-mytabmac')
|
portHtml = (port == "" || port == 0 || port == 'None' ) ? "   " : port;
|
||||||
|
|
||||||
highlightedCss = nodeData.data.mac == selectedNodeMac ?
|
// Build HTML for individual nodes in the network diagram
|
||||||
" highlightedNode " : "";
|
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ?
|
||||||
cssNodeType = nodeData.data.devIsNetworkNodeDynamic ?
|
`<div class="netIcon">
|
||||||
" node-network-device " : " node-standard-device ";
|
${atob(nodeData.data.icon)}
|
||||||
|
</div>` : "";
|
||||||
|
devicePort = `<div class="netPort"
|
||||||
|
style="width:${emSize}em;height:${emSize}em">
|
||||||
|
${portHtml}</div>
|
||||||
|
<div class="portBckgIcon"
|
||||||
|
style="margin-left:-${emSize*0.7}em;">
|
||||||
|
${portBckgIcon}
|
||||||
|
</div>`;
|
||||||
|
collapseExpandIcon = nodeData.data.hiddenChildren ?
|
||||||
|
"square-plus" : "square-minus";
|
||||||
|
|
||||||
networkHardwareIcon = nodeData.data.devIsNetworkNodeDynamic ? `<span class="network-hw-icon">
|
// generate +/- icon if node has children nodes
|
||||||
<i class="fa-solid fa-hard-drive"></i>
|
collapseExpandHtml = nodeData.data.hasChildren ?
|
||||||
</span>` : "";
|
`<div class="netCollapse"
|
||||||
|
style="font-size:${nodeHeightPx/2}px;top:${Math.floor(nodeHeightPx / 4)}px"
|
||||||
|
data-mytreepath="${nodeData.data.path}"
|
||||||
|
data-mytreemac="${nodeData.data.mac}">
|
||||||
|
<i class="fa fa-${collapseExpandIcon} pointer"></i>
|
||||||
|
</div>` : "";
|
||||||
|
|
||||||
const badgeConf = getStatusBadgeParts(nodeData.data.presentLastScan, nodeData.data.alertDown, nodeData.data.mac, statusText = '')
|
selectedNodeMac = $(".nav-tabs-custom .active a").attr('data-mytabmac')
|
||||||
|
|
||||||
return result = `<div
|
highlightedCss = nodeData.data.mac == selectedNodeMac ?
|
||||||
class="node-inner hover-node-info box pointer ${highlightedCss} ${cssNodeType}"
|
" highlightedNode " : "";
|
||||||
style="height:${nodeHeightPx}px;font-size:${nodeHeightPx-5}px;"
|
cssNodeType = nodeData.data.devIsNetworkNodeDynamic ?
|
||||||
onclick="handleNodeClick(this)"
|
" node-network-device " : " node-standard-device ";
|
||||||
data-mac="${nodeData.data.mac}"
|
|
||||||
data-parentMac="${nodeData.data.parentMac}"
|
networkHardwareIcon = nodeData.data.devIsNetworkNodeDynamic ? `<span class="network-hw-icon">
|
||||||
data-name="${nodeData.data.name}"
|
<i class="fa-solid fa-hard-drive"></i>
|
||||||
data-ip="${nodeData.data.ip}"
|
</span>` : "";
|
||||||
data-mac="${nodeData.data.mac}"
|
|
||||||
data-vendor="${nodeData.data.vendor}"
|
const badgeConf = getStatusBadgeParts(nodeData.data.presentLastScan, nodeData.data.alertDown, nodeData.data.mac, statusText = '')
|
||||||
data-type="${nodeData.data.type}"
|
|
||||||
data-devIsNetworkNodeDynamic="${nodeData.data.devIsNetworkNodeDynamic}"
|
return result = `<div
|
||||||
data-lastseen="${nodeData.data.lastseen}"
|
class="node-inner hover-node-info box pointer ${highlightedCss} ${cssNodeType}"
|
||||||
data-firstseen="${nodeData.data.firstseen}"
|
style="height:${nodeHeightPx}px;font-size:${nodeHeightPx-5}px;"
|
||||||
data-relationship="${nodeData.data.relType}"
|
onclick="handleNodeClick(this)"
|
||||||
data-status="${nodeData.data.status}"
|
data-mac="${nodeData.data.mac}"
|
||||||
data-present="${nodeData.data.presentLastScan}"
|
data-parentMac="${nodeData.data.parentMac}"
|
||||||
data-alert="${nodeData.data.alertDown}"
|
data-name="${nodeData.data.name}"
|
||||||
data-icon="${nodeData.data.icon}"
|
data-ip="${nodeData.data.ip}"
|
||||||
>
|
data-mac="${nodeData.data.mac}"
|
||||||
<div class="netNodeText">
|
data-vendor="${nodeData.data.vendor}"
|
||||||
<strong><span>${devicePort} <span class="${badgeConf.cssText}">${deviceIcon}</span></span>
|
data-type="${nodeData.data.type}"
|
||||||
<span class="spanNetworkTree anonymizeDev" style="width:${nodeWidthPx-50}px">${nodeData.data.name}</span>
|
data-devIsNetworkNodeDynamic="${nodeData.data.devIsNetworkNodeDynamic}"
|
||||||
${networkHardwareIcon}
|
data-lastseen="${nodeData.data.lastseen}"
|
||||||
</strong>
|
data-firstseen="${nodeData.data.firstseen}"
|
||||||
|
data-relationship="${nodeData.data.relType}"
|
||||||
|
data-status="${nodeData.data.status}"
|
||||||
|
data-present="${nodeData.data.presentLastScan}"
|
||||||
|
data-alert="${nodeData.data.alertDown}"
|
||||||
|
data-icon="${nodeData.data.icon}"
|
||||||
|
>
|
||||||
|
<div class="netNodeText">
|
||||||
|
<strong><span>${devicePort} <span class="${badgeConf.cssText}">${deviceIcon}</span></span>
|
||||||
|
<span class="spanNetworkTree anonymizeDev" style="width:${nodeWidthPx-50}px">${nodeData.data.name}</span>
|
||||||
|
${networkHardwareIcon}
|
||||||
|
</strong>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
${collapseExpandHtml}`;
|
||||||
${collapseExpandHtml}`;
|
},
|
||||||
},
|
mainAxisNodeSpacing: 'auto',
|
||||||
mainAxisNodeSpacing: 'auto',
|
// secondaryAxisNodeSpacing: 0.3,
|
||||||
// secondaryAxisNodeSpacing: 0.3,
|
nodeHeight: nodeHeightPx,
|
||||||
nodeHeight: nodeHeightPx,
|
nodeWidth: nodeWidthPx,
|
||||||
nodeWidth: nodeWidthPx,
|
marginTop: '5',
|
||||||
marginTop: '5',
|
isHorizontal : true,
|
||||||
isHorizontal : true,
|
hasZoom: true,
|
||||||
hasZoom: true,
|
hasPan: true,
|
||||||
hasPan: true,
|
marginLeft: '10',
|
||||||
marginLeft: '10',
|
marginRight: '10',
|
||||||
marginRight: '10',
|
idKey: "mac",
|
||||||
idKey: "mac",
|
hasFlatData: false,
|
||||||
hasFlatData: false,
|
relationnalField: "children",
|
||||||
relationnalField: "children",
|
linkWidth: (nodeData) => 2,
|
||||||
linkWidth: (nodeData) => 2,
|
linkColor: (nodeData) => {
|
||||||
linkColor: (nodeData) => {
|
relConf = getRelationshipConf(nodeData.data.relType)
|
||||||
relConf = getRelationshipConf(nodeData.data.relType)
|
return relConf.color;
|
||||||
return relConf.color;
|
}
|
||||||
}
|
// onNodeClick: (nodeData) => handleNodeClick(nodeData),
|
||||||
// onNodeClick: (nodeData) => handleNodeClick(nodeData),
|
});
|
||||||
});
|
|
||||||
|
|
||||||
console.log(deviceListGlobal);
|
console.log(deviceListGlobal);
|
||||||
myTree.refresh(myHierarchy);
|
myTree.refresh(myHierarchy);
|
||||||
|
|
||||||
// hide spinning icon
|
// hide spinning icon
|
||||||
hideSpinner()
|
hideSpinner()
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
console.error("getHierarchy() not returning expected result");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user