Implement typeahead for TopologyView

pull/1/head
ken 2021-07-07 19:19:26 +00:00
parent 190cc81c62
commit 2f370ade97
3 changed files with 74 additions and 61 deletions

View File

@ -123,12 +123,8 @@ class OverlaysView extends React.Component {
<Typeahead <Typeahead
id="searchOverlay" id="searchOverlay"
onChange={(selected) => { onChange={(selected) => {
try { if (selected.length > 0) {
if (selected[0] !== undefined) { this.onTypeheadChange(selected[0]);
this.onTypeheadChange(selected[0]);
}
} catch {
console.warn("Typeahead - No such item exists.");
} }
}} }}
options={ options={
@ -138,7 +134,7 @@ class OverlaysView extends React.Component {
} }
selected={this.state.selected} selected={this.state.selected}
selectHintOnEnter selectHintOnEnter
placeholder="Search overlay" placeholder="Search by overlay ID"
renderMenuItemChildren={(option) => { renderMenuItemChildren={(option) => {
return ( return (
<div className="searchResult"> <div className="searchResult">

View File

@ -30,6 +30,7 @@ class TopologyView extends React.Component {
this.timeoutId = null; this.timeoutId = null;
this.autoRefresh = this.props.autoUpdate; this.autoRefresh = this.props.autoUpdate;
this.cy = null; this.cy = null;
this._typeahead = null;
} }
/** /**
@ -42,7 +43,7 @@ class TopologyView extends React.Component {
var resp = await fetch(url).then((res) => { var resp = await fetch(url).then((res) => {
return res.json(); return res.json();
}); });
//console.log("apiQueryTopology: ", resp); console.log("apiQueryTopology: ", resp);
return resp; return resp;
} }
@ -70,19 +71,20 @@ class TopologyView extends React.Component {
<Typeahead <Typeahead
id="searchTopology" id="searchTopology"
onChange={(selected) => { onChange={(selected) => {
try { if (selected.length > 0) {
console.log("typeahead selected", selected); let selectedEle = this.cy
// this.cy .elements()
// .elements() .getElementById(selected[0].data.id);
// .getElementById(selected[0].data.id) this.cy.elements().unselect();
// .trigger("click"); selectedEle.select();
// this.cy.elements().getElementById(selected[0].data.id).select(); let part = this.partitionElements(selectedEle);
} catch (e) { part.neighborhood.removeClass("transparent");
console.warn(e); part.excluded.addClass("transparent");
} }
}} }}
options={[]} ref={(ref) => (this._typeahead = ref)}
placeholder={"select a node or tunnel"} options={this.props.cyElements}
placeholder={"search by node or tunnel ID"}
labelKey={(option) => { labelKey={(option) => {
return `${option.data.label}`; return `${option.data.label}`;
}} }}
@ -145,11 +147,9 @@ class TopologyView extends React.Component {
}; };
renderSidebarDetails() { renderSidebarDetails() {
if (this.props.selectedElementType === elementTypes.eleNode)
return this.renderNodeDetails();
return <null />; return <null />;
return (
this.props.selectedElementType === elementTypes.eleNode &&
this.renderNodeDetails()
);
} }
renderTopologyContent() { renderTopologyContent() {
@ -193,7 +193,8 @@ class TopologyView extends React.Component {
this.cy.layout({ name: "circle" }).run(); this.cy.layout({ name: "circle" }).run();
this.cy.zoom(this.props.zoomValue); this.cy.zoom(this.props.zoomValue);
this.cy.center(); this.cy.center();
//setting the redrawGraph back to false after the action so that it will be again active for next click event in breadcrumb component //setting the redrawGraph back to false after the action so that
//it will be again active for next click event in breadcrumb component
this.props.setRedrawGraph({ this.props.setRedrawGraph({
redrawGraph: "false", redrawGraph: "false",
}); });
@ -216,8 +217,7 @@ class TopologyView extends React.Component {
}; };
if (node.hasOwnProperty("NodeName")) if (node.hasOwnProperty("NodeName"))
nodeData["data"]["label"] = node.NodeName; nodeData["data"]["label"] = node.NodeName;
else else nodeData["data"]["label"] = node.NodeId.slice(0, 12);
nodeData["data"]["label"] = node.NodeId.slice(0, 12);
if (node.hasOwnProperty("Version")) if (node.hasOwnProperty("Version"))
nodeData["data"]["version"] = node.Version; nodeData["data"]["version"] = node.Version;
if (node.hasOwnProperty("GeoCoordinates")) if (node.hasOwnProperty("GeoCoordinates"))
@ -239,10 +239,18 @@ class TopologyView extends React.Component {
} }
for (var edgeId in topology.Edges) { for (var edgeId in topology.Edges) {
var edge = topology.Edges[edgeId]; var edge = topology.Edges[edgeId];
if (edge["Descriptor"].length > 2) {
console.error(
"Too many edge descriptors reported ",
JSON.stringify(edge["Descriptor"])
);
}
var edgeData = { var edgeData = {
group: "edges", group: "edges",
data: edge, data: {},
}; };
edgeData["data"]["id"] = edge.EdgeId;
edgeData["data"]["descriptor"] = edge["Descriptor"];
edgeData["data"]["label"] = edge.EdgeId.slice(0, 12); edgeData["data"]["label"] = edge.EdgeId.slice(0, 12);
edgeData["data"]["source"] = edge["Descriptor"][0].Source; edgeData["data"]["source"] = edge["Descriptor"][0].Source;
edgeData["data"]["target"] = edge["Descriptor"][0].Target; edgeData["data"]["target"] = edge["Descriptor"][0].Target;
@ -314,45 +322,52 @@ class TopologyView extends React.Component {
return linkStyle; 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 selectedElement = event.target[0];
var adjacentElements; var part;
var nonAdjacentElements;
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");
} else if (selectedElement.isNode()) { this._typeahead.clear();
this.props.setSelectedElement({ } else {
selectedElementType: elementTypes.eleNode, part = this.partitionElements(selectedElement);
selectedCyElementData: selectedElement.data(), part.neighborhood.removeClass("transparent");
}); part.excluded.addClass("transparent");
adjacentElements = selectedElement
.outgoers()
.union(selectedElement.incomers())
.union(selectedElement);
nonAdjacentElements = this.cy
.elements()
.difference(
selectedElement.outgoers().union(selectedElement.incomers())
)
.not(selectedElement);
adjacentElements.removeClass("transparent");
nonAdjacentElements.addClass("transparent");
} else if (selectedElement.isEdge()) {
this.props.setSelectedElement({
selectedElementType: elementTypes.eleTunnel,
selectedCyElementData: selectedElement.data(),
});
adjacentElements = selectedElement
.connectedNodes()
.union(selectedElement);
nonAdjacentElements = this.cy
.elements()
.difference(selectedElement.connectedNodes())
.not(selectedElement);
adjacentElements.removeClass("transparent");
nonAdjacentElements.addClass("transparent");
} }
} catch (error) { } catch (error) {
this.props.clearSelectedElement(); this.props.clearSelectedElement();
@ -414,6 +429,8 @@ class TopologyView extends React.Component {
componentWillUnmount() { componentWillUnmount() {
this.autoRefresh = false; this.autoRefresh = false;
clearTimeout(this.timeoutId); clearTimeout(this.timeoutId);
this.props.clearSelectedElement();
this.props.setCyElements([]);
} }
render() { render() {

View File

@ -29,7 +29,7 @@ const evioSlice = createSlice({
); );
}, },
clearSelectedElement(state) { clearSelectedElement(state) {
state.elementType = elementTypes.eleNone; state.selectedElementType = elementTypes.eleNone;
state.selectedCyElementData = JSON.stringify({}); state.selectedCyElementData = JSON.stringify({});
}, },
setRedrawGraph(state, action) { setRedrawGraph(state, action) {