Towards sidebar details

pull/1/head
ken 2021-07-18 20:54:45 +00:00
parent a808cbee5f
commit 28bf24ce7d
2 changed files with 324 additions and 332 deletions

View File

@ -54,8 +54,8 @@ class Sidebar extends React.Component {
<div id="searchBar" style={{ margin: "20px 0" }}> <div id="searchBar" style={{ margin: "20px 0" }}>
{this.renderTypeahead()} {this.renderTypeahead()}
</div> </div>
<div id="sidebarDetails" style={{ padding: "8px" }}> <div id="sideBarContent" style={{ padding: "8px" }}>
{this.renderDetails()} {this.props.sidebarDetails}
</div> </div>
</Slidebar> </Slidebar>
); );

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import ReactDOM from "react-dom";
//import cytoscape from "cytoscape"; //import cytoscape from "cytoscape";
import Cytoscape from "react-cytoscapejs"; import Cytoscape from "react-cytoscapejs";
//import CytoscapeComponent from "react-cytoscapejs"; //import CytoscapeComponent from "react-cytoscapejs";
@ -10,9 +11,9 @@ import SideBar from "./Sidebar";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { setCyElements } from "../features/evio/evioSlice"; import { setCyElements } from "../features/evio/evioSlice";
import { import {
setSelectedElement, //setSelectedElement,
clearSelectedElement, //clearSelectedElement,
elementTypes, //elementTypes,
setRedrawGraph, setRedrawGraph,
} from "../features/evio/evioSlice"; } from "../features/evio/evioSlice";
import { setCurrentView } from "../features/view/viewSlice"; import { setCurrentView } from "../features/view/viewSlice";
@ -70,25 +71,172 @@ class TopologyView extends React.Component {
}); });
} }
buildCyElements = (topologies) => {
var elements = [];
var nodeDetails = {};
if (topologies.length < 1) return elements;
var topology = topologies[0];
for (var nid in topology.Nodes) {
var node = topology.Nodes[nid];
var nodeData = {
group: "nodes",
data: {
id: node.NodeId,
},
};
if (node.hasOwnProperty("NodeName"))
nodeData["data"]["label"] = node.NodeName;
else nodeData["data"]["label"] = node.NodeId.slice(0, 12);
if (node.hasOwnProperty("Version"))
nodeData["data"]["version"] = node.Version;
else nodeData["data"]["version"] = "0.0.0";
if (node.hasOwnProperty("GeoCoordinates"))
nodeData["data"]["coords"] = node.GeoCoordinates;
else nodeData["data"]["coords"] = "0,0";
if (node.hasOwnProperty("Edges")) {
nodeData["data"]["edges"] = node.Edges;
if (node.Edges.length === 0) {
nodeData["data"]["state"] = nodeStates.noTunnels;
nodeData["data"]["color"] = "#F2BE22";
} else {
nodeData["data"]["state"] = nodeStates.connected;
nodeData["data"]["color"] = "#8AA626";
}
} else {
nodeData["data"]["state"] = nodeStates.notReporting;
nodeData["data"]["color"] = "#ADD8E6";
}
nodeDetails[node.NodeId] = nodeData;
}
for (var edgeId in topology.Edges) {
var edge = topology.Edges[edgeId];
if (edge["Descriptor"].length > 2) {
console.error(
"Too many edge descriptors reported ",
JSON.stringify(edge["Descriptor"])
);
}
var edgeData = {
group: "edges",
data: {},
};
edgeData["data"]["id"] = edge.EdgeId;
edgeData["data"]["descriptor"] = edge["Descriptor"];
edgeData["data"]["label"] = edge.EdgeId.slice(0, 12);
edgeData["data"]["source"] = edge["Descriptor"][0].Source;
edgeData["data"]["target"] = edge["Descriptor"][0].Target;
edgeData["data"]["color"] = this.getLinkColor(edge["Descriptor"][0].Type);
edgeData["data"]["style"] = this.getLinkStyle(
edge["Descriptor"][0].State
);
if (
edge["Descriptor"].length === 2 &&
edge["Descriptor"][0].Source > edge["Descriptor"][1].Source
) {
edgeData["data"]["source"] = edge["Descriptor"][1].Source;
edgeData["data"]["target"] = edge["Descriptor"][1].Target;
edgeData["data"]["color"] = this.getLinkColor(
edge["Descriptor"][1].Type
);
edgeData["data"]["style"] = this.getLinkStyle(
edge["Descriptor"][1].State
);
}
elements.push(edgeData);
}
var nodes = Object.keys(nodeDetails).sort();
nodes.forEach((nodeId) => elements.push(nodeDetails[nodeId]));
return elements;
};
getLinkColor(type) {
var linkColor;
switch (type) {
case "CETypeILongDistance":
linkColor = "#5E4FA2";
break;
case "CETypeLongDistance":
linkColor = "#5E4FA2";
break;
case "CETypePredecessor":
linkColor = "#01665E";
break;
case "CETypeSuccessor":
linkColor = "#01665E";
break;
default:
break;
}
return linkColor;
}
getLinkStyle(state) {
var linkStyle;
switch (state) {
case "CEStateInitialized":
case "CEStatePreAuth":
case "CEStateAuthorized":
case "CEStateCreated":
linkStyle = "dotted";
break;
case "CEStateConnected":
linkStyle = "solid";
break;
case "CEStateDisconnected":
case "CEStateDeleting":
linkStyle = "dashed";
break;
default:
break;
}
return linkStyle;
}
partitionElements(selectedElement) {
var neighborhood;
var excluded;
if (selectedElement.isNode()) {
neighborhood = selectedElement
.outgoers()
.union(selectedElement.incomers())
.union(selectedElement);
excluded = this.cy
.elements()
.difference(
selectedElement.outgoers().union(selectedElement.incomers())
)
.not(selectedElement);
let adj = selectedElement.neighborhood();
let abscomp = adj.absoluteComplement();
// console.log("nei", neighborhood, "adj", adj);
// console.log("excluded", excluded, "abscomp", abscomp);
} else if (selectedElement.isEdge()) {
neighborhood = selectedElement.connectedNodes().union(selectedElement);
excluded = this.cy
.elements()
.difference(selectedElement.connectedNodes())
.not(selectedElement);
}
return { neighborhood, excluded };
}
async queryGeoCoordinates(coordinates) { async queryGeoCoordinates(coordinates) {
coordinates = coordinates.split(","); coordinates = coordinates.split(",");
if (coordinates.length < 2) return "Unknown";
try { try {
const url = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${coordinates[0]},${coordinates[1]}&key=AIzaSyBjkkk4UyMh4-ihU1B1RR7uGocXpKECJhs&language=en`; const res = await fetch(
const res = await fetch(url); `https://maps.googleapis.com/maps/api/geocode/json?latlng=${coordinates[0]},${coordinates[1]}&key=AIzaSyBjkkk4UyMh4-ihU1B1RR7uGocXpKECJhs&language=en`
console.log("res.ok", res.ok);
var data = await res.json();
console.log("data", data);
console.log("data.results", data.results);
console.log("data.results.length", data.results.length);
console.log(
"data.results[data.results.length - 1].formatted_address",
data.results[data.results.length - 1].formatted_address
); );
var data = await res.json();
var nodeLocation = var nodeLocation =
data.results[data.results.length - 1].formatted_address; data.results[data.results.length - 1].formatted_address;
console.log("formatted_address", nodeLocation);
return nodeLocation.slice(7, nodeLocation.length); return nodeLocation.slice(7, nodeLocation.length);
} catch (err) { } catch (err) {
return "-"; return "Unknown";
} }
} }
@ -99,7 +247,7 @@ class TopologyView extends React.Component {
onChange={(selected) => { onChange={(selected) => {
if (selected.length > 0) { if (selected.length > 0) {
let selectedEle = this.cy let selectedEle = this.cy
.elements() //.elements()
.getElementById(selected[0].data.id); .getElementById(selected[0].data.id);
this.cy.elements().unselect(); this.cy.elements().unselect();
selectedEle.select(); selectedEle.select();
@ -152,55 +300,36 @@ class TopologyView extends React.Component {
); );
return nodeContent; return nodeContent;
} }
getConnectedLinkDetails(source, tgt, connectedEdges) {
for (var edge of connectedEdges) {
if (
(source.data().id === edge._private.data.source &&
tgt.id === edge._private.data.target) ||
(source.data().id === edge._private.data.target &&
tgt.id === edge._private.data.source)
) {
for (var descriptorItem of edge._private.data.descriptor) {
if (
source.data().id === descriptorItem.Source &&
tgt.id === descriptorItem.Target
) {
return [descriptorItem, edge._private.data.id];
}
}
}
}
}
getConnectedNodeDetails(sourceNode, connectedNodes, connectedEdges) { getConnectedNodeDetails(cyNode, connectedNodes, connectedEdges) {
var sidebarNodeslist = []; var sidebarNodeslist = [];
for (var el of connectedNodes) { for (var el of connectedNodes) {
if (sourceNode.data() !== el._private.data) { if (cyNode.data() !== el.data()) {
sidebarNodeslist.push(el._private.data); sidebarNodeslist.push(el.data());
} }
} }
var nodeContent = ( var nodeContent = (
<CollapsibleButton <CollapsibleButton
id={sourceNode.data().label + "Btn"} id={cyNode.data().label + "Btn"}
className="detailsNodeBtn" className="detailsNodeBtn"
key={sourceNode.data().label + "Btn"} key={cyNode.data().label + "Btn"}
name={sourceNode.data().label} name={cyNode.data().label}
> >
<div> <div>
<h5>{sourceNode.data().label}</h5> <h5>{cyNode.data().label}</h5>
<div id="DetailsLabel">Node ID</div> <div id="DetailsLabel">Node ID</div>
<label id="valueLabel">{sourceNode.data().id}</label> <label id="valueLabel">{cyNode.data().id}</label>
<div className="DetailsLabel">State</div> <div className="DetailsLabel">State</div>
<label id="valueLabel">{sourceNode.data().state}</label> <label id="valueLabel">{cyNode.data().state}</label>
<div className="DetailsLabel">Location</div> <div className="DetailsLabel">Location</div>
<label id="valueLabel">{"Unknown"}</label> <label id="valueLabel">{cyNode.data().location}</label>
<hr style={{ backgroundColor: "#486186" }} /> <hr style={{ backgroundColor: "#486186" }} />
<div id="connectedNode" style={{ overflow: "auto" }}> <div id="connectedNode" style={{ overflow: "auto" }}>
{sidebarNodeslist.map((connectedNode) => { {sidebarNodeslist.map((connectedNode) => {
try { try {
let [connectedlinkDetail, tunnelId] = let [connectedlinkDetail, tunnelId] =
this.getConnectedLinkDetails( this.getConnectedLinkDetails(
sourceNode, cyNode,
connectedNode, connectedNode,
connectedEdges connectedEdges
); );
@ -239,7 +368,7 @@ class TopologyView extends React.Component {
return connectedNodeBtn; return connectedNodeBtn;
} catch (e) { } catch (e) {
//console.log(e) console.log(e);
return false; return false;
} }
})} })}
@ -250,24 +379,24 @@ class TopologyView extends React.Component {
return nodeContent; return nodeContent;
} }
getNotConnectedNodeDetails(notConnectedNode) { getNotConnectedNodeDetails(cyNode) {
var nodeContent = ( var nodeContent = (
//No tunnels node //No tunnels node
<CollapsibleButton <CollapsibleButton
id={notConnectedNode.data().id + "Btn"} id={cyNode.data().id + "Btn"}
className="detailsNodeBtn" className="detailsNodeBtn"
key={notConnectedNode.data().id + "Btn"} key={cyNode.data().id + "Btn"}
name={notConnectedNode.data().label} name={cyNode.data().label}
isOpen isOpen
> >
<div> <div>
<h5>{notConnectedNode.data().label}</h5> <h5>{cyNode.data().label}</h5>
<div className="DetailsLabel">Node ID</div> <div className="DetailsLabel">Node ID</div>
<label id="valueLabel">{notConnectedNode.data().id}</label> <label id="valueLabel">{cyNode.data().id}</label>
<div className="DetailsLabel">State</div> <div className="DetailsLabel">State</div>
<label id="valueLabel">{notConnectedNode.data().state}</label> <label id="valueLabel">{cyNode.data().state}</label>
<div className="DetailsLabel">Location</div> <div className="DetailsLabel">Location</div>
<label id="valueLabel">{"Unknown"}</label> <label id="valueLabel">{cyNode.data().location}</label>
<hr style={{ backgroundColor: "#486186" }} /> <hr style={{ backgroundColor: "#486186" }} />
</div> </div>
</CollapsibleButton> </CollapsibleButton>
@ -275,52 +404,72 @@ class TopologyView extends React.Component {
return nodeContent; return nodeContent;
} }
renderNodeDetails = () => { renderNodeDetails = (cyNode, adj) => {
var selectedEle = JSON.parse(this.props.selectedCyElementData); var connectedNodes = adj.nodes();
var selectedNode = this.cy.getElementById(selectedEle.id); var connectedEdges = adj.edges();
var partitionElements = this.partitionElements(selectedNode);
var nodeDetails = null; var nodeDetails = null;
var connectedNodes = partitionElements.neighborhood.filter((ele) => this.queryGeoCoordinates(cyNode.data("coords"))
ele.isNode() .then((loc) => {
); cyNode.data("location", loc);
var connectedEdges = partitionElements.neighborhood.filter((ele) => if (cyNode.data("state") === nodeStates.notReporting) {
ele.isEdge() nodeDetails = this.getNotReportingNodeDetails(cyNode);
); } else if (cyNode.data("state") === nodeStates.connected) {
if (selectedEle.state === nodeStates.notReporting) { nodeDetails = this.getConnectedNodeDetails(
nodeDetails = this.getNotReportingNodeDetails(selectedNode); //Not reporting nodes cyNode,
} else if (selectedEle.state === nodeStates.connected) { connectedNodes,
nodeDetails = this.getConnectedNodeDetails( connectedEdges
selectedNode, );
connectedNodes, } else if (cyNode.data("state") === nodeStates.noTunnels) {
connectedEdges nodeDetails = this.getNotConnectedNodeDetails(cyNode);
); //Connected nodes }
} else if (selectedEle.state === nodeStates.noTunnels) { ReactDOM.render(
nodeDetails = this.getNotConnectedNodeDetails(selectedNode); //Not connected node <div>
} <div> Node Details </div>
return ( <div> {nodeDetails} </div>
<div> </div>,
<div> Node Details </div> document.getElementById("sideBarContent")
<div> {nodeDetails} </div> );
</div> })
); .catch((err) => {
console.warn(err);
});
}; };
getSourceAndTargetDetails(selectedTunnel) { getConnectedLinkDetails(source, tgt, connectedEdges) {
for (var edge of connectedEdges) {
if (
(source.data().id === edge.data("source") &&
tgt.id === edge.data("target")) ||
(source.data().id === edge.data.target &&
tgt.id === edge.data("source"))
) {
for (var descriptorItem of edge.data("descriptor")) {
if (
source.data().id === descriptorItem.Source &&
tgt.id === descriptorItem.Target
) {
return [descriptorItem, edge.data("id")];
}
}
}
}
}
getSourceAndTargetDetails(cyEdge) {
var sourceNodeLinkDetails; var sourceNodeLinkDetails;
var targetNodeLinkDetails; var targetNodeLinkDetails;
var srcNode; var srcNode;
var tgtNode; var tgtNode;
var selectedTunnel = cyEdge.data();
for (var descriptor of selectedTunnel.descriptor) { for (var descriptor of selectedTunnel.descriptor) {
if ( if (
descriptor.Source === selectedTunnel.source && descriptor.Source === selectedTunnel.source &&
descriptor.Target === selectedTunnel.target descriptor.Target === selectedTunnel.target
) { ) {
sourceNodeLinkDetails = descriptor; sourceNodeLinkDetails = descriptor;
srcNode = this.cy.getElementById(sourceNodeLinkDetails.Source)._private srcNode = this.cy.getElementById(sourceNodeLinkDetails.Source).data();
.data;
if (selectedTunnel.descriptor.length === 1) { if (selectedTunnel.descriptor.length === 1) {
tgtNode = this.cy.getElementById(sourceNodeLinkDetails.Target) tgtNode = this.cy.getElementById(sourceNodeLinkDetails.Target).data();
._private.data;
} }
} else if ( } else if (
descriptor.Target === selectedTunnel.source && descriptor.Target === selectedTunnel.source &&
@ -341,10 +490,6 @@ class TopologyView extends React.Component {
} }
} }
handleSwitch = () => {
this.setState({ isSwapToggle: !this.state.isSwapToggle });
};
getTunnelWithBothReportingNodes(selectedTunnel) { getTunnelWithBothReportingNodes(selectedTunnel) {
var LocalEndpointInternal; var LocalEndpointInternal;
var [sourceNodeLinkDetails, srcNode, tgtNode] = var [sourceNodeLinkDetails, srcNode, tgtNode] =
@ -584,252 +729,75 @@ class TopologyView extends React.Component {
return linkContentNR; return linkContentNR;
} }
renderTunnelDetails = () => { renderTunnelDetails = (cyEdge) => {
var tunnelDetails;
var selectedTunnelNodesDetails = []; var selectedTunnelNodesDetails = [];
var selectedEle = JSON.parse(this.props.selectedCyElementData); try {
var selectedTunnel = this.cy.getElementById(selectedEle.id); var partitionElements = this.partitionElements(cyEdge);
var partitionElements = this.partitionElements(selectedTunnel); for (var node of partitionElements.neighborhood) {
for (var node of partitionElements.neighborhood) { if (node._private.group === "nodes") {
if (node._private.group === "nodes") { selectedTunnelNodesDetails.push(node.data());
selectedTunnelNodesDetails.push(node._private.data); }
} }
} if (
if ( selectedTunnelNodesDetails[0].state === nodeStates.connected &&
selectedTunnelNodesDetails[0].state === nodeStates.connected && selectedTunnelNodesDetails[1].state === nodeStates.connected
selectedTunnelNodesDetails[1].state === nodeStates.connected ) {
) { tunnelDetails = this.getTunnelWithBothReportingNodes(cyEdge);
return this.getTunnelWithBothReportingNodes(selectedEle); } else if (
} else if ( (selectedTunnelNodesDetails[0].state === nodeStates.connected &&
(selectedTunnelNodesDetails[0].state === nodeStates.connected && selectedTunnelNodesDetails[1].state === nodeStates.notReporting) ||
selectedTunnelNodesDetails[1].state === nodeStates.notReporting) || (selectedTunnelNodesDetails[0].state === nodeStates.notReporting &&
(selectedTunnelNodesDetails[0].state === nodeStates.notReporting && selectedTunnelNodesDetails[1].state === nodeStates.connected)
selectedTunnelNodesDetails[1].state === nodeStates.connected) ) {
) { tunnelDetails = this.getTunnelWithEitherOneReportingNodes(cyEdge);
return this.getTunnelWithEitherOneReportingNodes(selectedEle); } else if (
} else if ( selectedTunnelNodesDetails[0].state === nodeStates.notReporting &&
selectedTunnelNodesDetails[0].state === nodeStates.notReporting && selectedTunnelNodesDetails[1].state === nodeStates.notReporting
selectedTunnelNodesDetails[1].state === nodeStates.notReporting ) {
) { tunnelDetails = this.getTunnelWithNoReportingNodes();
return this.getTunnelWithNoReportingNodes(); }
ReactDOM.render(
<div>
<div> Tunnel Details </div>
<div> {tunnelDetails} </div>
</div>,
document.getElementById("sideBarContent")
);
} catch (err) {
console.warn(err);
} }
}; };
renderSidebarDetails() { handleSwitch = () => {
try { this.setState({ isSwapToggle: !this.state.isSwapToggle });
if (this.props.selectedElementType === elementTypes.eleNode) };
return this.renderNodeDetails();
else if (this.props.selectedElementType === elementTypes.eleTunnel)
return this.renderTunnelDetails();
return <null />;
} catch (e) {
return <null />; //when selected tunnel broken on refresh then returns null
}
}
renderTopologyContent() {
const topologyContent = (
<Cytoscape
id="cy"
cy={(cy) => {
this.cy = cy;
this.cy
.layout({
name: "circle",
clockwise: true,
animate: true,
animationDuration: 400,
})
.run();
this.cy.on("click", this.handleCytoClick.bind(this));
this.cy.maxZoom(this.props.zoomMax);
this.cy.minZoom(this.props.zoomMin);
this.cy.zoom(this.props.zoomValue); // has to be set after the other operations or it gets reset
//this.cy.center();
}}
wheelSensitivity={0.1}
elements={JSON.parse(JSON.stringify(this.props.cyElements))} //props.cyElements are frozen
stylesheet={cytoscapeStyle}
style={{ width: window.innerWidth, height: window.innerHeight }}
/>
);
return topologyContent;
}
handleWheel(e) { handleWheel(e) {
this.props.setZoomValue(this.cy.zoom()); this.props.setZoomValue(this.cy.zoom());
} }
buildCyElements = (topologies) => {
var elements = [];
var nodeDetails = {};
if (topologies.length < 1) return elements;
var topology = topologies[0];
for (var nid in topology.Nodes) {
var node = topology.Nodes[nid];
var nodeData = {
group: "nodes",
data: {
id: node.NodeId,
},
};
if (node.hasOwnProperty("NodeName"))
nodeData["data"]["label"] = node.NodeName;
else nodeData["data"]["label"] = node.NodeId.slice(0, 12);
if (node.hasOwnProperty("Version"))
nodeData["data"]["version"] = node.Version;
if (node.hasOwnProperty("GeoCoordinates"))
nodeData["data"]["coords"] = node.GeoCoordinates;
if (node.hasOwnProperty("Edges")) {
nodeData["data"]["edges"] = node.Edges;
if (node.Edges.length === 0) {
nodeData["data"]["state"] = nodeStates.noTunnels;
nodeData["data"]["color"] = "#F2BE22";
} else {
nodeData["data"]["state"] = nodeStates.connected;
nodeData["data"]["color"] = "#8AA626";
}
} else {
nodeData["data"]["state"] = nodeStates.notReporting;
nodeData["data"]["color"] = "#ADD8E6";
}
nodeDetails[node.NodeId] = nodeData;
}
for (var edgeId in topology.Edges) {
var edge = topology.Edges[edgeId];
if (edge["Descriptor"].length > 2) {
console.error(
"Too many edge descriptors reported ",
JSON.stringify(edge["Descriptor"])
);
}
var edgeData = {
group: "edges",
data: {},
};
edgeData["data"]["id"] = edge.EdgeId;
edgeData["data"]["descriptor"] = edge["Descriptor"];
edgeData["data"]["label"] = edge.EdgeId.slice(0, 12);
edgeData["data"]["source"] = edge["Descriptor"][0].Source;
edgeData["data"]["target"] = edge["Descriptor"][0].Target;
edgeData["data"]["color"] = this.getLinkColor(edge["Descriptor"][0].Type);
edgeData["data"]["style"] = this.getLinkStyle(
edge["Descriptor"][0].State
);
if (
edge["Descriptor"].length === 2 &&
edge["Descriptor"][0].Source > edge["Descriptor"][1].Source
) {
edgeData["data"]["source"] = edge["Descriptor"][1].Source;
edgeData["data"]["target"] = edge["Descriptor"][1].Target;
edgeData["data"]["color"] = this.getLinkColor(
edge["Descriptor"][1].Type
);
edgeData["data"]["style"] = this.getLinkStyle(
edge["Descriptor"][1].State
);
}
elements.push(edgeData);
}
var nodes = Object.keys(nodeDetails).sort();
nodes.forEach((nodeId) => elements.push(nodeDetails[nodeId]));
return elements;
};
getLinkColor(type) {
var linkColor;
switch (type) {
case "CETypeILongDistance":
linkColor = "#5E4FA2";
break;
case "CETypeLongDistance":
linkColor = "#5E4FA2";
break;
case "CETypePredecessor":
linkColor = "#01665E";
break;
case "CETypeSuccessor":
linkColor = "#01665E";
break;
default:
break;
}
return linkColor;
}
getLinkStyle(state) {
var linkStyle;
switch (state) {
case "CEStateInitialized":
case "CEStatePreAuth":
case "CEStateAuthorized":
case "CEStateCreated":
linkStyle = "dotted";
break;
case "CEStateConnected":
linkStyle = "solid";
break;
case "CEStateDisconnected":
case "CEStateDeleting":
linkStyle = "dashed";
break;
default:
break;
}
return linkStyle;
}
partitionElements(selectedElement) {
var neighborhood;
var excluded;
if (selectedElement.isNode()) {
this.props.setSelectedElement({
selectedElementType: elementTypes.eleNode,
selectedCyElementData: selectedElement.data(),
});
neighborhood = selectedElement
.outgoers()
.union(selectedElement.incomers())
.union(selectedElement);
excluded = this.cy
.elements()
.difference(
selectedElement.outgoers().union(selectedElement.incomers())
)
.not(selectedElement);
} else if (selectedElement.isEdge()) {
this.props.setSelectedElement({
selectedElementType: elementTypes.eleTunnel,
selectedCyElementData: selectedElement.data(),
});
neighborhood = selectedElement.connectedNodes().union(selectedElement);
excluded = this.cy
.elements()
.difference(selectedElement.connectedNodes())
.not(selectedElement);
}
return { neighborhood, excluded };
}
handleCytoClick(event) { handleCytoClick(event) {
var selectedElement = event.target[0]; var cyEle = event.target[0];
var part;
try { try {
if (event.target === this.cy) { if (event.target === this.cy) {
this.props.clearSelectedElement(); //this.props.clearSelectedElement();
this.cy.elements().removeClass("transparent"); this.cy.elements().removeClass("transparent");
this._typeahead.clear(); this._typeahead.clear();
} else { return;
part = this.partitionElements(selectedElement); }
part.neighborhood.removeClass("transparent"); var part = this.partitionElements(cyEle);
part.excluded.addClass("transparent"); part.neighborhood.removeClass("transparent");
part.excluded.addClass("transparent");
if (cyEle.isNode()) {
this.renderNodeDetails(cyEle, cyEle.neighborhood());
} else if (cyEle.isEdge()) {
this.renderTunnelDetails(cyEle, part.neighborhood);
} }
} catch (error) { } catch (error) {
this.props.clearSelectedElement(); //this.props.clearSelectedElement();
this.cy.elements().removeClass("transparent"); this.cy.elements().removeClass("transparent");
console.warn(error);
} }
} }
@ -865,10 +833,40 @@ class TopologyView extends React.Component {
componentWillUnmount() { componentWillUnmount() {
this.autoRefresh = false; this.autoRefresh = false;
clearTimeout(this.timeoutId); clearTimeout(this.timeoutId);
this.props.clearSelectedElement(); //this.props.clearSelectedElement();
this.props.setCyElements([]); this.props.setCyElements([]);
} }
renderTopologyContent() {
const topologyContent = (
<Cytoscape
id="cy"
cy={(cy) => {
this.cy = cy;
this.cy
.layout({
name: "circle",
clockwise: true,
animate: true,
animationDuration: 400,
})
.run();
this.cy.on("click", this.handleCytoClick.bind(this));
this.cy.maxZoom(this.props.zoomMax);
this.cy.minZoom(this.props.zoomMin);
this.cy.zoom(this.props.zoomValue); // has to be set after the other operations or it gets reset
//this.cy.center();
}}
wheelSensitivity={0.1}
elements={JSON.parse(JSON.stringify(this.props.cyElements))} //props.cyElements are frozen
stylesheet={cytoscapeStyle}
style={{ width: window.innerWidth, height: window.innerHeight }}
/>
);
return topologyContent;
}
render() { render() {
return ( return (
<> <>
@ -879,13 +877,7 @@ class TopologyView extends React.Component {
<div id="cyArea">{this.renderTopologyContent()}</div> <div id="cyArea">{this.renderTopologyContent()}</div>
</section> </section>
<div id="SidePanel"> <div id="SidePanel">
<SideBar <SideBar typeahead={this.renderTypeahead()} />
typeahead={this.renderTypeahead()}
sidebarDetails={this.renderSidebarDetails()}
/>
{/* <div id="bottomTools">
<Toolbar />
</div> */}
</div> </div>
</> </>
); );
@ -894,8 +886,8 @@ class TopologyView extends React.Component {
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
currentOverlayId: state.evio.selectedOverlayId, currentOverlayId: state.evio.selectedOverlayId,
selectedElementType: state.evio.selectedElementType, //selectedElementType: state.evio.selectedElementType,
selectedCyElementData: state.evio.selectedCyElementData, //selectedCyElementData: state.evio.selectedCyElementData,
cyElements: state.evio.cyElements, cyElements: state.evio.cyElements,
currentView: state.view.current, currentView: state.view.current,
selectedView: state.view.selected, selectedView: state.view.selected,
@ -910,8 +902,8 @@ const mapDispatchToProps = {
setCurrentView, setCurrentView,
setZoomValue, setZoomValue,
setCyElements, setCyElements,
setSelectedElement, //setSelectedElement,
clearSelectedElement, //clearSelectedElement,
setRedrawGraph, setRedrawGraph,
}; };