Graph changes

master
Rohan Vazarkar 2016-08-02 22:38:16 -07:00
parent 67f1da03a3
commit e8cfd8040c
12 changed files with 174 additions and 17 deletions

View File

@ -10,7 +10,7 @@ let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 1440, height: 900, icon:__dirname + '/src/img/favicon.ico'})
mainWindow = new BrowserWindow({width: 1280, height: 800, icon:__dirname + '/src/img/favicon.ico'})
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`)

View File

@ -5,7 +5,7 @@
"main": "main.js",
"scripts": {
"start": "set ENV=development & electron .",
"server": "babel-node server.js",
"dev": "concurrently -k \"babel-node server.js\" \"npm start\"",
"build": "webpack --config webpack.config.production.js && electron-packager . Bloodhound --platform=all --arch=all --overwrite --prune",
"winbuild": "webpack --config webpack.config.production.js && electron-packager . Bloodhound --platform=win32 --arch=all --overwrite --prune"
},
@ -26,6 +26,7 @@
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-0": "^6.5.0",
"concurrently": "^2.2.0",
"electron-prebuilt": "^1.2.8",
"express": "^4.14.0",
"webpack": "^1.13.1",

View File

@ -6,8 +6,8 @@ import LogoutModal from './components/Modals/logoutmodal';
import ClearWarnModal from './components/Modals/clearwarnmodal'
import ClearConfirmModal from './components/Modals/clearconfirmmodal'
import ClearingModal from './components/Modals/clearingmodal'
import LoadingContainer from './components/loadingcontainer';
import GenericAlert from './components/alert';
import LoadingContainer from './components/Float/loadingcontainer';
import GenericAlert from './components/Float/alert';
import RawQuery from './components/rawquery';
import MenuContainer from './components/Menu/menucontainer';
import ExportContainer from './components/Float/exportcontainer';

View File

@ -0,0 +1,11 @@
import React, { Component } from 'react';
export class QueryNodeSelect extends Component {
render() {
return (
<div>
</div>
);
}
}

View File

@ -0,0 +1,14 @@
import React, { Component } from 'react';
export default class QueryNodeSelectItem extends Component {
_handleClick(){
var qstring = 'MATCH (n),(m:Group {name:"{}"}),p=allShortestPaths((n)-[*1..]->(m)) RETURN p'
emitter.emit('query', qstring.format(this.props.text), this.props.text)
}
render() {
return (
<button onClick={this._handleClick.bind(this)} class="list-group-item">{this.props.text}</button>
);
}
}

View File

@ -67,6 +67,31 @@ export default class GraphContainer extends Component {
}
}
loadFromChildProcess(graph){
if (graph.nodes.length === 0){
emitter.emit('showAlert', "No data returned from query")
}else{
$.each(graph.nodes, function(i, node){
node.glyphs = $.map(node.glyphs, function(value, index) {
return [value];
});
})
appStore.queryStack.push({
nodes: this.state.sigmaInstance.graph.nodes(),
edges: this.state.sigmaInstance.graph.edges(),
spotlight: appStore.spotlightData,
startNode: appStore.startNode,
endNode: appStore.endNode
})
appStore.spotlightData = graph.spotlightData;
this.state.sigmaInstance.graph.clear();
this.state.sigmaInstance.graph.read(graph);
this.state.sigmaInstance.refresh()
emitter.emit('spotlightUpdate');
}
}
import(payload){
fs.readFile(payload, 'utf8', function(err, data){
var graph;
@ -317,11 +342,17 @@ export default class GraphContainer extends Component {
// child.on('message', function(m) {
// // Receive results from child process
// console.log(m)
// });
// this.loadFromChildProcess(m)
// }.bind(this));
// // Send child process some work
// child.send(sigmaInstance);
// child.send(JSON.stringify({nodes:sigmaInstance.graph.nodes(),
// edges: sigmaInstance.graph.edges(),
// edge: params.allowCollapse ? appStore.performance.edge : 0 ,
// sibling: params.allowCollapse ? appStore.performance.sibling : 0,
// start: appStore.startNode,
// end: appStore.endNode
// }))
}.bind(this))
if (this.state.firstDraw){
setTimeout(function(){
@ -427,7 +458,8 @@ export default class GraphContainer extends Component {
glyphFillColor: 'black',
glyphTextColor: 'white',
glyphTextThreshold: 1,
zoomingRatio: 1.4
zoomingRatio: 1.4,
scalingMode: 'inside'
}
)
@ -560,7 +592,8 @@ export default class GraphContainer extends Component {
var dagreListener = sigma.layouts.dagre.configure(sigmaInstance, {
easing: 'cubicInOut',
boundingBox: true,
background: true
background: true,
rankDir: 'LR'
});
dagreListener.bind('stop', function(event){
@ -573,12 +606,16 @@ export default class GraphContainer extends Component {
emitter.emit('showLoadingIndicator', true)
})
var noverlapListener = sigmaInstance.configNoverlap({
nodeMargin: 20.0,
easing: 'cubicInOut',
gridSize: 20,
permittedExpansion: 1.3
});
// var noverlapListener = sigmaInstance.configNoverlap({
// nodeMargin: 5.0,
// easing: 'cubicInOut',
// gridSize: 20,
// permittedExpansion: 1.3
// });
//
var noverlapListener = sigmaInstance.configNoverlap({})
noverlapListener.bind('stop', function(event) {
emitter.emit('updateLoadingText', 'Done!');
setTimeout(function(){

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Login from '../login'
import Login from '../Float/login'
var Modal = require('react-bootstrap').Modal;

View File

@ -3,7 +3,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import AppContainer from './appcontainer';
import Login from './components/login'
import Login from './components/Float/login'
import { getStorageData, storageHasKey, storageSetKey } from './js/utils.js';
const ConfigStore = require('configstore');

94
src/js/worker.js Normal file
View File

@ -0,0 +1,94 @@
var indexes,
edge,
sibling,
spotlightData,
adjacentNodes,
adjacentEdges,
idMap;
process.on('message', function(m){
adjacentNodes = {}
adjacentEdges = {}
idMap = {}
spotlightData = {}
var data = JSON.parse(m)
buildIndexes(data)
edge = data.edge;
sibling = data.sibling
data = processEdgeNodes(data)
data.spotlightData = spotlightData
data.nodes.forEach(function(node){
if (!spotlightData.hasOwnProperty(node.id)){
spotlightData[node.id] = [node.neo4j_data.name, 0, ""]
}
})
process.send(data)
})
function buildIndexes(graph){
graph.nodes.forEach(function(node){
idMap[node.id] = node
adjacentNodes[node.id] = []
adjacentEdges[node.id] = []
})
graph.edges.forEach(function(edge){
adjacentNodes[edge.target].push(idMap[edge.source])
adjacentNodes[edge.source].push(idMap[edge.target])
adjacentEdges[edge.source].push(edge)
adjacentEdges[edge.target].push(edge)
})
}
function processEdgeNodes(graph){
if (edge === 0){
return graph;
}
Object.keys(idMap).forEach(function(id){
var node = idMap[id]
adjacentNodes[node.id].forEach(function(anode){
if (anode.neo4j_data.name === graph.endNode || anode.neo4j_data.name === graph.startNode){
return
}
var edges = adjacentEdges[anode.id]
if ((edges.length > 1 || edges.length === 0) || (anode.folded.nodes.length > 0)){
return;
}
var edge = edges[0]
if ((anode.type_user && (edge.label === 'MemberOf' || edge.label === 'AdminTo'))
|| (anode.type_computer && (edge.label === 'AdminTo' || edge.label === 'MemberOf'))
|| (anode.type_group && edge.label === 'AdminTo')){
node.isGrouped = true
node.folded.nodes.push(anode)
node.folded.edges.push(edge)
spotlightData[anode.id] = [anode.neo4j_data.name, node.id, node.neo4j_data.name];
graph.nodes = graph.nodes.filter(function(index) {
return index.id !== anode.id
});
graph.edges = graph.edges.filter(function(index) {
return index.id !== edge.id
});
}
})
if (node.folded.nodes.length > 0){
node.glyphs.push({
'position': 'bottom-left',
'content': node.folded.nodes.length
})
}
})
return graph
}