File size: 6,394 Bytes
be99f83 4a674c0 db19895 be99f83 8207a08 be99f83 c298fc4 36669dc db19895 06a1fe2 4a674c0 be99f83 ddd1aa2 916a392 8207a08 db19895 c298fc4 be99f83 8207a08 ddd1aa2 06a1fe2 ddd1aa2 c298fc4 4a674c0 c298fc4 36669dc db19895 36669dc 06a1fe2 c298fc4 06a1fe2 36669dc 4a674c0 ddd1aa2 916a392 36669dc 916a392 36669dc 916a392 36669dc ddd1aa2 be99f83 ddd1aa2 db19895 ddd1aa2 be99f83 8207a08 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
import type {} from '@redux-devtools/extension';
import { humanId } from 'human-id';
import lodashSet from 'lodash/set';
import {
Connection,
Edge,
EdgeChange,
Node,
NodeChange,
OnConnect,
OnEdgesChange,
OnNodesChange,
OnSelectionChangeFunc,
OnSelectionChangeParams,
addEdge,
applyEdgeChanges,
applyNodeChanges,
} from 'reactflow';
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
import { Operator } from './constant';
import { NodeData } from './interface';
export type RFState = {
nodes: Node<NodeData>[];
edges: Edge[];
selectedNodeIds: string[];
selectedEdgeIds: string[];
onNodesChange: OnNodesChange;
onEdgesChange: OnEdgesChange;
onConnect: OnConnect;
setNodes: (nodes: Node[]) => void;
setEdges: (edges: Edge[]) => void;
updateNodeForm: (nodeId: string, values: any) => void;
onSelectionChange: OnSelectionChangeFunc;
addNode: (nodes: Node) => void;
getNode: (id?: string | null) => Node<NodeData> | undefined;
addEdge: (connection: Connection) => void;
getEdge: (id: string) => Edge | undefined;
deletePreviousEdgeOfClassificationNode: (connection: Connection) => void;
duplicateNode: (id: string) => void;
deleteEdge: () => void;
deleteEdgeById: (id: string) => void;
deleteNodeById: (id: string) => void;
deleteEdgeBySourceAndSourceHandle: (connection: Partial<Connection>) => void;
findNodeByName: (operatorName: Operator) => Node | undefined;
updateMutableNodeFormItem: (id: string, field: string, value: any) => void;
getOperatorTypeFromId: (id?: string | null) => string | undefined;
};
// this is our useStore hook that we can use in our components to get parts of the store and call actions
const useGraphStore = create<RFState>()(
devtools(
(set, get) => ({
nodes: [] as Node[],
edges: [] as Edge[],
selectedNodeIds: [] as string[],
selectedEdgeIds: [] as string[],
onNodesChange: (changes: NodeChange[]) => {
set({
nodes: applyNodeChanges(changes, get().nodes),
});
},
onEdgesChange: (changes: EdgeChange[]) => {
set({
edges: applyEdgeChanges(changes, get().edges),
});
},
onConnect: (connection: Connection) => {
set({
edges: addEdge(connection, get().edges),
});
get().deletePreviousEdgeOfClassificationNode(connection);
},
onSelectionChange: ({ nodes, edges }: OnSelectionChangeParams) => {
set({
selectedEdgeIds: edges.map((x) => x.id),
selectedNodeIds: nodes.map((x) => x.id),
});
},
setNodes: (nodes: Node[]) => {
set({ nodes });
},
setEdges: (edges: Edge[]) => {
set({ edges });
},
addNode: (node: Node) => {
set({ nodes: get().nodes.concat(node) });
},
getNode: (id?: string | null) => {
return get().nodes.find((x) => x.id === id);
},
getOperatorTypeFromId: (id?: string | null) => {
return get().getNode(id)?.data?.label;
},
addEdge: (connection: Connection) => {
set({
edges: addEdge(connection, get().edges),
});
get().deletePreviousEdgeOfClassificationNode(connection);
},
getEdge: (id: string) => {
return get().edges.find((x) => x.id === id);
},
deletePreviousEdgeOfClassificationNode: (connection: Connection) => {
// Delete the edge on the classification node anchor when the anchor is connected to other nodes
const { edges, getOperatorTypeFromId } = get();
if (getOperatorTypeFromId(connection.source) === Operator.Categorize) {
const previousEdge = edges.find(
(x) =>
x.source === connection.source &&
x.sourceHandle === connection.sourceHandle &&
x.target !== connection.target,
);
if (previousEdge) {
set({
edges: edges.filter((edge) => edge !== previousEdge),
});
}
}
},
// addOnlyOneEdgeBetweenTwoNodes: (connection: Connection) => {
// },
duplicateNode: (id: string) => {
const { getNode, addNode } = get();
const node = getNode(id);
const position = {
x: (node?.position?.x || 0) + 30,
y: (node?.position?.y || 0) + 20,
};
addNode({
...(node || {}),
data: node?.data,
selected: false,
dragging: false,
id: `${node?.data?.label}:${humanId()}`,
position,
});
},
deleteEdge: () => {
const { edges, selectedEdgeIds } = get();
set({
edges: edges.filter((edge) =>
selectedEdgeIds.every((x) => x !== edge.id),
),
});
},
deleteEdgeById: (id: string) => {
const { edges } = get();
set({
edges: edges.filter((edge) => edge.id !== id),
});
},
deleteEdgeBySourceAndSourceHandle: ({
source,
sourceHandle,
}: Partial<Connection>) => {
const { edges } = get();
const nextEdges = edges.filter(
(edge) =>
edge.source !== source || edge.sourceHandle !== sourceHandle,
);
set({
edges: nextEdges,
});
},
deleteNodeById: (id: string) => {
const { nodes, edges } = get();
set({
nodes: nodes.filter((node) => node.id !== id),
edges: edges
.filter((edge) => edge.source !== id)
.filter((edge) => edge.target !== id),
});
},
findNodeByName: (name: Operator) => {
return get().nodes.find((x) => x.data.label === name);
},
updateNodeForm: (nodeId: string, values: any) => {
set({
nodes: get().nodes.map((node) => {
if (node.id === nodeId) {
node.data = { ...node.data, form: values };
}
return node;
}),
});
},
updateMutableNodeFormItem: (id: string, field: string, value: any) => {
const { nodes } = get();
const idx = nodes.findIndex((x) => x.id === id);
if (idx) {
lodashSet(nodes, [idx, 'data', 'form', field], value);
}
},
}),
{ name: 'graph' },
),
);
export default useGraphStore;
|