diff --git a/public/manifest.json b/public/manifest.json index 2d35f21..33bcdcb 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -4,7 +4,7 @@ "icons": [ { "src": "gremlin-visualizer.png", - "sizes": "192x192", + "sizes": "64x64", "type": "image/png" } ], diff --git a/src/components/Details/DetailsComponent.js b/src/components/Details/DetailsComponent.js index 71b8310..6373aff 100644 --- a/src/components/Details/DetailsComponent.js +++ b/src/components/Details/DetailsComponent.js @@ -15,7 +15,9 @@ import { Table, TableBody, TableRow, - TableCell + TableCell, + FormControlLabel, + Switch } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import AddIcon from '@material-ui/icons/Add'; @@ -60,6 +62,18 @@ class Details extends React.Component { }); } + onTogglePhysics(enabled){ + this.props.dispatch({ type: ACTIONS.SET_IS_PHYSICS_ENABLED, payload: enabled }); + if (this.props.network) { + const edges = { + smooth: { + type: enabled ? 'dynamic' : 'continuous' + } + }; + this.props.network.setOptions( { physics: enabled, edges } ); + } + } + generateList(list) { let key = 0; return list.map(value => { @@ -149,10 +163,26 @@ class Details extends React.Component { aria-controls="panel1a-content" id="panel1a-header" > - Node Labels + Settings - + + + { this.onTogglePhysics(!this.props.isPhysicsEnabled); }} + value="physics" + color="primary" + /> + } + label="Enable Physics" + /> + + + Node Labels + {this.generateNodeLabelList(this.props.nodeLabels)} @@ -222,9 +252,11 @@ export const DetailsComponent = connect((state)=>{ return { host: state.gremlin.host, port: state.gremlin.port, + network: state.graph.network, selectedNode: state.graph.selectedNode, selectedEdge: state.graph.selectedEdge, queryHistory: state.options.queryHistory, - nodeLabels: state.options.nodeLabels + nodeLabels: state.options.nodeLabels, + isPhysicsEnabled: state.options.isPhysicsEnabled }; })(Details); \ No newline at end of file diff --git a/src/components/NetworkGraph/NetworkGraphComponent.js b/src/components/NetworkGraph/NetworkGraphComponent.js index 51654d8..1511249 100644 --- a/src/components/NetworkGraph/NetworkGraphComponent.js +++ b/src/components/NetworkGraph/NetworkGraphComponent.js @@ -23,6 +23,8 @@ class NetworkGraph extends React.Component{ this.props.dispatch({ type: ACTIONS.SET_SELECTED_EDGE, payload: edgeId }); } }); + + this.props.dispatch({ type: ACTIONS.SET_NETWORK, payload: network }); } render(){ diff --git a/src/constants.js b/src/constants.js index 4702beb..41f569c 100644 --- a/src/constants.js +++ b/src/constants.js @@ -6,12 +6,13 @@ export const ACTIONS = { SET_PORT: 'SET_PORT', SET_QUERY: 'SET_QUERY', SET_ERROR: 'SET_ERROR', + SET_NETWORK: 'SET_NETWORK', CLEAR_GRAPH: 'CLEAR_GRAPH', - LOAD_GRAPH: 'LOAD_GRAPH', ADD_NODES: 'ADD_NODES', ADD_EDGES: 'ADD_EDGES', SET_SELECTED_NODE: 'SET_SELECTED_NODE', SET_SELECTED_EDGE: 'SET_SELECTED_EDGE', + SET_IS_PHYSICS_ENABLED: 'SET_IS_PHYSICS_ENABLED', ADD_QUERY_HISTORY: 'ADD_QUERY_HISTORY', CLEAR_QUERY_HISTORY: 'CLEAR_QUERY_HISTORY', SET_NODE_LABELS: 'SET_NODE_LABELS', diff --git a/src/logics/utils.js b/src/logics/utils.js index add99ce..7257371 100644 --- a/src/logics/utils.js +++ b/src/logics/utils.js @@ -32,7 +32,7 @@ export const extractEdgesAndNodes = (nodeList, nodeLabels=[]) => { const label = labelField in node.properties ? node.properties[labelField] : type; nodes.push({ id: node.id, label: String(label), group: node.label, properties: node.properties, type }); - edges = edges.concat(_.map(node.edges, edge => ({ ...edge, type: edge.label}))); + edges = edges.concat(_.map(node.edges, edge => ({ ...edge, type: edge.label, arrows: { to: { enabled: true, scaleFactor: 0.5 } } }))); }); return { edges, nodes, nodeLabels } diff --git a/src/reducers/graphReducer.js b/src/reducers/graphReducer.js index cd0744f..9cc6d24 100644 --- a/src/reducers/graphReducer.js +++ b/src/reducers/graphReducer.js @@ -4,6 +4,7 @@ import { ACTIONS } from '../constants'; import { getDiffNodes, getDiffEdges, findNodeById } from '../logics/utils'; const initialState = { + network: null, nodeHolder: new vis.DataSet([]), edgeHolder: new vis.DataSet([]), nodes: [], @@ -20,11 +21,8 @@ export const reducer = (state=initialState, action)=>{ return { ...state, nodes: [], edges: [], selectedNode:{}, selectedEdge: {} }; } - case ACTIONS.LOAD_GRAPH: { - state.nodeHolder.add(state.nodes); - state.edgeHolder.add(state.edges); - - return state; + case ACTIONS.SET_NETWORK: { + return { ...state, network: action.payload }; } case ACTIONS.ADD_NODES: { const newNodes = getDiffNodes(action.payload, state.nodes); diff --git a/src/reducers/optionReducer.js b/src/reducers/optionReducer.js index cadacc2..dff2f37 100644 --- a/src/reducers/optionReducer.js +++ b/src/reducers/optionReducer.js @@ -4,7 +4,31 @@ import { ACTIONS } from '../constants'; const initialState = { nodeLabels: [], queryHistory: [], + isPhysicsEnabled: true, networkOptions: { + physics: { + forceAtlas2Based: { + gravitationalConstant: -26, + centralGravity: 0.005, + springLength: 230, + springConstant: 0.18, + avoidOverlap: 1.5 + }, + maxVelocity: 40, + solver: 'forceAtlas2Based', + timestep: 0.35, + stabilization: { + enabled: true, + iterations: 50, + updateInterval: 25 + } + }, + configure: function(option, path) { + if (path.indexOf("smooth") !== -1 || option === "smooth") { + return true; + } + return false; + }, nodes: { shape: "dot", size: 20, @@ -17,6 +41,9 @@ const initialState = { width: 2, font: { size: 11 + }, + smooth: { + type: 'dynamic' } } } @@ -24,6 +51,10 @@ const initialState = { export const reducer = (state=initialState, action)=>{ switch (action.type){ + case ACTIONS.SET_IS_PHYSICS_ENABLED: { + const isPhysicsEnabled = _.get(action, 'payload', true); + return { ...state, isPhysicsEnabled }; + } case ACTIONS.ADD_QUERY_HISTORY: { return { ...state, queryHistory: [ ...state.queryHistory, action.payload] } }