fix(elements): change data from outside

This commit is contained in:
moklick
2019-07-17 17:34:42 +02:00
parent a5aa78f02a
commit 1dbeebfb27
8 changed files with 59 additions and 33 deletions
-1
View File
@@ -82,7 +82,6 @@ class App extends PureComponent {
} }
render() { render() {
console.log(this.state.elements);
return ( return (
<Graph <Graph
elements={this.state.elements} elements={this.state.elements}
+4 -4
View File
@@ -3,11 +3,11 @@ import React from 'react';
export default (props) => { export default (props) => {
const { targetNode, sourceNode } = props; const { targetNode, sourceNode } = props;
const sourceX = sourceNode.position.x + (sourceNode.data.__width / 2); const sourceX = sourceNode.__rg.position.x + (sourceNode.__rg.width / 2);
const sourceY = sourceNode.position.y + sourceNode.data.__height; const sourceY = sourceNode.__rg.position.y + sourceNode.__rg.height;
const targetX = targetNode.position.x + (targetNode.data.__width / 2); const targetX = targetNode.__rg.position.x + (targetNode.__rg.width / 2);
const targetY = targetNode.position.y; const targetY = targetNode.__rg.position.y;
return ( return (
<path <path
+4 -1
View File
@@ -20,7 +20,10 @@ export const Provider = (props) => {
const existingNode = state.nodes.find(n => n.data.id === propNode.data.id); const existingNode = state.nodes.find(n => n.data.id === propNode.data.id);
if (existingNode) { if (existingNode) {
return Object.assign(propNode, existingNode); return {
...existingNode,
data: { ...existingNode.data, ...propNode.data }
};
} }
return propNode; return propNode;
+10 -8
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useContext } from 'react'; import React, { useEffect, useRef, useContext, useState } from 'react';
import ReactDraggable from 'react-draggable'; import ReactDraggable from 'react-draggable';
import cx from 'classnames'; import cx from 'classnames';
@@ -8,10 +8,13 @@ import { updateNodeData, updateNodePos } from '../../state/actions';
const isInputTarget = (e) => ['INPUT', 'SELECT', 'TEXTAREA'].includes(e.target.nodeName); const isInputTarget = (e) => ['INPUT', 'SELECT', 'TEXTAREA'].includes(e.target.nodeName);
export default NodeComponent => (props) => { export default NodeComponent => (props) => {
const { position, data, onNodeClick } = props;
const { id } = data;
const nodeElement = useRef(null); const nodeElement = useRef(null);
const graphContext = useContext(GraphContext); const graphContext = useContext(GraphContext);
const [offset, setOffset] = useState({ x: 0, y: 0 });
const { data, onNodeClick, __rg } = props;
const { position } = __rg;
const { id } = data;
const [ x, y, k ] = graphContext.state.transform; const [ x, y, k ] = graphContext.state.transform;
const selected = graphContext.state.selectedNodes.includes(id); const selected = graphContext.state.selectedNodes.includes(id);
const nodeClasses = cx('react-graph__node', { selected }); const nodeClasses = cx('react-graph__node', { selected });
@@ -21,7 +24,7 @@ export default NodeComponent => (props) => {
const unscaledWith = Math.round(bounds.width * (1 / k)); const unscaledWith = Math.round(bounds.width * (1 / k));
const unscaledHeight = Math.round(bounds.height * (1 / k)); const unscaledHeight = Math.round(bounds.height * (1 / k));
graphContext.dispatch(updateNodeData(id, { __width: unscaledWith, __height: unscaledHeight })); graphContext.dispatch(updateNodeData(id, { width: unscaledWith, height: unscaledHeight }));
}, []); }, []);
return ( return (
@@ -39,18 +42,17 @@ export default NodeComponent => (props) => {
const offsetX = unscaledPos.x - position.x - x; const offsetX = unscaledPos.x - position.x - x;
const offsetY = unscaledPos.y - position.y - y; const offsetY = unscaledPos.y - position.y - y;
graphContext.dispatch(updateNodeData(id, { __offsetX: offsetX, __offsetY: offsetY })); setOffset({ x: offsetX, y: offsetY });
}} }}
onDrag={(e, d) => { onDrag={(e, d) => {
const { __offsetX = 0, __offsetY = 0 } = data;
const unscaledPos = { const unscaledPos = {
x: e.clientX * (1 / k), x: e.clientX * (1 / k),
y: e.clientY * (1 / k) y: e.clientY * (1 / k)
} }
graphContext.dispatch(updateNodePos(id, { graphContext.dispatch(updateNodePos(id, {
x: unscaledPos.x - x - __offsetX, x: unscaledPos.x - x - offset.x,
y: unscaledPos.y - y - __offsetY y: unscaledPos.y - y - offset.y
})); }));
}} }}
scale={k} scale={k}
+1 -3
View File
@@ -15,10 +15,8 @@ class NodeRenderer extends PureComponent {
return ( return (
<NodeComponent <NodeComponent
key={d.data.id} key={d.data.id}
position={d.position}
data={d.data}
style={d.style || {}}
onNodeClick={onNodeClick} onNodeClick={onNodeClick}
{...d}
/> />
); );
} }
+30 -11
View File
@@ -1,25 +1,43 @@
export const isEdge = element => element.data.source && element.data.target; export const isEdge = element => element.data.source && element.data.target;
export const separateElements = elements => ({ export const parseElements = e => ({
nodes: elements.filter(e => !isEdge(e)), ...e,
edges: elements.filter(e => isEdge(e)) __rg: {
position: e.position,
width: null,
height: null
}
}); });
export const separateElements = (res, element) => {
res.edges = res.edges ? res.edges : [];
res.nodes = res.nodes ? res.nodes : [];
if (isEdge(element)) {
res.edges.push(element);
} else {
res.nodes.push(element);
}
return res;
};
export const getBoundingBox = (nodes) => { export const getBoundingBox = (nodes) => {
const bbox = nodes.reduce((res, node) => { const bbox = nodes.reduce((res, node) => {
const x2 = node.position.x + node.data.__width; const { position } = node.__rg;
const y2 = node.position.y + node.data.__height; const x2 = position.x + node.__rg.width;
const y2 = position.y + node.__rg.height;
if (node.position.x < res.minX) { if (position.x < res.minX) {
res.minX = node.position.x; res.minX = position.x;
} }
if (x2 > res.maxX) { if (x2 > res.maxX) {
res.maxX = x2; res.maxX = x2;
} }
if (node.position.y < res.minY) { if (position.y < res.minY) {
res.minY = node.position.y; res.minY = position.y;
} }
if (y2 > res.maxY) { if (y2 > res.maxY) {
@@ -58,10 +76,11 @@ export const getNodesInside = (nodes, bbox, transform = [0, 0, 1]) => {
}; };
const bboxWidth = bbox.width * (1 / transform[2]); const bboxWidth = bbox.width * (1 / transform[2]);
const bboxHeight = bbox.height * (1 / transform[2]); const bboxHeight = bbox.height * (1 / transform[2]);
const { position, width, height } = n.__rg;
return ( return (
(n.position.x > bboxPos.x && (n.position.x + n.data.__width) < (bboxPos.x + bboxWidth)) && (position.x > bboxPos.x && (position.x + width) < (bboxPos.x + bboxWidth)) &&
(n.position.y > bboxPos.y && (n.position.y + n.data.__height) < (bboxPos.y + bboxHeight)) (position.y > bboxPos.y && (position.y + height) < (bboxPos.y + bboxHeight))
); );
}); });
}; };
+4 -2
View File
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { separateElements } from './graph-utils'; import { parseElements, separateElements } from './graph-utils';
import GraphView from './GraphView'; import GraphView from './GraphView';
import { Provider } from './GraphContext'; import { Provider } from './GraphContext';
import { createNodeTypes } from './NodeRenderer/utils'; import { createNodeTypes } from './NodeRenderer/utils';
@@ -23,7 +23,9 @@ class ReactGraph extends PureComponent {
style, onNodeClick, children, onLoad, onMove, onChange, elements style, onNodeClick, children, onLoad, onMove, onChange, elements
} = this.props; } = this.props;
const { nodes, edges } = separateElements(elements); const { nodes, edges } = elements
.map(parseElements)
.reduce(separateElements, {});
return ( return (
<div style={style} className="react-graph"> <div style={style} className="react-graph">
+6 -3
View File
@@ -36,8 +36,8 @@ export const reducer = (state, action) => {
...state, ...state,
nodes: state.nodes.map((n) => { nodes: state.nodes.map((n) => {
if (n.data.id === action.payload.id) { if (n.data.id === action.payload.id) {
n.data = { n.__rg = {
...n.data, ...n.__rg,
...action.payload.data ...action.payload.data
}; };
} }
@@ -50,7 +50,10 @@ export const reducer = (state, action) => {
...state, ...state,
nodes: state.nodes.map((n) => { nodes: state.nodes.map((n) => {
if (n.data.id === action.payload.id) { if (n.data.id === action.payload.id) {
n.position = action.payload.pos; n.__rg = {
...n.__rg,
position: action.payload.pos
};
} }
return n; return n;