feat: add auto layout functionality to workflow editor and toolbar
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
|||||||
RotateCcwIcon,
|
RotateCcwIcon,
|
||||||
SaveIcon,
|
SaveIcon,
|
||||||
SendIcon,
|
SendIcon,
|
||||||
|
SparklesIcon,
|
||||||
Undo2Icon,
|
Undo2Icon,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
|
|
||||||
@@ -23,6 +24,8 @@ export function WorkflowEditorToolbar({
|
|||||||
undoDisabled = false,
|
undoDisabled = false,
|
||||||
onRedo,
|
onRedo,
|
||||||
redoDisabled = false,
|
redoDisabled = false,
|
||||||
|
onAutoLayout,
|
||||||
|
autoLayoutDisabled = false,
|
||||||
onRestoreDefault,
|
onRestoreDefault,
|
||||||
restoreDefaultDisabled = false,
|
restoreDefaultDisabled = false,
|
||||||
onValidate,
|
onValidate,
|
||||||
@@ -40,6 +43,8 @@ export function WorkflowEditorToolbar({
|
|||||||
undoDisabled?: boolean
|
undoDisabled?: boolean
|
||||||
onRedo?: () => void
|
onRedo?: () => void
|
||||||
redoDisabled?: boolean
|
redoDisabled?: boolean
|
||||||
|
onAutoLayout?: () => void
|
||||||
|
autoLayoutDisabled?: boolean
|
||||||
onRestoreDefault?: () => void
|
onRestoreDefault?: () => void
|
||||||
restoreDefaultDisabled?: boolean
|
restoreDefaultDisabled?: boolean
|
||||||
onValidate?: () => void
|
onValidate?: () => void
|
||||||
@@ -74,6 +79,10 @@ export function WorkflowEditorToolbar({
|
|||||||
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={redoDisabled} onClick={onRedo}>
|
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={redoDisabled} onClick={onRedo}>
|
||||||
重做
|
重做
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={autoLayoutDisabled} onClick={onAutoLayout}>
|
||||||
|
<SparklesIcon className="size-3.5" />
|
||||||
|
自动布局
|
||||||
|
</Button>
|
||||||
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={restoreDefaultDisabled} onClick={onRestoreDefault}>
|
<Button type="button" variant="ghost" size="sm" className="h-7 px-2 text-xs" disabled={restoreDefaultDisabled} onClick={onRestoreDefault}>
|
||||||
<RotateCcwIcon className="size-3.5" />
|
<RotateCcwIcon className="size-3.5" />
|
||||||
恢复默认
|
恢复默认
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
type WorkflowJSON,
|
type WorkflowJSON,
|
||||||
type WorkflowNodeJSON,
|
type WorkflowNodeJSON,
|
||||||
useClientContext,
|
useClientContext,
|
||||||
|
usePlaygroundTools,
|
||||||
useService,
|
useService,
|
||||||
} from "@flowgram.ai/free-layout-editor"
|
} from "@flowgram.ai/free-layout-editor"
|
||||||
|
|
||||||
@@ -151,8 +152,10 @@ function WorkflowEditorInner({
|
|||||||
publishDisabled?: boolean
|
publishDisabled?: boolean
|
||||||
}) {
|
}) {
|
||||||
const context = useClientContext()
|
const context = useClientContext()
|
||||||
|
const playgroundTools = usePlaygroundTools()
|
||||||
const workflowDocument = useService(WorkflowDocument)
|
const workflowDocument = useService(WorkflowDocument)
|
||||||
const selectService = useService(WorkflowSelectService)
|
const selectService = useService(WorkflowSelectService)
|
||||||
|
const [autoLayouting, setAutoLayouting] = useState(false)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const disposable = selectService.onSelectionChanged(() => {
|
const disposable = selectService.onSelectionChanged(() => {
|
||||||
@@ -192,6 +195,24 @@ function WorkflowEditorInner({
|
|||||||
onDefinitionChange(context.document.toJSON() as AIWorkflowDefinition)
|
onDefinitionChange(context.document.toJSON() as AIWorkflowDefinition)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const autoLayout = async () => {
|
||||||
|
if (autoLayouting || definition.nodes.length < 2) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setAutoLayouting(true)
|
||||||
|
try {
|
||||||
|
await playgroundTools.autoLayout({
|
||||||
|
enableAnimation: true,
|
||||||
|
animationDuration: 240,
|
||||||
|
disableFitView: true,
|
||||||
|
})
|
||||||
|
playgroundTools.fitView(true)
|
||||||
|
emitCurrentDefinition()
|
||||||
|
} finally {
|
||||||
|
setAutoLayouting(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const closeConfigPanel = () => {
|
const closeConfigPanel = () => {
|
||||||
selectService.clear()
|
selectService.clear()
|
||||||
onSelectNode("")
|
onSelectNode("")
|
||||||
@@ -214,6 +235,8 @@ function WorkflowEditorInner({
|
|||||||
undoDisabled={undoDisabled}
|
undoDisabled={undoDisabled}
|
||||||
onRedo={onRedo}
|
onRedo={onRedo}
|
||||||
redoDisabled={redoDisabled}
|
redoDisabled={redoDisabled}
|
||||||
|
onAutoLayout={() => void autoLayout()}
|
||||||
|
autoLayoutDisabled={autoLayouting || definition.nodes.length < 2}
|
||||||
onRestoreDefault={onRestoreDefault}
|
onRestoreDefault={onRestoreDefault}
|
||||||
restoreDefaultDisabled={restoreDefaultDisabled}
|
restoreDefaultDisabled={restoreDefaultDisabled}
|
||||||
onValidate={onValidate}
|
onValidate={onValidate}
|
||||||
|
|||||||
Reference in New Issue
Block a user