feat: add delete functionality for condition branches in node forms and improve edge filtering in workflow normalization
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { Field, type WorkflowNodeRegistry } from "@flowgram.ai/free-layout-editor"
|
import { Field, type WorkflowNodeRegistry } from "@flowgram.ai/free-layout-editor"
|
||||||
import { PlusIcon } from "lucide-react"
|
import { PlusIcon, XIcon } from "lucide-react"
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import type { AIWorkflowNodeSpec } from "@/lib/api/admin"
|
import type { AIWorkflowNodeSpec } from "@/lib/api/admin"
|
||||||
@@ -99,6 +99,9 @@ function ConditionNodeForm({ fallbackTitle }: { fallbackTitle: string }) {
|
|||||||
branches: ensureConditionBranches(nextBranches),
|
branches: ensureConditionBranches(nextBranches),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const deleteBranch = (branchId: string) => {
|
||||||
|
updateBranches(branches.filter((branch) => branch.id !== branchId))
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="px-4 py-3">
|
<div className="px-4 py-3">
|
||||||
@@ -114,6 +117,19 @@ function ConditionNodeForm({ fallbackTitle }: { fallbackTitle: string }) {
|
|||||||
<span className="shrink-0 rounded-sm bg-[#e7e9f3] px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
<span className="shrink-0 rounded-sm bg-[#e7e9f3] px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
||||||
{branch.default ? "else" : index === 0 ? "if" : "elseif"}
|
{branch.default ? "else" : index === 0 ? "if" : "elseif"}
|
||||||
</span>
|
</span>
|
||||||
|
{branch.default ? null : (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="flex size-5 shrink-0 items-center justify-center rounded-sm text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
|
||||||
|
aria-label={`删除条件 ${branch.name || branch.id}`}
|
||||||
|
onClick={(event) => {
|
||||||
|
event.stopPropagation()
|
||||||
|
deleteBranch(branch.id)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<XIcon className="size-3.5" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
<span
|
<span
|
||||||
data-port-id={branch.id}
|
data-port-id={branch.id}
|
||||||
data-port-type="output"
|
data-port-type="output"
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ function ConditionBranchesEditor({
|
|||||||
className="h-8"
|
className="h-8"
|
||||||
onChange={(event) => onChange({ ...branch, name: event.target.value })}
|
onChange={(event) => onChange({ ...branch, name: event.target.value })}
|
||||||
/>
|
/>
|
||||||
|
{branch.default ? null : (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@@ -283,6 +284,7 @@ function ConditionBranchesEditor({
|
|||||||
>
|
>
|
||||||
删除
|
删除
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
|
|||||||
@@ -241,18 +241,32 @@ export function deleteConditionBranch(
|
|||||||
return definition
|
return definition
|
||||||
}
|
}
|
||||||
const config = normalizeNodeConfig(node.data?.config)
|
const config = normalizeNodeConfig(node.data?.config)
|
||||||
return updateWorkflowNodeData(definition, nodeId, {
|
const nextDefinition = updateWorkflowNodeData(definition, nodeId, {
|
||||||
...(node.data ?? {}),
|
...(node.data ?? {}),
|
||||||
config: {
|
config: {
|
||||||
...config,
|
...config,
|
||||||
branches: (config.branches ?? []).filter((branch) => branch.id !== branchId),
|
branches: (config.branches ?? []).filter((branch) => branch.id !== branchId),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
return {
|
||||||
|
...nextDefinition,
|
||||||
|
edges: nextDefinition.edges.filter((edge) => !(edge.sourceNodeID === nodeId && edge.sourcePortID === branchId)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeConditionPortsForFlowgram(
|
export function normalizeConditionPortsForFlowgram(
|
||||||
definition: AIWorkflowDefinition
|
definition: AIWorkflowDefinition
|
||||||
): AIWorkflowDefinition {
|
): AIWorkflowDefinition {
|
||||||
|
const branchIdsByNodeId = new Map<string, Set<string>>()
|
||||||
|
for (const node of definition.nodes) {
|
||||||
|
if (node.type !== "condition") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const config = normalizeNodeConfig(node.data?.config)
|
||||||
|
const branches = ensureConditionBranches(config.branches ?? [])
|
||||||
|
branchIdsByNodeId.set(node.id, new Set(branches.map((branch) => branch.id)))
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...definition,
|
...definition,
|
||||||
nodes: definition.nodes.map((node) => {
|
nodes: definition.nodes.map((node) => {
|
||||||
@@ -271,7 +285,13 @@ export function normalizeConditionPortsForFlowgram(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
edges: definition.edges.map((edge) => {
|
edges: definition.edges.filter((edge) => {
|
||||||
|
if (!edge.sourcePortID) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const branchIds = branchIdsByNodeId.get(edge.sourceNodeID)
|
||||||
|
return !branchIds || branchIds.has(edge.sourcePortID)
|
||||||
|
}).map((edge) => {
|
||||||
const source = definition.nodes.find((node) => node.id === edge.sourceNodeID)
|
const source = definition.nodes.find((node) => node.id === edge.sourceNodeID)
|
||||||
if (!source || source.type !== "condition" || edge.sourcePortID) {
|
if (!source || source.type !== "condition" || edge.sourcePortID) {
|
||||||
return edge
|
return edge
|
||||||
|
|||||||
Reference in New Issue
Block a user