├── .babelrc ├── src ├── node_modules │ ├── index.js │ └── Neo4jGraphRenderer │ │ ├── package.json │ │ ├── Neo4jGraphRenderer.js │ │ ├── assets │ │ ├── graph.js │ │ ├── connection.js │ │ ├── renderer.js │ │ └── util.js │ │ └── Neo4jGraphRenderer.css ├── index.js └── registerServiceWorker.js ├── public ├── favicon.ico ├── manifest.json └── index.html ├── lib ├── Neo4jGraphRenderer │ ├── package.json │ ├── assets │ │ ├── graph.js │ │ ├── connection.js │ │ ├── renderer.js │ │ └── util.js │ ├── Neo4jGraphRenderer.css │ └── Neo4jGraphRenderer.js └── index.js ├── config ├── jest │ ├── fileTransform.js │ └── cssTransform.js ├── polyfills.js ├── paths.js ├── env.js ├── webpackDevServer.config.js ├── webpack.config.dev.js └── webpack.config.prod.js ├── .gitignore ├── scripts ├── test.js ├── start.js └── build.js ├── LICENSE.txt ├── README.md └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react", "stage-2"] 3 | } -------------------------------------------------------------------------------- /src/node_modules/index.js: -------------------------------------------------------------------------------- 1 | export { default as Neo4jGraphRenderer } from './Neo4jGraphRenderer'; -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jbitton/neo4j-graph-renderer/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /lib/Neo4jGraphRenderer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Neo4jGraphRenderer", 3 | "main": "./Neo4jGraphRenderer.js", 4 | "dependencies": { 5 | "d3": "3.5.17", 6 | "jquery": "^3.2.1", 7 | "react": "^15.6.1", 8 | "style-loader": "^0.18.2", 9 | "css-loader": "^0.28.4" 10 | } 11 | } -------------------------------------------------------------------------------- /src/node_modules/Neo4jGraphRenderer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Neo4jGraphRenderer", 3 | "main": "./Neo4jGraphRenderer.js", 4 | "dependencies": { 5 | "d3": "3.5.17", 6 | "jquery": "^3.2.1", 7 | "react": "^15.6.1", 8 | "style-loader": "^0.18.2", 9 | "css-loader": "^0.28.4" 10 | } 11 | } -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | // This is a custom Jest transformer turning file imports into filenames. 6 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 7 | 8 | module.exports = { 9 | process(src, filename) { 10 | return `module.exports = ${JSON.stringify(path.basename(filename))};`; 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | 23 | ../* 24 | /.idea/* -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _Neo4jGraphRenderer = require('./Neo4jGraphRenderer'); 8 | 9 | Object.defineProperty(exports, 'Neo4jGraphRenderer', { 10 | enumerable: true, 11 | get: function get() { 12 | return _interopRequireDefault(_Neo4jGraphRenderer).default; 13 | } 14 | }); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import registerServiceWorker from './registerServiceWorker'; 4 | import Neo4jGraphRenderer from 'Neo4jGraphRenderer'; 5 | 6 | const App = () => ( 7 |
8 | 9 |
10 | ); 11 | 12 | ReactDOM.render(, document.getElementById('root')); 13 | registerServiceWorker(); -------------------------------------------------------------------------------- /src/node_modules/Neo4jGraphRenderer/Neo4jGraphRenderer.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { createGraph } from './assets/graph'; 3 | import './Neo4jGraphRenderer.css'; 4 | 5 | class Neo4JGraphRenderer extends Component { 6 | componentDidMount() { 7 | this.loadData(this.props); 8 | } 9 | 10 | componentWillReceiveProps(newProps) { 11 | this.loadData(newProps); 12 | } 13 | 14 | loadData(props) { 15 | const connection = { url: props.url, user: props.user, pass: props.password }; 16 | createGraph(connection, props.query); 17 | } 18 | 19 | render () { 20 | return
; 21 | } 22 | } 23 | 24 | export default Neo4JGraphRenderer; 25 | -------------------------------------------------------------------------------- /config/polyfills.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | if (typeof Promise === 'undefined') { 4 | // Rejection tracking prevents a common issue where React gets into an 5 | // inconsistent state due to an error, but it gets swallowed by a Promise, 6 | // and the user has no idea what causes React's erratic future behavior. 7 | require('promise/lib/rejection-tracking').enable(); 8 | window.Promise = require('promise/lib/es6-extensions.js'); 9 | } 10 | 11 | // fetch() polyfill for making API calls. 12 | require('whatwg-fetch'); 13 | 14 | // Object.assign() is commonly used with React. 15 | // It will use the native implementation if it's present and isn't buggy. 16 | Object.assign = require('object-assign'); 17 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | const jest = require('jest'); 19 | const argv = process.argv.slice(2); 20 | 21 | // Watch unless on CI or in coverage mode 22 | if (!process.env.CI && argv.indexOf('--coverage') < 0) { 23 | argv.push('--watch'); 24 | } 25 | 26 | 27 | jest.run(argv); 28 | -------------------------------------------------------------------------------- /src/node_modules/Neo4jGraphRenderer/assets/graph.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | import { graphRenderer } from './renderer'; 3 | import { neo4jConnection } from './connection'; 4 | 5 | const createGraph = (urlSource, query) => { 6 | const d3Graph = graphRenderer(); 7 | const connection = neo4jConnection(urlSource); 8 | try { 9 | connection.executeQuery(query, {}, (err,res) => { 10 | res = res || {}; 11 | const { graph } = res; 12 | if (graph) { 13 | let div = $("#graph"); 14 | div.empty(); 15 | d3Graph.render("graph", div, graph); 16 | } else { 17 | if (err) { 18 | window.alert(err.length > 0 19 | ? `Cypher error:\n${err}` 20 | : `JS Error:\n${err}`); 21 | } 22 | } 23 | }); 24 | } catch(e) { 25 | window.alert(`Caught error: ${e}`); 26 | } 27 | }; 28 | 29 | export { createGraph }; 30 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Joanna Bitton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/Neo4jGraphRenderer/assets/graph.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.createGraph = undefined; 7 | 8 | var _jquery = require('jquery'); 9 | 10 | var _jquery2 = _interopRequireDefault(_jquery); 11 | 12 | var _renderer = require('./renderer'); 13 | 14 | var _connection = require('./connection'); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17 | 18 | var createGraph = function createGraph(urlSource, query) { 19 | var d3Graph = (0, _renderer.graphRenderer)(); 20 | var connection = (0, _connection.neo4jConnection)(urlSource); 21 | try { 22 | connection.executeQuery(query, {}, function (err, res) { 23 | res = res || {}; 24 | var _res = res, 25 | graph = _res.graph; 26 | 27 | if (graph) { 28 | var div = (0, _jquery2.default)("#graph"); 29 | div.empty(); 30 | d3Graph.render("graph", div, graph); 31 | } else { 32 | if (err) { 33 | window.alert(err.length > 0 ? 'Cypher error:\n' + err : 'JS Error:\n' + err); 34 | } 35 | } 36 | }); 37 | } catch (e) { 38 | window.alert('Caught error: ' + e); 39 | } 40 | }; 41 | 42 | exports.createGraph = createGraph; -------------------------------------------------------------------------------- /lib/Neo4jGraphRenderer/Neo4jGraphRenderer.css: -------------------------------------------------------------------------------- 1 | path.link { 2 | fill:none; 3 | stroke:#7f8c8d; 4 | stroke-width:2px; 5 | } 6 | 7 | text { 8 | pointer-events:none; 9 | } 10 | 11 | marker { 12 | fill:#d8dadc; 13 | } 14 | 15 | .node .outline { 16 | -webkit-transform:scale(1); 17 | -moz-transform:scale(1); 18 | -o-transform:scale(1); 19 | -ms-transform:scale(1); 20 | transform:scale(1); 21 | -webkit-transition:all .15s; 22 | -moz-transition:all .15s; 23 | -o-transition:all .15s; 24 | -ms-transition:all .15s; 25 | transition:all .15s; 26 | -webkit-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 27 | -moz-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 28 | -o-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 29 | -ms-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 30 | transition-timing-function:cubic-bezier(.694,.0482,.335,1) 31 | } 32 | 33 | .node:hover .outline { 34 | -webkit-transform:scale(1.4); 35 | -moz-transform:scale(1.4); 36 | -o-transform:scale(1.4); 37 | -ms-transform:scale(1.4); 38 | transform:scale(1.4) 39 | } 40 | 41 | .relationship:hover { 42 | stroke:#3498db 43 | } 44 | 45 | .outline,.overlay { 46 | cursor:pointer 47 | } 48 | 49 | svg { 50 | width:100%; 51 | height: 100vh; 52 | } -------------------------------------------------------------------------------- /src/node_modules/Neo4jGraphRenderer/Neo4jGraphRenderer.css: -------------------------------------------------------------------------------- 1 | path.link { 2 | fill:none; 3 | stroke:#7f8c8d; 4 | stroke-width:2px; 5 | } 6 | 7 | text { 8 | pointer-events:none; 9 | } 10 | 11 | marker { 12 | fill:#d8dadc; 13 | } 14 | 15 | .node .outline { 16 | -webkit-transform:scale(1); 17 | -moz-transform:scale(1); 18 | -o-transform:scale(1); 19 | -ms-transform:scale(1); 20 | transform:scale(1); 21 | -webkit-transition:all .15s; 22 | -moz-transition:all .15s; 23 | -o-transition:all .15s; 24 | -ms-transition:all .15s; 25 | transition:all .15s; 26 | -webkit-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 27 | -moz-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 28 | -o-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 29 | -ms-transition-timing-function:cubic-bezier(.694,.0482,.335,1); 30 | transition-timing-function:cubic-bezier(.694,.0482,.335,1) 31 | } 32 | 33 | .node:hover .outline { 34 | -webkit-transform:scale(1.4); 35 | -moz-transform:scale(1.4); 36 | -o-transform:scale(1.4); 37 | -ms-transform:scale(1.4); 38 | transform:scale(1.4) 39 | } 40 | 41 | .relationship:hover { 42 | stroke:#3498db 43 | } 44 | 45 | .outline,.overlay { 46 | cursor:pointer 47 | } 48 | 49 | svg { 50 | width:100%; 51 | height: 100vh; 52 | } -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 22 | React App 23 | 24 | 25 | 28 |
29 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # neo4j-graph-renderer 2 | 3 | Since neo4j does not provide a way to render its graphs, I've created a react component that can be used in order to render a neo4j graph (with all the animations, etc). 4 | 5 | ## Installation 6 | 7 | If you are using `create-react-app`: 8 | ```bash 9 | # using NPM 10 | $ npm install neo4j-graph-renderer --save 11 | # using yarn 12 | $ yarn add neo4j-graph-renderer 13 | ``` 14 | 15 | If you are not using `create-react-app`, please install the following: 16 | ```bash 17 | $ npm install style-loader --save-dev # style-loader for webpack 18 | $ npm install css-loader --save-dev # css-loader for webpack 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```javascript 24 | // Using ES6 Syntax 25 | import React from 'react'; 26 | import ReactDOM from 'react-dom'; 27 | import { Neo4jGraphRenderer } from 'neo4j-graph-renderer'; 28 | 29 | const App = () => ( 30 |
31 | 33 |
34 | ); 35 | 36 | ReactDOM.render(, document.getElementById('root')); 37 | ``` 38 | 39 | Props you must provide: 40 | * ```url```: the url required to access your neo4j db (e.g. "http://localhost:7474") 41 | * ```user```: the username required to access your neo4j db 42 | * ```password```: the password required to access your neo4j db 43 | * ```query```: the query you'd like to execute 44 | 45 | & There you go! Your neo4j graph has been rendered! 46 | 47 | **NOTE**: If you would like to add any extra CSS or your own font, the graph is generated in a ```div``` with id "graph" 48 | 49 | ## Issues 50 | 51 | If you find a bug, please file an issue on the [issue tracker](https://github.com/jbitton/neo4j-graph-renderer/issues) on GitHub. 52 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebookincubator/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(path, needsSlash) { 15 | const hasSlash = path.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return path.substr(path, path.length - 1); 18 | } else if (!hasSlash && needsSlash) { 19 | return `${path}/`; 20 | } else { 21 | return path; 22 | } 23 | } 24 | 25 | const getPublicUrl = appPackageJson => 26 | envPublicUrl || require(appPackageJson).homepage; 27 | 28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 29 | // "public path" at which the app is served. 30 | // Webpack needs to know it to put the right