UNPKG

popoto

Version:

Graph based search interface for Neo4j database.

313 lines (266 loc) 11.1 kB
import * as d3 from "d3"; import dataModel from "../datamodel/dataModel"; import cypherviewer from "../cypherviewer/cypherviewer"; import provider from "../provider/provider"; import graph from "../graph/graph"; var queryviewer = {}; queryviewer.containerId = "popoto-query"; queryviewer.QUERY_STARTER = "I'm looking for"; queryviewer.CHOOSE_LABEL = "choose"; /** * Create the query viewer area. * */ queryviewer.createQueryArea = function () { var id = "#" + queryviewer.containerId; queryviewer.queryConstraintSpanElements = d3.select(id).append("p").attr("class", "ppt-query-constraint-elements").selectAll(".queryConstraintSpan"); queryviewer.querySpanElements = d3.select(id).append("p").attr("class", "ppt-query-elements").selectAll(".querySpan"); }; /** * Update all the elements displayed on the query viewer based on current graph. */ queryviewer.updateQuery = function () { // Remove all query span elements queryviewer.queryConstraintSpanElements = queryviewer.queryConstraintSpanElements.data([]); queryviewer.querySpanElements = queryviewer.querySpanElements.data([]); queryviewer.queryConstraintSpanElements.exit().remove(); queryviewer.querySpanElements.exit().remove(); // Update data queryviewer.queryConstraintSpanElements = queryviewer.queryConstraintSpanElements.data(queryviewer.generateConstraintData(dataModel.links, dataModel.nodes)); queryviewer.querySpanElements = queryviewer.querySpanElements.data(queryviewer.generateData(dataModel.links, dataModel.nodes)); // Remove old span (not needed as all have been cleaned before) // queryviewer.querySpanElements.exit().remove(); // Add new span queryviewer.queryConstraintSpanElements = queryviewer.queryConstraintSpanElements.enter().append("span") .on("contextmenu", queryviewer.rightClickSpan) .on("click", queryviewer.clickSpan) .on("mouseover", queryviewer.mouseOverSpan) .on("mouseout", queryviewer.mouseOutSpan) .merge(queryviewer.queryConstraintSpanElements); queryviewer.querySpanElements = queryviewer.querySpanElements.enter().append("span") .on("contextmenu", queryviewer.rightClickSpan) .on("click", queryviewer.clickSpan) .on("mouseover", queryviewer.mouseOverSpan) .on("mouseout", queryviewer.mouseOutSpan) .merge(queryviewer.querySpanElements); // Update all span queryviewer.queryConstraintSpanElements .attr("id", function (d) { return d.id }) .attr("class", function (d) { if (d.isLink) { return "ppt-span-link"; } else { if (d.type === graph.node.NodeTypes.ROOT) { return "ppt-span-root"; } else if (d.type === graph.node.NodeTypes.CHOOSE) { if (d.ref.value !== undefined && d.ref.value.length > 0) { return "ppt-span-value"; } else { return "ppt-span-choose"; } } else if (d.type === graph.node.NodeTypes.VALUE) { return "ppt-span-value"; } else if (d.type === graph.node.NodeTypes.GROUP) { return "ppt-span-group"; } else { return "ppt-span"; } } }) .text(function (d) { return d.term + " "; }); queryviewer.querySpanElements .attr("id", function (d) { return d.id }) .attr("class", function (d) { if (d.isLink) { return "ppt-span-link"; } else { if (d.type === graph.node.NodeTypes.ROOT) { return "ppt-span-root"; } else if (d.type === graph.node.NodeTypes.CHOOSE) { if (d.ref.value !== undefined && d.ref.value.length > 0) { return "ppt-span-value"; } else { return "ppt-span-choose"; } } else if (d.type === graph.node.NodeTypes.VALUE) { return "ppt-span-value"; } else if (d.type === graph.node.NodeTypes.GROUP) { return "ppt-span-group"; } else { return "ppt-span"; } } }) .text(function (d) { return d.term + " "; }); }; queryviewer.generateConstraintData = function (links, nodes) { var elmts = [], id = 0; // Add query starter elmts.push( {id: id++, term: queryviewer.QUERY_STARTER} ); // Add the root node as query term if (nodes.length > 0) { elmts.push( {id: id++, type: nodes[0].type, term: provider.node.getSemanticValue(nodes[0]), ref: nodes[0]} ); } // Add a span for each link and its target node links.forEach(function (l) { var sourceNode = l.source; var targetNode = l.target; if (l.type === graph.link.LinkTypes.RELATION && targetNode.type !== graph.node.NodeTypes.GROUP && targetNode.value !== undefined && targetNode.value.length > 0) { if (sourceNode.type === graph.node.NodeTypes.GROUP) { elmts.push( { id: id++, type: sourceNode.type, term: provider.node.getSemanticValue(sourceNode), ref: sourceNode } ); } elmts.push({id: id++, isLink: true, term: provider.link.getSemanticValue(l), ref: l}); if (targetNode.type !== graph.node.NodeTypes.GROUP) { if (targetNode.value !== undefined && targetNode.value.length > 0) { elmts.push( { id: id++, type: targetNode.type, term: provider.node.getSemanticValue(targetNode), ref: targetNode } ); } else { elmts.push( { id: id++, type: targetNode.type, term: "<" + queryviewer.CHOOSE_LABEL + " " + provider.node.getSemanticValue(targetNode) + ">", ref: targetNode } ); } } } }); return elmts; }; // TODO add option nodes in generated query when no value is available queryviewer.generateData = function (links, nodes) { var elmts = [], options = [], id = 0; // Add a span for each link and its target node links.forEach(function (l) { var sourceNode = l.source; var targetNode = l.target; if (targetNode.type === graph.node.NodeTypes.GROUP) { options.push( { id: id++, type: targetNode.type, term: provider.node.getSemanticValue(targetNode), ref: targetNode } ); } if (l.type === graph.link.LinkTypes.RELATION && targetNode.type !== graph.node.NodeTypes.GROUP && (targetNode.value === undefined || targetNode.value.length === 0)) { if (sourceNode.type === graph.node.NodeTypes.GROUP) { elmts.push( { id: id++, type: sourceNode.type, term: provider.node.getSemanticValue(sourceNode), ref: sourceNode } ); } elmts.push({id: id++, isLink: true, term: provider.link.getSemanticValue(l), ref: l}); if (targetNode.type !== graph.node.NodeTypes.GROUP) { elmts.push( { id: id++, type: targetNode.type, term: "<" + queryviewer.CHOOSE_LABEL + " " + provider.node.getSemanticValue(targetNode) + ">", ref: targetNode } ); } } }); return elmts.concat(options); }; /** * */ queryviewer.mouseOverSpan = function () { d3.select(this).classed("hover", function (d) { return d.ref; }); var hoveredSpan = d3.select(this).data()[0]; if (hoveredSpan.ref) { var linkElmt = graph.svg.selectAll("#" + graph.link.gID + " > g").filter(function (d) { return d === hoveredSpan.ref; }); linkElmt.select("path").classed("ppt-link-hover", true); linkElmt.select("text").classed("ppt-link-hover", true); var nodeElmt = graph.svg.selectAll("#" + graph.node.gID + " > g").filter(function (d) { return d === hoveredSpan.ref; }); nodeElmt.select(".ppt-g-node-background").selectAll("circle").transition().style("fill-opacity", 0.5); if (cypherviewer.isActive) { cypherviewer.querySpanElements.filter(function (d) { return d.node === hoveredSpan.ref || d.link === hoveredSpan.ref; }).classed("hover", true); } } }; queryviewer.rightClickSpan = function () { var clickedSpan = d3.select(this).data()[0]; if (!clickedSpan.isLink && clickedSpan.ref) { var nodeElmt = graph.svg.selectAll("#" + graph.node.gID + " > g").filter(function (d) { return d === clickedSpan.ref; }); nodeElmt.on("contextmenu").call(nodeElmt.node(), clickedSpan.ref); } }; queryviewer.clickSpan = function () { var clickedSpan = d3.select(this).data()[0]; if (!clickedSpan.isLink && clickedSpan.ref) { var nodeElmt = graph.svg.selectAll("#" + graph.node.gID + " > g").filter(function (d) { return d === clickedSpan.ref; }); nodeElmt.on("click").call(nodeElmt.node(), clickedSpan.ref); } }; /** * */ queryviewer.mouseOutSpan = function () { d3.select(this).classed("hover", false); var hoveredSpan = d3.select(this).data()[0]; if (hoveredSpan.ref) { var linkElmt = graph.svg.selectAll("#" + graph.link.gID + " > g").filter(function (d) { return d === hoveredSpan.ref; }); linkElmt.select("path").classed("ppt-link-hover", false); linkElmt.select("text").classed("ppt-link-hover", false); var nodeElmt = graph.svg.selectAll("#" + graph.node.gID + " > g").filter(function (d) { return d === hoveredSpan.ref; }); nodeElmt.select(".ppt-g-node-background").selectAll("circle").transition().style("fill-opacity", 0); if (cypherviewer.isActive) { cypherviewer.querySpanElements.filter(function (d) { return d.node === hoveredSpan.ref || d.link === hoveredSpan.ref; }).classed("hover", false); } } }; export default queryviewer