From ca3077abd82f1e41aeb2c90c3317c1b9d1876fe3 Mon Sep 17 00:00:00 2001 From: Dennis-Gireesh Date: Tue, 20 Jul 2021 18:58:46 -0400 Subject: [PATCH 1/4] Custom Collapsible Button Component --- src/app/CustomCollapsibleButton.js | 54 ++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/app/CustomCollapsibleButton.js diff --git a/src/app/CustomCollapsibleButton.js b/src/app/CustomCollapsibleButton.js new file mode 100644 index 0000000..e66278f --- /dev/null +++ b/src/app/CustomCollapsibleButton.js @@ -0,0 +1,54 @@ +import React from "react"; +import DownArrow from "../images/icons/down-arrow-ic.svg"; +import UpArrow from "../images/icons/up-arrow-ic.svg"; +import { connect } from "react-redux"; + +class CustomCollapsibleButton extends React.Component { + constructor(props) { + super(props); + this.state = { + open: false, + }; + if(this.props.hasOwnProperty("expanded")){ + this.state.open = this.props.expanded; + } + this.togglePanel = this.togglePanel.bind(this); + } + componentDidUpdate() {} + + componentDidMount() {} + + componentWillUnmount() {} + + togglePanel(e) { + this.setState({ open: !this.state.open }); + } + render() { + return ( + <> +
+
+
this.togglePanel(e)} className="collapse-header"> +
+
{this.props.title}
+
+ {this.state.open ? ( + up-arrow + ) : ( + down-arrow + )} +
+
+
+ {this.state.open ? ( +
+ {this.props.description} + {this.props.children} +
+ ) : null} +
+ + ); + } +} +export default CustomCollapsibleButton; From ec1b140af932949c49ea0328e66d5d365e81de48 Mon Sep 17 00:00:00 2001 From: Dennis-Gireesh Date: Tue, 20 Jul 2021 18:59:14 -0400 Subject: [PATCH 2/4] minor fixes --- src/app/CollapsibleButton.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/CollapsibleButton.js b/src/app/CollapsibleButton.js index 6e041ab..5f4fd71 100644 --- a/src/app/CollapsibleButton.js +++ b/src/app/CollapsibleButton.js @@ -3,7 +3,7 @@ import Card from "react-bootstrap/Card"; import "bootstrap/dist/css/bootstrap.min.css"; import Accordion from "react-bootstrap/Accordion"; import Button from "react-bootstrap/Button"; -import DowmArrow from "../images/icons/down-arrow-ic.svg"; +import DownArrow from "../images/icons/down-arrow-ic.svg"; import UpArrow from "../images/icons/up-arrow-ic.svg"; import { connect } from "react-redux"; @@ -11,7 +11,7 @@ class CollapsibleButton extends React.Component { constructor(props) { super(props); this.isToggle = false; - this.accordionStyle = this.props.isOpen ? "block" : "none" + this.accordionStyle = this.props.isOpen ? "block" : "none"; } componentDidUpdate(prevProps, prevState) { if (this.props.selectedOverlayId !== prevProps.selectedOverlayId) { @@ -28,7 +28,7 @@ class CollapsibleButton extends React.Component { handleOnClick(){ this.isToggle = !this.isToggle; this.accordionStyle = this.isToggle ? "block" : "none"; - }; + } render() { return ( @@ -53,9 +53,9 @@ class CollapsibleButton extends React.Component {
{this.props.isToggle ? ( up-arrow - ) : ( - down-arrow - )} + ) : ( + down-arrow + )}
From 2b1c37f439690254b81de1d3ec1d02fa488640ea Mon Sep 17 00:00:00 2001 From: Dennis-Gireesh Date: Tue, 20 Jul 2021 19:00:15 -0400 Subject: [PATCH 3/4] updated Sidebar details with custom collapseible button and Location details fix --- src/app/TopologyView.js | 340 ++++++++++++++++------------------------ 1 file changed, 136 insertions(+), 204 deletions(-) diff --git a/src/app/TopologyView.js b/src/app/TopologyView.js index f3c114a..eb7bcf7 100644 --- a/src/app/TopologyView.js +++ b/src/app/TopologyView.js @@ -1,19 +1,13 @@ import React from "react"; import ReactDOM from "react-dom"; -//import cytoscape from "cytoscape"; import Cytoscape from "react-cytoscapejs"; -//import CytoscapeComponent from "react-cytoscapejs"; -import CollapsibleButton from "./CollapsibleButton"; +import CollapseButton from "./CustomCollapsibleButton"; import cytoscapeStyle from "./cytoscapeStyle.js"; import { Typeahead } from "react-bootstrap-typeahead"; -//import { Spinner } from "react-bootstrap"; import SideBar from "./Sidebar"; import { connect } from "react-redux"; import { setCyElements } from "../features/evio/evioSlice"; import { - //setSelectedElement, - //clearSelectedElement, - //elementTypes, setRedrawGraph, } from "../features/evio/evioSlice"; import { setCurrentView } from "../features/view/viewSlice"; @@ -28,9 +22,7 @@ const nodeStates = { class TopologyView extends React.Component { constructor(props) { super(props); - this.state = { - isSwapToggle: false, - }; + this.isSwapToggle = false; this.intervalId = null; this.timeoutId = null; this.autoRefresh = this.props.autoUpdate; @@ -211,8 +203,6 @@ class TopologyView extends React.Component { .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 @@ -233,7 +223,6 @@ class TopologyView extends React.Component { var data = await res.json(); var nodeLocation = data.results[data.results.length - 1].formatted_address; - console.log("formatted_address", nodeLocation); return nodeLocation.slice(7, nodeLocation.length); } catch (err) { return "Unknown"; @@ -277,26 +266,20 @@ class TopologyView extends React.Component { ); } - getNotReportingNodeDetails(notReportingNode) { + getNotReportingNodeDetails(cyNode) { var nodeContent = ( - +
-
{notReportingNode.data().label}
+
{cyNode.data().label}
Node ID
- +
State
- +
Location
- +
-
+ ); return nodeContent; } @@ -309,72 +292,63 @@ class TopologyView extends React.Component { } } var nodeContent = ( - -
-
{cyNode.data().label}
-
Node ID
- -
State
- -
Location
- -
-
- {sidebarNodeslist.map((connectedNode) => { - try { - let [connectedlinkDetail, tunnelId] = - this.getConnectedLinkDetails( - cyNode, - connectedNode, - connectedEdges - ); - var connectedNodeBtn = ( - -
Node ID
- -
Tunnel ID
- -
Interface Name
- -
MAC
- -
State
- -
Tunnel Type
- -
- ); - - return connectedNodeBtn; - } catch (e) { - console.log(e); - return false; - } - })} + +
Node ID
+ +
State
+ +
Location
+ +
+
-
-
+ } + > + {sidebarNodeslist.map((connectedNode) => { + try { + var [connectedlinkDetail, tunnelId] = this.getConnectedLinkDetails( + cyNode, + connectedNode, + connectedEdges + ); + var connectedNodeBtn = ( + +
Node ID
+ +
Tunnel ID
+ +
Interface Name
+ +
MAC
+ +
State
+ +
Tunnel Type
+ +
+ ); + return connectedNodeBtn; + } catch (e) { + console.log(e); + return false; + } + })} +
+ ); return nodeContent; } @@ -382,13 +356,7 @@ class TopologyView extends React.Component { getNotConnectedNodeDetails(cyNode) { var nodeContent = ( //No tunnels node - +
{cyNode.data().label}
Node ID
@@ -399,7 +367,7 @@ class TopologyView extends React.Component {
-
+ ); return nodeContent; } @@ -408,6 +376,27 @@ class TopologyView extends React.Component { var connectedNodes = adj.nodes(); var connectedEdges = adj.edges(); var nodeDetails = null; + if(cyNode.data().hasOwnProperty("location")){ + if (cyNode.data("state") === nodeStates.notReporting) { + nodeDetails = this.getNotReportingNodeDetails(cyNode); + } else if (cyNode.data("state") === nodeStates.connected) { + nodeDetails = this.getConnectedNodeDetails( + cyNode, + connectedNodes, + connectedEdges + ); + } else if (cyNode.data("state") === nodeStates.noTunnels) { + nodeDetails = this.getNotConnectedNodeDetails(cyNode); + } + ReactDOM.render( +
+
Node Details
+
{nodeDetails}
+
, + document.getElementById("sideBarContent") + ); + } + else{ this.queryGeoCoordinates(cyNode.data("coords")) .then((loc) => { cyNode.data("location", loc); @@ -433,22 +422,23 @@ class TopologyView extends React.Component { .catch((err) => { console.warn(err); }); + } }; 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")) + (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.data("descriptor")) { + for (var descriptorItem of edge._private.data.descriptor) { if ( source.data().id === descriptorItem.Source && tgt.id === descriptorItem.Target ) { - return [descriptorItem, edge.data("id")]; + return [descriptorItem, edge._private.data.id]; } } } @@ -480,7 +470,7 @@ class TopologyView extends React.Component { .data; } } - if (this.state.isSwapToggle === false) { + if (this.isSwapToggle === false) { return [sourceNodeLinkDetails, srcNode, tgtNode]; } else { //if swapbutton toggled then swap source and node details @@ -490,7 +480,7 @@ class TopologyView extends React.Component { } } - getTunnelWithBothReportingNodes(selectedTunnel) { + getTunnelWithBothReportingNodes(selectedTunnel, adj) { var LocalEndpointInternal; var [sourceNodeLinkDetails, srcNode, tgtNode] = this.getSourceAndTargetDetails(selectedTunnel); @@ -501,69 +491,42 @@ class TopologyView extends React.Component { } var linkContent = ( - +
-
{sourceNodeLinkDetails.TapName}
-
Node ID
State
Location
- {/* */} - -
+ + -
Node ID
State
Location
- {/* */} - -
+ +
-

Tunnel ID
- +
Interface Name
MAC
@@ -597,12 +560,12 @@ class TopologyView extends React.Component { {sourceNodeLinkDetails.RemoteEndpoint.External}
-
+ ); return linkContent; } - getTunnelWithEitherOneReportingNodes(selectedTunnel) { + getTunnelWithEitherOneReportingNodes(selectedTunnel, adj) { var LocalEndpointInternal; var [sourceNodeLinkDetails, srcNode, tgtNode] = this.getSourceAndTargetDetails(selectedTunnel); @@ -612,69 +575,44 @@ class TopologyView extends React.Component { LocalEndpointInternal = sourceNodeLinkDetails.LocalEndpoint.Internal; } var linkContent = ( -
-
{sourceNodeLinkDetails.TapName}
-
Node ID
State
Location
- {/* */} - -
+ + - +
Node ID
State
Location
- {/* */} - -
+ +
-

Tunnel ID
- +
Interface Name
MAC
@@ -708,33 +646,30 @@ class TopologyView extends React.Component { {sourceNodeLinkDetails.RemoteEndpoint.External}
-
+ ); return linkContent; } getTunnelWithNoReportingNodes() { var linkContentNR = ( -
-
+ ); return linkContentNR; } - renderTunnelDetails = (cyEdge) => { + renderTunnelDetails = (cyEdge, adj) => { var tunnelDetails; var selectedTunnelNodesDetails = []; try { - var partitionElements = this.partitionElements(cyEdge); - for (var node of partitionElements.neighborhood) { + for (var node of adj) { if (node._private.group === "nodes") { selectedTunnelNodesDetails.push(node.data()); } @@ -743,14 +678,14 @@ class TopologyView extends React.Component { selectedTunnelNodesDetails[0].state === nodeStates.connected && selectedTunnelNodesDetails[1].state === nodeStates.connected ) { - tunnelDetails = this.getTunnelWithBothReportingNodes(cyEdge); + tunnelDetails = this.getTunnelWithBothReportingNodes(cyEdge, adj); } else if ( (selectedTunnelNodesDetails[0].state === nodeStates.connected && selectedTunnelNodesDetails[1].state === nodeStates.notReporting) || (selectedTunnelNodesDetails[0].state === nodeStates.notReporting && selectedTunnelNodesDetails[1].state === nodeStates.connected) ) { - tunnelDetails = this.getTunnelWithEitherOneReportingNodes(cyEdge); + tunnelDetails = this.getTunnelWithEitherOneReportingNodes(cyEdge, adj); } else if ( selectedTunnelNodesDetails[0].state === nodeStates.notReporting && selectedTunnelNodesDetails[1].state === nodeStates.notReporting @@ -769,8 +704,9 @@ class TopologyView extends React.Component { } }; - handleSwitch = () => { - this.setState({ isSwapToggle: !this.state.isSwapToggle }); + handleSwitch = (selectedTunnel, adj) => { + this.isSwapToggle= !this.isSwapToggle; + this.renderTunnelDetails(selectedTunnel, adj); }; handleWheel(e) { @@ -819,7 +755,7 @@ class TopologyView extends React.Component { if (this.props.zoomMax !== prevProps.zoomMax) { this.cy.maxZoom(this.props.zoomMax); } - if (this.props.redrawGraph !== prevState.redrawGraph) { + if (this.props.redrawGraph !== prevProps.redrawGraph) { this.cy.center(); } if (this.props.autoUpdate !== prevProps.autoUpdate) { @@ -886,8 +822,6 @@ class TopologyView extends React.Component { const mapStateToProps = (state) => ({ currentOverlayId: state.evio.selectedOverlayId, - //selectedElementType: state.evio.selectedElementType, - //selectedCyElementData: state.evio.selectedCyElementData, cyElements: state.evio.cyElements, currentView: state.view.current, selectedView: state.view.selected, @@ -902,8 +836,6 @@ const mapDispatchToProps = { setCurrentView, setZoomValue, setCyElements, - //setSelectedElement, - //clearSelectedElement, setRedrawGraph, }; From f7a4cf36a3793fffe0d70f33f747e30c07dc5ac7 Mon Sep 17 00:00:00 2001 From: Dennis-Gireesh Date: Tue, 20 Jul 2021 19:00:43 -0400 Subject: [PATCH 4/4] CSS for Custom Collapsible Button --- src/index.css | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/index.css b/src/index.css index f5a1d26..b9a9346 100644 --- a/src/index.css +++ b/src/index.css @@ -181,6 +181,23 @@ h5 { background-size: contain; } +.collapse-header { + cursor: pointer; + padding: 10px; + color: white; + background: #405b80; + border-radius: 5px; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} +.collapse-content { + padding: 8px; + color: white; + background: transparent; + border-radius: 5px; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, + border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} .overlayBtn, .connectedNodeBtn, .detailsNodeBtn,