mirror of
https://github.com/langgenius/dify.git
synced 2026-11-12 14:21:29 +08:00
# Conflicts: # api/services/app_generate_service.py # api/services/workflow_service.py # web/app/components/app/create-app-dialog-shell.tsx # web/app/components/app/create-app-dialog/__tests__/index.spec.tsx # web/app/components/app/create-app-dialog/app-list/__tests__/sidebar.spec.tsx # web/app/components/app/create-app-modal/__tests__/index.spec.tsx # web/app/components/app/create-app-modal/index.tsx # web/app/components/apps/__tests__/list.spec.tsx # web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts # web/app/components/workflow-app/components/__tests__/workflow-main.spec.tsx # web/app/components/workflow-app/components/__tests__/workflow-panel.spec.tsx # web/app/components/workflow-app/hooks/__tests__/use-DSL.spec.ts # web/app/components/workflow-app/hooks/__tests__/use-nodes-sync-draft.spec.ts # web/app/components/workflow-app/hooks/__tests__/use-workflow-init.spec.ts # web/app/components/workflow-app/hooks/__tests__/use-workflow-refresh-draft.spec.ts # web/app/components/workflow-app/hooks/__tests__/use-workflow-run.spec.ts # web/app/components/workflow-app/hooks/use-DSL.ts # web/app/components/workflow-app/hooks/use-nodes-sync-draft.ts # web/app/components/workflow-app/hooks/use-workflow-init.ts # web/app/components/workflow-app/hooks/use-workflow-refresh-draft.ts # web/app/components/workflow/__tests__/workflow-edge-events.spec.tsx # web/app/components/workflow/collaboration/core/__tests__/crdt-provider.test.ts # web/app/components/workflow/collaboration/hooks/__tests__/use-collaboration.spec.ts # web/app/components/workflow/header/__tests__/header-layouts.spec.tsx # web/app/components/workflow/header/__tests__/run-and-history.spec.tsx # web/app/components/workflow/header/__tests__/scroll-to-selected-node-button.spec.tsx # web/app/components/workflow/header/checklist/__tests__/index.spec.tsx # web/app/components/workflow/hooks/__tests__/use-workflow-panel-interactions.spec.tsx # web/app/components/workflow/hooks/__tests__/use-workflow-search.spec.tsx # web/app/components/workflow/hooks/__tests__/use-workflow-update.spec.tsx # web/app/components/workflow/hooks/__tests__/use-workflow.spec.ts # web/app/components/workflow/nodes/__tests__/index.spec.tsx # web/app/components/workflow/nodes/question-classifier/__tests__/integration.spec.tsx # web/app/components/workflow/operator/__tests__/control.spec.tsx # web/app/components/workflow/operator/__tests__/zoom-in-out.spec.tsx # web/app/components/workflow/panel/__tests__/workflow-preview.spec.tsx # web/app/components/workflow/run/__tests__/result-panel.spec.tsx # web/app/components/workflow/store/__tests__/workflow-draft-slice.spec.ts # web/app/components/workflow/utils/__tests__/node-navigation.spec.ts # web/app/components/workflow/utils/node-navigation.ts # web/i18n/locales/ar-TN/app.json # web/i18n/locales/az-AZ/app.json # web/i18n/locales/de-DE/app.json # web/i18n/locales/en-US/app.json # web/i18n/locales/es-ES/app.json # web/i18n/locales/fa-IR/app.json # web/i18n/locales/fr-FR/app.json # web/i18n/locales/hi-IN/app.json # web/i18n/locales/id-ID/app.json # web/i18n/locales/it-IT/app.json # web/i18n/locales/ja-JP/app.json # web/i18n/locales/ko-KR/app.json # web/i18n/locales/lo-LA/app.json # web/i18n/locales/nl-NL/app.json # web/i18n/locales/pl-PL/app.json # web/i18n/locales/pt-BR/app.json # web/i18n/locales/ro-RO/app.json # web/i18n/locales/ru-RU/app.json # web/i18n/locales/sl-SI/app.json # web/i18n/locales/th-TH/app.json # web/i18n/locales/tr-TR/app.json # web/i18n/locales/uk-UA/app.json # web/i18n/locales/vi-VN/app.json # web/i18n/locales/zh-Hans/app.json # web/i18n/locales/zh-Hant/app.json # web/i18n/resources.generated.d.ts # web/service/console/client.spec.ts
120 lines
3.5 KiB
TypeScript
120 lines
3.5 KiB
TypeScript
import type { Node, ReactFlowInstance } from 'reactflow'
|
|
|
|
/**
|
|
* Node navigation utilities for workflow
|
|
* This module provides functions for node selection, focusing and scrolling in workflow
|
|
*/
|
|
|
|
/**
|
|
* Interface for node selection event detail
|
|
*/
|
|
type NodeSelectionDetail = {
|
|
nodeId: string
|
|
focus?: boolean
|
|
shouldFocus?: () => boolean
|
|
}
|
|
|
|
/**
|
|
* Select a node in the workflow
|
|
* @param nodeId - The ID of the node to select
|
|
* @param focus - Whether to focus/scroll to the node
|
|
*/
|
|
export function selectWorkflowNode(
|
|
nodeId: string,
|
|
focus = false,
|
|
shouldFocus?: () => boolean,
|
|
): void {
|
|
// Create and dispatch a custom event for node selection
|
|
const event = new CustomEvent('workflow:select-node', {
|
|
detail: {
|
|
nodeId,
|
|
focus,
|
|
...(shouldFocus && { shouldFocus }),
|
|
},
|
|
})
|
|
document.dispatchEvent(event)
|
|
}
|
|
|
|
/**
|
|
* Scroll to a specific node in the workflow
|
|
* @param nodeId - The ID of the node to scroll to
|
|
*/
|
|
export function scrollToWorkflowNode(nodeId: string): void {
|
|
// Create and dispatch a custom event for scrolling to node
|
|
const event = new CustomEvent('workflow:scroll-to-node', {
|
|
detail: { nodeId },
|
|
})
|
|
document.dispatchEvent(event)
|
|
}
|
|
|
|
/**
|
|
* Setup node selection event listener
|
|
* @param handleNodeSelect - Function to handle node selection
|
|
* @returns Cleanup function
|
|
*/
|
|
export function setupNodeSelectionListener(handleNodeSelect: (nodeId: string) => void): () => void {
|
|
// Event handler for node selection
|
|
const handleNodeSelection = (event: CustomEvent<NodeSelectionDetail>) => {
|
|
const { nodeId, focus, shouldFocus } = event.detail
|
|
if (nodeId) {
|
|
// Select the node
|
|
handleNodeSelect(nodeId)
|
|
|
|
// If focus is requested, scroll to the node
|
|
if (focus) {
|
|
// Use a small timeout to ensure node selection happens first
|
|
setTimeout(() => {
|
|
if (!shouldFocus || shouldFocus()) scrollToWorkflowNode(nodeId)
|
|
}, 100)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add event listener
|
|
document.addEventListener('workflow:select-node', handleNodeSelection as EventListener)
|
|
|
|
// Return cleanup function
|
|
return () => {
|
|
document.removeEventListener('workflow:select-node', handleNodeSelection as EventListener)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Setup scroll to node event listener with ReactFlow
|
|
* @param nodes - The workflow nodes
|
|
* @param reactflow - The ReactFlow instance
|
|
* @returns Cleanup function
|
|
*/
|
|
export function setupScrollToNodeListener(
|
|
nodes: Pick<Node, 'id' | 'position'>[],
|
|
reactflow: Pick<ReactFlowInstance, 'setCenter'>,
|
|
): () => void {
|
|
// Event handler for scrolling to node
|
|
const handleScrollToNode = (event: CustomEvent<NodeSelectionDetail>) => {
|
|
const { nodeId } = event.detail
|
|
if (nodeId) {
|
|
// Find the target node
|
|
const node = nodes.find((n) => n.id === nodeId)
|
|
if (node) {
|
|
// Use ReactFlow's fitView API to scroll to the node
|
|
const nodePosition = { x: node.position.x, y: node.position.y }
|
|
|
|
// Calculate position to place node in top-left area
|
|
// Move the center point right and down to show node in top-left
|
|
const targetX = nodePosition.x + window.innerWidth * 0.25
|
|
const targetY = nodePosition.y + window.innerHeight * 0.25
|
|
|
|
reactflow.setCenter(targetX, targetY, { zoom: 1, duration: 800 })
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add event listener
|
|
document.addEventListener('workflow:scroll-to-node', handleScrollToNode as EventListener)
|
|
|
|
// Return cleanup function
|
|
return () => {
|
|
document.removeEventListener('workflow:scroll-to-node', handleScrollToNode as EventListener)
|
|
}
|
|
}
|