Skip to content
Snippets Groups Projects
Commit 20fd778e authored by Marc Feger's avatar Marc Feger
Browse files

Add first stable version

parent 11644b6e
Branches
Tags
No related merge requests found
......@@ -2191,6 +2191,302 @@
"integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
"dev": true
},
"d3": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/d3/-/d3-5.9.2.tgz",
"integrity": "sha512-ydrPot6Lm3nTWH+gJ/Cxf3FcwuvesYQ5uk+j/kXEH/xbuYWYWTMAHTJQkyeuG8Y5WM5RSEYB41EctUrXQQytRQ==",
"dev": true,
"requires": {
"d3-array": "1",
"d3-axis": "1",
"d3-brush": "1",
"d3-chord": "1",
"d3-collection": "1",
"d3-color": "1",
"d3-contour": "1",
"d3-dispatch": "1",
"d3-drag": "1",
"d3-dsv": "1",
"d3-ease": "1",
"d3-fetch": "1",
"d3-force": "1",
"d3-format": "1",
"d3-geo": "1",
"d3-hierarchy": "1",
"d3-interpolate": "1",
"d3-path": "1",
"d3-polygon": "1",
"d3-quadtree": "1",
"d3-random": "1",
"d3-scale": "2",
"d3-scale-chromatic": "1",
"d3-selection": "1",
"d3-shape": "1",
"d3-time": "1",
"d3-time-format": "2",
"d3-timer": "1",
"d3-transition": "1",
"d3-voronoi": "1",
"d3-zoom": "1"
}
},
"d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==",
"dev": true
},
"d3-axis": {
"version": "1.0.12",
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz",
"integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==",
"dev": true
},
"d3-brush": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.6.tgz",
"integrity": "sha512-lGSiF5SoSqO5/mYGD5FAeGKKS62JdA1EV7HPrU2b5rTX4qEJJtpjaGLJngjnkewQy7UnGstnFd3168wpf5z76w==",
"dev": true,
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
}
},
"d3-chord": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz",
"integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==",
"dev": true,
"requires": {
"d3-array": "1",
"d3-path": "1"
}
},
"d3-collection": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
"integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==",
"dev": true
},
"d3-color": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.2.3.tgz",
"integrity": "sha512-x37qq3ChOTLd26hnps36lexMRhNXEtVxZ4B25rL0DVdDsGQIJGB18S7y9XDwlDD6MD/ZBzITCf4JjGMM10TZkw==",
"dev": true
},
"d3-contour": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz",
"integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==",
"dev": true,
"requires": {
"d3-array": "^1.1.1"
}
},
"d3-dispatch": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.5.tgz",
"integrity": "sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g==",
"dev": true
},
"d3-drag": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.3.tgz",
"integrity": "sha512-8S3HWCAg+ilzjJsNtWW1Mutl74Nmzhb9yU6igspilaJzeZVFktmY6oO9xOh5TDk+BM2KrNFjttZNoJJmDnkjkg==",
"dev": true,
"requires": {
"d3-dispatch": "1",
"d3-selection": "1"
}
},
"d3-dsv": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.1.1.tgz",
"integrity": "sha512-1EH1oRGSkeDUlDRbhsFytAXU6cAmXFzc52YUe6MRlPClmWb85MP1J5x+YJRzya4ynZWnbELdSAvATFW/MbxaXw==",
"dev": true,
"requires": {
"commander": "2",
"iconv-lite": "0.4",
"rw": "1"
}
},
"d3-ease": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.5.tgz",
"integrity": "sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ==",
"dev": true
},
"d3-fetch": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.2.tgz",
"integrity": "sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==",
"dev": true,
"requires": {
"d3-dsv": "1"
}
},
"d3-force": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
"integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==",
"dev": true,
"requires": {
"d3-collection": "1",
"d3-dispatch": "1",
"d3-quadtree": "1",
"d3-timer": "1"
}
},
"d3-format": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.3.2.tgz",
"integrity": "sha512-Z18Dprj96ExragQ0DeGi+SYPQ7pPfRMtUXtsg/ChVIKNBCzjO8XYJvRTC1usblx52lqge56V5ect+frYTQc8WQ==",
"dev": true
},
"d3-geo": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.11.3.tgz",
"integrity": "sha512-n30yN9qSKREvV2fxcrhmHUdXP9TNH7ZZj3C/qnaoU0cVf/Ea85+yT7HY7i8ySPwkwjCNYtmKqQFTvLFngfkItQ==",
"dev": true,
"requires": {
"d3-array": "1"
}
},
"d3-hierarchy": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.8.tgz",
"integrity": "sha512-L+GHMSZNwTpiq4rt9GEsNcpLa4M96lXMR8M/nMG9p5hBE0jy6C+3hWtyZMenPQdwla249iJy7Nx0uKt3n+u9+w==",
"dev": true
},
"d3-interpolate": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.3.2.tgz",
"integrity": "sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==",
"dev": true,
"requires": {
"d3-color": "1"
}
},
"d3-path": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.7.tgz",
"integrity": "sha512-q0cW1RpvA5c5ma2rch62mX8AYaiLX0+bdaSM2wxSU9tXjU4DNvkx9qiUvjkuWCj3p22UO/hlPivujqMiR9PDzA==",
"dev": true
},
"d3-polygon": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.5.tgz",
"integrity": "sha512-RHhh1ZUJZfhgoqzWWuRhzQJvO7LavchhitSTHGu9oj6uuLFzYZVeBzaWTQ2qSO6bz2w55RMoOCf0MsLCDB6e0w==",
"dev": true
},
"d3-quadtree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.6.tgz",
"integrity": "sha512-NUgeo9G+ENQCQ1LsRr2qJg3MQ4DJvxcDNCiohdJGHt5gRhBW6orIB5m5FJ9kK3HNL8g9F4ERVoBzcEwQBfXWVA==",
"dev": true
},
"d3-random": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz",
"integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==",
"dev": true
},
"d3-scale": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz",
"integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==",
"dev": true,
"requires": {
"d3-array": "^1.2.0",
"d3-collection": "1",
"d3-format": "1",
"d3-interpolate": "1",
"d3-time": "1",
"d3-time-format": "2"
}
},
"d3-scale-chromatic": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.3.3.tgz",
"integrity": "sha512-BWTipif1CimXcYfT02LKjAyItX5gKiwxuPRgr4xM58JwlLocWbjPLI7aMEjkcoOQXMkYsmNsvv3d2yl/OKuHHw==",
"dev": true,
"requires": {
"d3-color": "1",
"d3-interpolate": "1"
}
},
"d3-selection": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.0.tgz",
"integrity": "sha512-EYVwBxQGEjLCKF2pJ4+yrErskDnz5v403qvAid96cNdCMr8rmCYfY5RGzWz24mdIbxmDf6/4EAH+K9xperD5jg==",
"dev": true
},
"d3-shape": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.5.tgz",
"integrity": "sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==",
"dev": true,
"requires": {
"d3-path": "1"
}
},
"d3-time": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.11.tgz",
"integrity": "sha512-Z3wpvhPLW4vEScGeIMUckDW7+3hWKOQfAWg/U7PlWBnQmeKQ00gCUsTtWSYulrKNA7ta8hJ+xXc6MHrMuITwEw==",
"dev": true
},
"d3-time-format": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.3.tgz",
"integrity": "sha512-6k0a2rZryzGm5Ihx+aFMuO1GgelgIz+7HhB4PH4OEndD5q2zGn1mDfRdNrulspOfR6JXkb2sThhDK41CSK85QA==",
"dev": true,
"requires": {
"d3-time": "1"
}
},
"d3-timer": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.9.tgz",
"integrity": "sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg==",
"dev": true
},
"d3-transition": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.2.0.tgz",
"integrity": "sha512-VJ7cmX/FPIPJYuaL2r1o1EMHLttvoIuZhhuAlRoOxDzogV8iQS6jYulDm3xEU3TqL80IZIhI551/ebmCMrkvhw==",
"dev": true,
"requires": {
"d3-color": "1",
"d3-dispatch": "1",
"d3-ease": "1",
"d3-interpolate": "1",
"d3-selection": "^1.1.0",
"d3-timer": "1"
}
},
"d3-voronoi": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz",
"integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==",
"dev": true
},
"d3-zoom": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.3.tgz",
"integrity": "sha512-xEBSwFx5Z9T3/VrwDkMt+mr0HCzv7XjpGURJ8lWmIC8wxe32L39eWHIasEe/e7Ox8MPU4p1hvH8PKN2olLzIBg==",
"dev": true,
"requires": {
"d3-dispatch": "1",
"d3-drag": "1",
"d3-interpolate": "1",
"d3-selection": "1",
"d3-transition": "1"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
......@@ -6520,6 +6816,12 @@
"aproba": "^1.1.1"
}
},
"rw": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
"integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=",
"dev": true
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
......
......@@ -14,6 +14,7 @@
"@babel/preset-env": "^7.4.5",
"babel-loader": "^8.0.6",
"css-loader": "^2.1.1",
"d3": "^5.9.2",
"file-loader": "^3.0.1",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
......
import {Graph} from "./js/graph/graph";
import {Edge} from "./js/graph/edge";
import {Node} from "./js/graph/node";
import {Neo4JAdapter} from "./js/neo4j/neo"
import {Visualizer} from './js/visualizer/visualizer'
var graph = new Graph();
var neo = new Neo4JAdapter('neo4j', 'W7uFSy$ywR3M3ck');
graph = neo.getGraph();
console.log(graph);
\ No newline at end of file
new Visualizer().plotGraph('match (a:Issue{id:4})<-[r*..]-(b) return *');
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Foo</title>
</head>
<body>
</body>
</html>
\ No newline at end of file
<meta charset="utf-8">
<style>
body {
font-family: "Inconsolata";
}
circle {
fill: aquamarine;
}
line {
stroke: blueviolet;
}
</style>
<svg width="960" height="600"></svg>
\ No newline at end of file
export class Edge {
constructor(id, properties, type, start, end) {
this.id = id;
this.properties = properties;
this.type = type;
this.start = start;
this.end = end;
}
}
\ No newline at end of file
import {Edge} from './edge'
export class Graph {
constructor(){
this.edges = {};
this.nodes = {};
}
addEdge(edge) {
if (!(edge.id in this.edges)) {
this.edges[edge.id] = edge;
console.log("Added: " + JSON.stringify(edge) + " to edges.");
this.nodes = new Array();
this.edges = new Array();
}
};
addNode(node) {
if (!(node.id in this.nodes)) {
this.nodes[node.id] = node;
console.log("Added: " + JSON.stringify(node) + " to nodes.");
}
};
_asList(dict) {
var list = [];
for (var key in dict) {
if (dict.hasOwnProperty(key)) {
list.push(dict[key]);
}
}
return list;
addNode(newNode){
this.nodes.push(newNode);
this.nodes = this.getUnique(this.nodes, "id");
}
get edgesAsList() {
return this._asList(this.edges);
addEdge(newEdge){
this.edges.push(newEdge);
}
get nodesAsList() {
return this._asList(this.nodes);
getUnique(arr, comp) {
const unique = arr
.map(e => e[comp])
// store the keys of the unique objects
.map((e, i, final) => final.indexOf(e) === i && i)
// eliminate the dead keys & store unique objects
.filter(e => arr[e]).map(e => arr[e]);
return unique;
}
}
\ No newline at end of file
import {Neo4JAdapter} from '../neo4j/neo'
import {v1 as neo4j} from 'neo4j-driver'
export class GraphCreator{
async fill(graph, withQuery){
const queryResult = await new Neo4JAdapter('neo4j', 'W7uFSy$ywR3M3ck').ask(withQuery);
var records = queryResult.records;
records.forEach(function (record) {
record.forEach(function (element) {
if (element instanceof neo4j.types.Node) {
var id = element.identity.toInt();
var newNode = {"id": id};
graph.addNode(newNode);
} else if (element instanceof neo4j.types.Relationship) {
var newEdge = {"source": element.start.toInt(), "target": element.end.toInt()};
graph.addEdge(newEdge);
} else if (element instanceof Array) {
element.forEach(function (relation) {
var newEdge = {"source": relation.start.toInt(), "target": relation.end.toInt()};
graph.addEdge(newEdge);
})
}
});
});
return graph;
}
}
\ No newline at end of file
export class Node {
constructor(id, properties, labels) {
this.id = id;
this.properties = properties;
this.labels = labels
}
}
\ No newline at end of file
import {v1 as neo4j} from 'neo4j-driver'
import {Edge} from '../graph/edge'
import {Node} from '../graph/node'
import {Graph} from '../graph/graph'
export class Neo4JAdapter {
constructor(username, password) {
......@@ -10,33 +7,12 @@ export class Neo4JAdapter {
this.authToken = neo4j.auth.basic(this.username, this.password);
}
getGraph(graph) {
const driver = neo4j.driver('bolt://localhost:7687', this.authToken, {
encrypted: false
});
async ask(query){
const driver = neo4j.driver('bolt://localhost:7687', this.authToken);
const session = driver.session();
const resultPromise = session.run(
'match (a:User)<-[r]-() return *'
);
var graph = new Graph();
resultPromise.then(result => {
const result = await session.run(query);
session.close();
result.records.forEach(function (element) {
element.forEach(function (subelement) {
if (subelement instanceof neo4j.types.Node) {
graph.addNode(new Node(subelement.identity.toInt(), subelement.properties, subelement.labels));
} else if (subelement instanceof neo4j.types.Relationship) {
graph.addEdge(new Edge(subelement.identity.toInt(), subelement.properties, subelement.type, subelement.start.toInt(), subelement.end.toInt()));
}
});
});
driver.close();
});
return graph
return result;
}
}
import * as d3 from 'd3'
import {Neo4JAdapter} from '../neo4j/neo'
import {Graph} from '../graph/graph'
import {GraphCreator} from '../graph/graphCreator'
import {v1 as neo4j} from 'neo4j-driver'
export class Visualizer {
async plotGraph(query) {
const graph = await new GraphCreator().fill(new Graph(), query);
var svg = d3.select("svg");
var width = +svg.attr("width");
var height = +svg.attr("height");
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function (d) {
return d.id;
}))
.force('charge', d3.forceManyBody()
.strength(0)
.theta(1)
.distanceMax(10)
)
.force('collide', d3.forceCollide().radius(d => 40)
.iterations(2)
)
.force("center", d3.forceCenter(width / 2, height / 2));
this.run(svg, simulation, graph);
}
async run(svg, simulation, graph) {
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.2).restart()
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
var link = svg.append("g")
.selectAll("line")
.data(graph.edges)
.enter()
.append("line");
var node = svg.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(graph.nodes)
.enter()
.append("circle")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
var label = svg.append("g")
.attr("class", "labels")
.selectAll("text")
.data(graph.nodes)
.enter()
.append("text")
.attr("class", "label")
.text(function (d) {
return d.id;
});
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.edges);
function ticked() {
link
.attr("x1", function (d) {
return d.source.x;
})
.attr("y1", function (d) {
return d.source.y;
})
.attr("x2", function (d) {
return d.target.x;
})
.attr("y2", function (d) {
return d.target.y;
});
node
.attr("r", 10)
.style("stroke", "#424242")
.style("stroke-width", "2px")
.attr("cx", function (d) {
return d.x + 3;
})
.attr("cy", function (d) {
return d.y - 3;
});
label
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y;
})
.style("font-size", "10px").style("fill", "#333");
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment