fix: fixed deleting behaviour
ref: N25B-450
This commit is contained in:
@@ -44,6 +44,7 @@ const selector = (state: FlowState) => ({
|
|||||||
nodes: state.nodes,
|
nodes: state.nodes,
|
||||||
edges: state.edges,
|
edges: state.edges,
|
||||||
onNodesChange: state.onNodesChange,
|
onNodesChange: state.onNodesChange,
|
||||||
|
onNodesDelete: state.onNodesDelete,
|
||||||
onEdgesDelete: state.onEdgesDelete,
|
onEdgesDelete: state.onEdgesDelete,
|
||||||
onEdgesChange: state.onEdgesChange,
|
onEdgesChange: state.onEdgesChange,
|
||||||
onConnect: state.onConnect,
|
onConnect: state.onConnect,
|
||||||
@@ -69,6 +70,7 @@ const VisProgUI = () => {
|
|||||||
const {
|
const {
|
||||||
nodes, edges,
|
nodes, edges,
|
||||||
onNodesChange,
|
onNodesChange,
|
||||||
|
onNodesDelete,
|
||||||
onEdgesDelete,
|
onEdgesDelete,
|
||||||
onEdgesChange,
|
onEdgesChange,
|
||||||
onConnect,
|
onConnect,
|
||||||
@@ -122,6 +124,7 @@ const VisProgUI = () => {
|
|||||||
defaultEdgeOptions={DEFAULT_EDGE_OPTIONS}
|
defaultEdgeOptions={DEFAULT_EDGE_OPTIONS}
|
||||||
nodeTypes={NodeTypes}
|
nodeTypes={NodeTypes}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
|
onNodesDelete={onNodesDelete}
|
||||||
onEdgesDelete={onEdgesDelete}
|
onEdgesDelete={onEdgesDelete}
|
||||||
onEdgesChange={onEdgesChange}
|
onEdgesChange={onEdgesChange}
|
||||||
onReconnect={onReconnect}
|
onReconnect={onReconnect}
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ function createNode(id: string, type: string, position: XYPosition, data: Record
|
|||||||
// ...breaks logic that is dependent on connection events
|
// ...breaks logic that is dependent on connection events
|
||||||
const initialEdges: Edge[] = [];
|
const initialEdges: Edge[] = [];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* useFlowStore contains the implementation for all editor functionality
|
* useFlowStore contains the implementation for all editor functionality
|
||||||
* and stores the current state of the visual programming editor
|
* and stores the current state of the visual programming editor
|
||||||
@@ -87,7 +86,9 @@ const useFlowStore = create<FlowState>(UndoRedo((set, get) => ({
|
|||||||
*/
|
*/
|
||||||
onNodesChange: (changes) => set({nodes: applyNodeChanges(changes, get().nodes)}),
|
onNodesChange: (changes) => set({nodes: applyNodeChanges(changes, get().nodes)}),
|
||||||
|
|
||||||
onNodesDelete: (nodes) => nodes.forEach(node => get().unregisterNodeRules(node.id)),
|
onNodesDelete: (nodes) => nodes.forEach((_node) => {
|
||||||
|
return;
|
||||||
|
}),
|
||||||
|
|
||||||
onEdgesDelete: (edges) => {
|
onEdgesDelete: (edges) => {
|
||||||
// we make sure any affected nodes get updated to reflect removal of edges
|
// we make sure any affected nodes get updated to reflect removal of edges
|
||||||
@@ -183,19 +184,30 @@ const useFlowStore = create<FlowState>(UndoRedo((set, get) => ({
|
|||||||
* Deletes a node by ID, respecting NodeDeletes rules.
|
* Deletes a node by ID, respecting NodeDeletes rules.
|
||||||
* Also removes all edges connected to that node.
|
* Also removes all edges connected to that node.
|
||||||
*/
|
*/
|
||||||
deleteNode: (nodeId) => {
|
deleteNode: (nodeId, deleteElements) => {
|
||||||
get().pushSnapshot();
|
get().pushSnapshot();
|
||||||
|
|
||||||
// Let's find our node to check if they have a special deletion function
|
// Let's find our node to check if they have a special deletion function
|
||||||
const ourNode = get().nodes.find((n)=>n.id==nodeId);
|
const ourNode = get().nodes.find((n)=>n.id==nodeId);
|
||||||
const ourFunction = Object.entries(NodeDeletes).find(([t])=>t==ourNode?.type)?.[1]
|
const ourFunction = Object.entries(NodeDeletes).find(([t])=>t==ourNode?.type)?.[1]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// If there's no function, OR, our function tells us we can delete it, let's do so...
|
// If there's no function, OR, our function tells us we can delete it, let's do so...
|
||||||
if (ourFunction == undefined || ourFunction()) {
|
if (ourFunction == undefined || ourFunction()) {
|
||||||
set({
|
deleteElements({
|
||||||
nodes: get().nodes.filter((n) => n.id !== nodeId),
|
nodes: get().nodes.filter((n) => n.id === nodeId),
|
||||||
edges: get().edges.filter((e) => e.source !== nodeId && e.target !== nodeId),
|
edges: get().edges.filter((e) => e.source !== nodeId && e.target === nodeId)}
|
||||||
})}
|
).then(() => {
|
||||||
|
get().unregisterNodeRules(nodeId);
|
||||||
|
get().unregisterWarningsForId(nodeId);
|
||||||
|
});
|
||||||
|
// set({
|
||||||
|
// nodes: get().nodes.filter((n) => n.id !== nodeId),
|
||||||
|
// edges: get().edges.filter((e) => e.source !== nodeId && e.target !== nodeId),
|
||||||
|
// })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type {
|
|||||||
OnReconnect,
|
OnReconnect,
|
||||||
Node,
|
Node,
|
||||||
OnEdgesDelete,
|
OnEdgesDelete,
|
||||||
OnNodesDelete
|
OnNodesDelete, DeleteElementsOptions
|
||||||
} from '@xyflow/react';
|
} from '@xyflow/react';
|
||||||
import type {EditorWarningRegistry} from "./components/EditorWarnings.tsx";
|
import type {EditorWarningRegistry} from "./components/EditorWarnings.tsx";
|
||||||
import type {HandleRule} from "./HandleRuleLogic.ts";
|
import type {HandleRule} from "./HandleRuleLogic.ts";
|
||||||
@@ -69,7 +69,10 @@ export type FlowState = {
|
|||||||
* Deletes a node and any connected edges.
|
* Deletes a node and any connected edges.
|
||||||
* @param nodeId - the ID of the node to delete
|
* @param nodeId - the ID of the node to delete
|
||||||
*/
|
*/
|
||||||
deleteNode: (nodeId: string) => void;
|
deleteNode: (nodeId: string, deleteElements: (params: DeleteElementsOptions) => Promise<{
|
||||||
|
deletedNodes: Node[]
|
||||||
|
deletedEdges: Edge[]
|
||||||
|
}>) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the current nodes array in the store.
|
* Replaces the current nodes array in the store.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {NodeToolbar} from '@xyflow/react';
|
import {NodeToolbar, useReactFlow} from '@xyflow/react';
|
||||||
import '@xyflow/react/dist/style.css';
|
import '@xyflow/react/dist/style.css';
|
||||||
import {type JSX, useState} from "react";
|
import {type JSX, useState} from "react";
|
||||||
import {createPortal} from "react-dom";
|
import {createPortal} from "react-dom";
|
||||||
@@ -30,10 +30,11 @@ type ToolbarProps = {
|
|||||||
*/
|
*/
|
||||||
export function Toolbar({nodeId, allowDelete}: ToolbarProps) {
|
export function Toolbar({nodeId, allowDelete}: ToolbarProps) {
|
||||||
const {nodes, deleteNode} = useFlowStore();
|
const {nodes, deleteNode} = useFlowStore();
|
||||||
|
const { deleteElements } = useReactFlow();
|
||||||
|
|
||||||
const deleteParentNode = () => {
|
const deleteParentNode = () => {
|
||||||
deleteNode(nodeId);
|
|
||||||
|
deleteNode(nodeId, deleteElements);
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodeType = nodes.find((node) => node.id === nodeId)?.type as keyof typeof NodeTooltips;
|
const nodeType = nodes.find((node) => node.id === nodeId)?.type as keyof typeof NodeTooltips;
|
||||||
|
|||||||
Reference in New Issue
Block a user