refactor(api): use all elements instead of nodes only

This commit is contained in:
moklick
2019-07-24 23:44:48 +02:00
parent 9d44f26c68
commit 81746b2714
9 changed files with 38 additions and 25 deletions
+1 -1
View File
@@ -86,7 +86,7 @@ class App extends PureComponent {
<Graph <Graph
elements={this.state.elements} elements={this.state.elements}
onElementClick={node => console.log('clicked', node)} onElementClick={node => console.log('clicked', node)}
onNodeRemove={nodeIds => console.log('remove', nodeIds)} onElementsRemove={elements => console.log('remove', elements)}
style={{ width: '100%', height: '100%' }} style={{ width: '100%', height: '100%' }}
onLoad={graphInstance => this.onLoad(graphInstance)} onLoad={graphInstance => this.onLoad(graphInstance)}
onChange={(elements) => this.onChange(elements)} onChange={(elements) => this.onChange(elements)}
+6 -5
View File
@@ -3,16 +3,17 @@ import ReactDraggable from 'react-draggable';
import cx from 'classnames'; import cx from 'classnames';
import { GraphContext } from '../../GraphContext'; import { GraphContext } from '../../GraphContext';
import { updateNodePos, setSelectedNodesIds } from '../../state/actions'; import { updateNodePos, setSelectedElements } from '../../state/actions';
import { isEdge } from '../../graph-utils';
const isInputTarget = (e) => ['INPUT', 'SELECT', 'TEXTAREA'].includes(e.target.nodeName); const isInputTarget = (e) => ['INPUT', 'SELECT', 'TEXTAREA'].includes(e.target.nodeName);
export default EdgeComponent => (props) => { export default EdgeComponent => (props) => {
const { state, dispatch } = useContext(GraphContext); const { state, dispatch } = useContext(GraphContext);
const { data, onClick } = props; const { data, onClick } = props;
const { id } = data; const selected = state.selectedElements
const [ x, y, k ] = state.transform; .filter(e => isEdge(e))
const selected = state.selectedNodeIds.includes(id); .find(e => e.data.source === data.source && e.data.target === data.target);
const edgeClasses = cx('react-graph__edge', { selected }); const edgeClasses = cx('react-graph__edge', { selected });
return ( return (
@@ -23,7 +24,7 @@ export default EdgeComponent => (props) => {
return false; return false;
} }
// dispatch(setSelectedNodesIds(id)); dispatch(setSelectedElements({ data }));
onClick({ data }); onClick({ data });
}} }}
> >
+2 -2
View File
@@ -9,8 +9,8 @@ export default (props) => {
const removePressed = useKeyPress('Backspace'); const removePressed = useKeyPress('Backspace');
useEffect(() => { useEffect(() => {
if (removePressed && state.selectedNodeIds.length) { if (removePressed && state.selectedElements.length) {
props.onNodeRemove(state.selectedNodeIds); props.onElementsRemove(state.selectedElements);
dispatch(setNodesSelection({ isActive: false })); dispatch(setNodesSelection({ isActive: false }));
} }
}, [removePressed]) }, [removePressed])
+4 -3
View File
@@ -3,7 +3,8 @@ import ReactDraggable from 'react-draggable';
import cx from 'classnames'; import cx from 'classnames';
import { GraphContext } from '../../GraphContext'; import { GraphContext } from '../../GraphContext';
import { updateNodeData, updateNodePos, setSelectedNodesIds } from '../../state/actions'; import { updateNodeData, updateNodePos, setSelectedElements } from '../../state/actions';
import { isEdge } from '../../graph-utils';
const isInputTarget = (e) => ['INPUT', 'SELECT', 'TEXTAREA'].includes(e.target.nodeName); const isInputTarget = (e) => ['INPUT', 'SELECT', 'TEXTAREA'].includes(e.target.nodeName);
@@ -16,7 +17,7 @@ export default NodeComponent => (props) => {
const { position } = __rg; const { position } = __rg;
const { id } = data; const { id } = data;
const [ x, y, k ] = state.transform; const [ x, y, k ] = state.transform;
const selected = state.selectedNodeIds.includes(id); const selected = state.selectedElements.filter(e => !isEdge(e)).map(e => e.data.id).includes(id);
const nodeClasses = cx('react-graph__node', { selected }); const nodeClasses = cx('react-graph__node', { selected });
useEffect(() => { useEffect(() => {
@@ -69,7 +70,7 @@ export default NodeComponent => (props) => {
return false; return false;
} }
dispatch(setSelectedNodesIds(id)); dispatch(setSelectedElements({ data }));
onClick({ data, position }); onClick({ data, position });
}} }}
> >
+1 -1
View File
@@ -1,4 +1,4 @@
export const isEdge = element => element.data.source && element.data.target; export const isEdge = element => element.data && element.data.source && element.data.target;
export const parseElements = e => ({ export const parseElements = e => ({
...e, ...e,
+3 -3
View File
@@ -25,7 +25,7 @@ class ReactGraph extends PureComponent {
render() { render() {
const { const {
style, onElementClick, children, onLoad, onMove, onChange, elements, onNodeRemove style, onElementClick, children, onLoad, onMove, onChange, elements, onElementsRemove
} = this.props; } = this.props;
const { nodes, edges } = elements const { nodes, edges } = elements
@@ -43,7 +43,7 @@ class ReactGraph extends PureComponent {
edgeTypes={this.edgeTypes} edgeTypes={this.edgeTypes}
/> />
<GlobalKeyHandler <GlobalKeyHandler
onNodeRemove={onNodeRemove} onElementsRemove={onElementsRemove}
/> />
{children} {children}
</Provider> </Provider>
@@ -54,7 +54,7 @@ class ReactGraph extends PureComponent {
ReactGraph.defaultProps = { ReactGraph.defaultProps = {
onElementClick: () => {}, onElementClick: () => {},
onNodeRemove: () => {}, onElementsRemove: () => {},
onLoad: () => {}, onLoad: () => {},
onMove: () => {}, onMove: () => {},
onChange: () => {}, onChange: () => {},
+10 -4
View File
@@ -2,7 +2,7 @@ import {
UPDATE_TRANSFORM, UPDATE_SIZE, SET_NODES, SET_EDGES, UPDATE_TRANSFORM, UPDATE_SIZE, SET_NODES, SET_EDGES,
UPDATE_NODE_DATA, UPDATE_NODE_POS, INIT_D3, FIT_VIEW, UPDATE_NODE_DATA, UPDATE_NODE_POS, INIT_D3, FIT_VIEW,
UPDATE_SELECTION, SET_SELECTION, SET_NODES_SELECTION, UPDATE_SELECTION, SET_SELECTION, SET_NODES_SELECTION,
SET_SELECTED_NODES_IDS, REMOVE_NODES SET_SELECTED_ELEMENTS, REMOVE_NODES
} from './index'; } from './index';
export const updateTransform = (transform) => { export const updateTransform = (transform) => {
@@ -66,10 +66,16 @@ export const setNodesSelection = ({ isActive, selection }) => {
return { type: SET_NODES_SELECTION, payload: { nodesSelectionActive: isActive, selection } }; return { type: SET_NODES_SELECTION, payload: { nodesSelectionActive: isActive, selection } };
}; };
export const setSelectedNodesIds = (ids) => { export const setSelectedElements = (elements) => {
const idArray = Array.isArray(ids) ? ids : [ids]; const elementsArray = Array.isArray(elements) ? elements : [elements];
return { type: SET_SELECTED_NODES_IDS, payload: { selectedNodeIds: idArray, nodesSelectionActive: false } }; return {
type: SET_SELECTED_ELEMENTS,
payload: {
selectedElements: elementsArray,
nodesSelectionActive: false
}
};
}; };
export const removeNodes = (ids) => { export const removeNodes = (ids) => {
+7 -6
View File
@@ -13,7 +13,7 @@ export const FIT_VIEW = 'FIT_VIEW';
export const UPDATE_SELECTION = 'UPDATE_SELECTION'; export const UPDATE_SELECTION = 'UPDATE_SELECTION';
export const SET_SELECTION = 'SET_SELECTION'; export const SET_SELECTION = 'SET_SELECTION';
export const SET_NODES_SELECTION = 'SET_NODES_SELECTION'; export const SET_NODES_SELECTION = 'SET_NODES_SELECTION';
export const SET_SELECTED_NODES_IDS = 'SET_SELECTED_NODES_IDS'; export const SET_SELECTED_ELEMENTS = 'SET_SELECTED_ELEMENTS';
export const REMOVE_NODES = 'REMOVE_NODES'; export const REMOVE_NODES = 'REMOVE_NODES';
export const initialState = { export const initialState = {
@@ -22,7 +22,7 @@ export const initialState = {
transform: [0, 0, 1], transform: [0, 0, 1],
nodes: [], nodes: [],
edges: [], edges: [],
selectedNodeIds: [], selectedElements: [],
selectedNodesBbox: { x: 0, y: 0, width: 0, height: 0 }, selectedNodesBbox: { x: 0, y: 0, width: 0, height: 0 },
d3Zoom: null, d3Zoom: null,
@@ -79,13 +79,14 @@ export const reducer = (state, action) => {
} }
case UPDATE_SELECTION: { case UPDATE_SELECTION: {
const selectedNodes = getNodesInside(state.nodes, action.payload.selection, state.transform); const selectedNodes = getNodesInside(state.nodes, action.payload.selection, state.transform);
const selectedNodeIds = selectedNodes.map(n => n.data.id); const selectedNodesIds = selectedNodes.map(n => n.data.id);
const selectedEdges = state.edges.filter(e => selectedNodesIds.includes(e.data.source) || selectedNodesIds.includes(e.data.target))
return { ...state, ...action.payload, selectedNodeIds }; return { ...state, ...action.payload, selectedElements: [...selectedNodes, ...selectedEdges] };
} }
case SET_NODES_SELECTION: { case SET_NODES_SELECTION: {
if (!action.payload.nodesSelectionActive) { if (!action.payload.nodesSelectionActive) {
return { ...state, nodesSelectionActive: false, selectedNodeIds: [] }; return { ...state, nodesSelectionActive: false, selectedElements: [] };
} }
const selectedNodes = getNodesInside(state.nodes, action.payload.selection, state.transform); const selectedNodes = getNodesInside(state.nodes, action.payload.selection, state.transform);
const selectedNodesBbox = getBoundingBox(selectedNodes); const selectedNodesBbox = getBoundingBox(selectedNodes);
@@ -105,7 +106,7 @@ export const reducer = (state, action) => {
case INIT_D3: case INIT_D3:
case UPDATE_SIZE: case UPDATE_SIZE:
case SET_SELECTION: case SET_SELECTION:
case SET_SELECTED_NODES_IDS: case SET_SELECTED_ELEMENTS:
return { ...state, ...action.payload }; return { ...state, ...action.payload };
default: default:
return state; return state;
+4
View File
@@ -52,6 +52,10 @@
pointer-events: all; pointer-events: all;
} }
.react-graph__edge.selected {
stroke: #ff5050;
}
.react-graph__nodes { .react-graph__nodes {
width: 100%; width: 100%;
height: 100%; height: 100%;