refactor(elements): simplfy node and edge handling

This commit is contained in:
moklick
2019-07-31 18:01:15 +02:00
parent 3403203adb
commit e348cccc76
14 changed files with 4105 additions and 4157 deletions
+1996 -2014
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -212,7 +212,7 @@ var parent = module.bundle.parent;
if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') { if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {
var hostname = "" || location.hostname; var hostname = "" || location.hostname;
var protocol = location.protocol === 'https:' ? 'wss' : 'ws'; var protocol = location.protocol === 'https:' ? 'wss' : 'ws';
var ws = new WebSocket(protocol + '://' + hostname + ':' + "58449" + '/'); var ws = new WebSocket(protocol + '://' + hostname + ':' + "53462" + '/');
ws.onmessage = function (event) { ws.onmessage = function (event) {
checkedAssets = {}; checkedAssets = {};
+3 -3
View File
@@ -1,6 +1,6 @@
import React from 'react'; import React, { memo } from 'react';
export default (props) => { export default memo((props) => {
const { targetNode, sourceNode } = props; const { targetNode, sourceNode } = props;
const style = props.style || {}; const style = props.style || {};
@@ -26,4 +26,4 @@ export default (props) => {
d={dAttr} d={dAttr}
/> />
); );
}; });
+3 -3
View File
@@ -1,6 +1,6 @@
import React from 'react'; import React, { memo } from 'react';
export default (props) => { export default memo((props) => {
const { targetNode, sourceNode } = props; const { targetNode, sourceNode } = props;
const style = props.style || {}; const style = props.style || {};
@@ -20,4 +20,4 @@ export default (props) => {
d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`} d={`M ${sourceX},${sourceY}L ${targetX},${targetY}`}
/> />
); );
}; });
+1
View File
@@ -21,6 +21,7 @@ function renderEdge(e, props, graphContext) {
return ( return (
<EdgeComponent <EdgeComponent
key={`${e.source}-${e.target}`} key={`${e.source}-${e.target}`}
id={e.id}
type={e.type} type={e.type}
sourceNode={sourceNode} sourceNode={sourceNode}
targetNode={targetNode} targetNode={targetNode}
+12 -10
View File
@@ -1,14 +1,16 @@
import React, { createContext, useEffect, useReducer, useRef } from 'react'; import React, { createContext, useEffect, useReducer } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import isEqual from 'lodash.isequal'; import isEqual from 'lodash.isequal';
import { reducer, initialState } from '../state'; import { reducer, initialState } from '../state';
import { setNodes, setEdges } from '../state/actions'; import { setNodes, setEdges } from '../state/actions';
import { parseElement, isNode, isEdge } from '../graph-utils';
export const GraphContext = createContext({}); export const GraphContext = createContext({});
export const Provider = (props) => { export const Provider = (props) => {
const { const {
elements,
children, children,
onConnect onConnect
} = props; } = props;
@@ -16,7 +18,10 @@ export const Provider = (props) => {
const [state, dispatch] = useReducer(reducer, initialState); const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => { useEffect(() => {
const nextNodes = props.nodes.map(propNode => { const nodes = elements.filter(isNode);
const edges = elements.filter(isEdge).map(parseElement);
const nextNodes = nodes.map(propNode => {
const existingNode = state.nodes.find(n => n.id === propNode.id); const existingNode = state.nodes.find(n => n.id === propNode.id);
if (existingNode) { if (existingNode) {
@@ -29,22 +34,21 @@ export const Provider = (props) => {
}; };
} }
return propNode; return parseElement(propNode);
}); });
const nodesChanged = !isEqual(state.nodes, nextNodes); const nodesChanged = !isEqual(state.nodes, nextNodes);
const edgesChanged = !isEqual(state.edges, props.edges); const edgesChanged = !isEqual(state.edges, edges);
if (nodesChanged) { if (nodesChanged) {
dispatch(setNodes(nextNodes)); dispatch(setNodes(nextNodes));
} }
if (edgesChanged) { if (edgesChanged) {
dispatch(setEdges(props.edges)); dispatch(setEdges(edges));
} }
}); });
const graphContext = { const graphContext = {
state, state,
dispatch, dispatch,
@@ -63,11 +67,9 @@ export const Provider = (props) => {
export const { Consumer } = GraphContext; export const { Consumer } = GraphContext;
Provider.propTypes = { Provider.propTypes = {
nodes: PropTypes.arrayOf(PropTypes.object), elements: PropTypes.arrayOf(PropTypes.object)
edges: PropTypes.arrayOf(PropTypes.object)
}; };
Provider.defaultProps = { Provider.defaultProps = {
nodes: [], elements: [],
edges: []
}; };
+1 -1
View File
@@ -66,7 +66,7 @@ const onNodeClick = (evt, { onClick, dispatch, id, type, position, data }) => {
const node = { id, type, position, data } const node = { id, type, position, data }
dispatch(setSelectedElements(node)); dispatch(setSelectedElements({ id, type }));
onClick(node); onClick(node);
}; };
+1
View File
@@ -25,6 +25,7 @@ function renderNode(d, props, graphContext) {
transform={graphContext.state.transform} transform={graphContext.state.transform}
getNodeById={graphContext.getNodeById} getNodeById={graphContext.getNodeById}
selectedElements={graphContext.state.selectedElements} selectedElements={graphContext.state.selectedElements}
style={d.style}
/> />
); );
} }
+2 -28
View File
@@ -1,12 +1,10 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import isEqual from 'lodash.isequal';
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
const whyDidYouRender = require('@welldone-software/why-did-you-render'); const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React); whyDidYouRender(React);
} }
import { parseElements, isNode, isEdge } from '../graph-utils';
import GraphView from '../GraphView'; import GraphView from '../GraphView';
import GlobalKeyHandler from '../GlobalKeyHandler'; import GlobalKeyHandler from '../GlobalKeyHandler';
import { Provider } from '../GraphContext'; import { Provider } from '../GraphContext';
@@ -28,42 +26,18 @@ class ReactGraph extends PureComponent {
this.nodeTypes = createNodeTypes(props.nodeTypes); this.nodeTypes = createNodeTypes(props.nodeTypes);
this.edgeTypes = createEdgeTypes(props.edgeTypes); this.edgeTypes = createEdgeTypes(props.edgeTypes);
this.state = {
nodes: [],
edges: []
};
}
componentDidMount() {
this.updateElements(this.props.elements);
}
componentDidUpdate(prevProps) {
if (!isEqual(prevProps.elements, this.props.elements)) {
this.updateElements(this.props.elements);
}
}
updateElements(elements) {
const parsedElements = elements.map(parseElements);
this.setState({
nodes: parsedElements.filter(isNode),
edges: parsedElements.filter(isEdge),
});
} }
render() { render() {
const { const {
style, onElementClick, children, onLoad, style, onElementClick, elements, children, onLoad,
onMove, onChange, onElementsRemove, onConnect, onNodeDragStop, onMove, onChange, onElementsRemove, onConnect, onNodeDragStop,
connectionLineType, connectionLineStyle connectionLineType, connectionLineStyle
} = this.props; } = this.props;
return ( return (
<div style={style} className="react-graph"> <div style={style} className="react-graph">
<Provider nodes={this.state.nodes} edges={this.state.edges} onConnect={onConnect}> <Provider elements={elements} onConnect={onConnect}>
<GraphView <GraphView
onLoad={onLoad} onLoad={onLoad}
onMove={onMove} onMove={onMove}
+5 -6
View File
@@ -23,15 +23,13 @@ export const removeElements = (elements, elementsToRemove) => {
}); });
}; };
let internalNodeId = 0; const getEdgeId = (e) => `react-graph__edge-${e.source}-${e.target}`;
const getId = () => internalNodeId++; export const parseElement = (e) => {
export const parseElements = (e) => {
e.type = e.type || 'default'; e.type = e.type || 'default';
e.id = e.id ? e.id : getId();
if (isEdge(e)) { if (isEdge(e)) {
e.id = e.id ? e.id.toString() : getEdgeId(e);
return e; return e;
} }
@@ -132,5 +130,6 @@ export default {
separateElements, separateElements,
getBoundingBox, getBoundingBox,
graphPosToZoomedPos, graphPosToZoomedPos,
getConnectedEdges getConnectedEdges,
parseElement
}; };
+1 -1
View File
@@ -5,7 +5,7 @@ export default ReactGraph;
export { default as SourceHandle } from './NodeRenderer/HandleTypes/SourceHandle'; export { default as SourceHandle } from './NodeRenderer/HandleTypes/SourceHandle';
export { default as TargetHandle } from './NodeRenderer/HandleTypes/TargetHandle'; export { default as TargetHandle } from './NodeRenderer/HandleTypes/TargetHandle';
export { export {
isNode, isNode,
isEdge, isEdge,
removeElements, removeElements,
+5 -1
View File
@@ -1,4 +1,5 @@
import { zoomIdentity } from 'd3-zoom'; import { zoomIdentity } from 'd3-zoom';
import isEqual from 'lodash.isequal';
import { getBoundingBox, getNodesInside, getConnectedEdges } from '../graph-utils'; import { getBoundingBox, getNodesInside, getConnectedEdges } from '../graph-utils';
@@ -101,10 +102,13 @@ export const reducer = (state, action) => {
const selectedNodes = getNodesInside(state.nodes, action.payload.selection, state.transform); const selectedNodes = getNodesInside(state.nodes, action.payload.selection, state.transform);
const selectedEdges = getConnectedEdges(selectedNodes, state.edges); const selectedEdges = getConnectedEdges(selectedNodes, state.edges);
const nextSelectedElements = [...selectedNodes, ...selectedEdges];
const selectedElementsUpdated = !isEqual(nextSelectedElements, state.selectedElements);
return { return {
...state, ...state,
...action.payload, ...action.payload,
selectedElements: [...selectedNodes, ...selectedEdges] selectedElements: selectedElementsUpdated ? nextSelectedElements: state.selectedElements
}; };
} }
case SET_NODES_SELECTION: { case SET_NODES_SELECTION: {