diff --git a/web/app/components/workflow-app/components/workflow-main.tsx b/web/app/components/workflow-app/components/workflow-main.tsx index b891e9ecac2..449f4f66e27 100644 --- a/web/app/components/workflow-app/components/workflow-main.tsx +++ b/web/app/components/workflow-app/components/workflow-main.tsx @@ -421,6 +421,7 @@ const WorkflowMain = ({ nodes, edges, viewport }: WorkflowMainProps) => { viewport={viewport} onWorkflowDataUpdate={handleWorkflowDataUpdate} hooksStore={hooksStore as unknown as Partial} + isCollaborationEnabled={isCollaborationEnabled} cursors={filteredCursors} myUserId={myUserId} onlineUsers={onlineUsers} diff --git a/web/app/components/workflow/__tests__/workflow-edge-events.spec.tsx b/web/app/components/workflow/__tests__/workflow-edge-events.spec.tsx index 373c75daba8..44194d9d394 100644 --- a/web/app/components/workflow/__tests__/workflow-edge-events.spec.tsx +++ b/web/app/components/workflow/__tests__/workflow-edge-events.spec.tsx @@ -25,6 +25,7 @@ const reactFlowBridge = vi.hoisted(() => ({ })) const collaborationBridge = vi.hoisted(() => ({ + canPersistLocalGraph: vi.fn(), graphImportHandler: null as null | ((payload: { nodes: Node[]; edges: Edge[] }) => void), historyActionHandler: null as null | ((payload: unknown) => void), restoreIntentHandler: null as @@ -196,6 +197,7 @@ vi.mock('@langgenius/dify-ui/toast', () => ({ vi.mock('../collaboration/core/collaboration-manager', () => ({ collaborationManager: { + canPersistLocalGraph: collaborationBridge.canPersistLocalGraph, onGraphImport: (handler: (payload: { nodes: Node[]; edges: Edge[] }) => void) => { collaborationBridge.graphImportHandler = handler return vi.fn() @@ -453,12 +455,18 @@ function renderSubject(options?: { nodes?: Node[] edges?: Edge[] initialStoreState?: Record + isCollaborationEnabled?: boolean }) { - const { nodes = baseNodes, edges = baseEdges, initialStoreState } = options ?? {} + const { + nodes = baseNodes, + edges = baseEdges, + initialStoreState, + isCollaborationEnabled, + } = options ?? {} return renderWorkflowComponent( - + , @@ -514,6 +522,7 @@ vi.mock('@/context/permission-state', async () => { describe('Workflow edge event wiring', () => { beforeEach(() => { vi.clearAllMocks() + collaborationBridge.canPersistLocalGraph.mockReturnValue(true) eventEmitterState.subscription = null reactFlowBridge.store = null collaborationBridge.graphImportHandler = null @@ -615,7 +624,7 @@ describe('Workflow edge event wiring', () => { }, ) - const { unmount } = renderSubject() + const { unmount } = renderSubject({ isCollaborationEnabled: true }) unmount() @@ -624,6 +633,17 @@ describe('Workflow edge event wiring', () => { }) }) + it('should skip the unmount save while the collaborative graph is not ready', () => { + collaborationBridge.canPersistLocalGraph.mockReturnValue(false) + + const { unmount } = renderSubject({ isCollaborationEnabled: true }) + + unmount() + + expect(workflowHookMocks.handleSyncWorkflowDraft).not.toHaveBeenCalled() + expect(toastErrorMock).not.toHaveBeenCalled() + }) + it('should render confirm description and clear showConfirm when cancelled', async () => { const onConfirm = vi.fn() const { store } = renderSubject({ diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index c097d003976..0b8b982d839 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -125,6 +125,7 @@ export type WorkflowProps = { viewport?: Viewport children?: React.ReactNode onWorkflowDataUpdate?: (v: WorkflowDataUpdatePayload) => void + isCollaborationEnabled?: boolean cursors?: Record myUserId?: string | null onlineUsers?: OnlineUser[] @@ -168,6 +169,7 @@ export const Workflow: FC = memo( viewport, children, onWorkflowDataUpdate, + isCollaborationEnabled = false, cursors, myUserId, onlineUsers, @@ -364,6 +366,8 @@ export const Workflow: FC = memo( useEffect(() => { return () => { + if (isCollaborationEnabled && !collaborationManager.canPersistLocalGraph()) return + handleSyncWorkflowDraft(true, true, { onError: () => { toast.error( @@ -375,7 +379,7 @@ export const Workflow: FC = memo( }, }) } - }, [handleSyncWorkflowDraft, t]) + }, [handleSyncWorkflowDraft, isCollaborationEnabled, t]) const handlePendingCommentPositionChange = useCallback( (position: NonNullable) => {