refactor(api): use all elements instead of nodes only
This commit is contained in:
@@ -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)}
|
||||||
|
|||||||
@@ -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 });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -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])
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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%;
|
||||||
|
|||||||
Reference in New Issue
Block a user