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,13 +123,9 @@ 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={
this.state.overlays !== null this.state.overlays !== null
@ -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;
} }
handleCytoClick(event) { partitionElements(selectedElement) {
var selectedElement = event.target[0]; var neighborhood;
var adjacentElements; var excluded;
var nonAdjacentElements; if (selectedElement.isNode()) {
try {
if (event.target === this.cy) {
this.props.clearSelectedElement();
this.cy.elements().removeClass("transparent");
} else if (selectedElement.isNode()) {
this.props.setSelectedElement({ this.props.setSelectedElement({
selectedElementType: elementTypes.eleNode, selectedElementType: elementTypes.eleNode,
selectedCyElementData: selectedElement.data(), selectedCyElementData: selectedElement.data(),
}); });
adjacentElements = selectedElement neighborhood = selectedElement
.outgoers() .outgoers()
.union(selectedElement.incomers()) .union(selectedElement.incomers())
.union(selectedElement); .union(selectedElement);
nonAdjacentElements = this.cy excluded = this.cy
.elements() .elements()
.difference( .difference(
selectedElement.outgoers().union(selectedElement.incomers()) selectedElement.outgoers().union(selectedElement.incomers())
) )
.not(selectedElement); .not(selectedElement);
adjacentElements.removeClass("transparent");
nonAdjacentElements.addClass("transparent");
} else if (selectedElement.isEdge()) { } else if (selectedElement.isEdge()) {
this.props.setSelectedElement({ this.props.setSelectedElement({
selectedElementType: elementTypes.eleTunnel, selectedElementType: elementTypes.eleTunnel,
selectedCyElementData: selectedElement.data(), selectedCyElementData: selectedElement.data(),
}); });
adjacentElements = selectedElement neighborhood = selectedElement
.connectedNodes() .connectedNodes()
.union(selectedElement); .union(selectedElement);
nonAdjacentElements = this.cy excluded = this.cy
.elements() .elements()
.difference(selectedElement.connectedNodes()) .difference(selectedElement.connectedNodes())
.not(selectedElement); .not(selectedElement);
adjacentElements.removeClass("transparent"); }
nonAdjacentElements.addClass("transparent"); return { neighborhood, excluded };
}
handleCytoClick(event) {
var selectedElement = event.target[0];
var part;
try {
if (event.target === this.cy) {
this.props.clearSelectedElement();
this.cy.elements().removeClass("transparent");
this._typeahead.clear();
} else {
part = this.partitionElements(selectedElement);
part.neighborhood.removeClass("transparent");
part.excluded.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) {