mirror of https://github.com/langgenius/dify.git
fix(workflow): reset onboarding auto-open flag across flows
This commit is contained in:
parent
f02d575379
commit
075173e67d
|
|
@ -18,6 +18,7 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
const mockSetShowOnboarding = jest.fn()
|
||||
const mockSetHasSelectedStartNode = jest.fn()
|
||||
const mockSetHasShownOnboarding = jest.fn()
|
||||
const mockSetShouldAutoOpenStartNodeSelector = jest.fn()
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
|
|
@ -31,6 +32,8 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
hasShownOnboarding: false,
|
||||
setHasShownOnboarding: mockSetHasShownOnboarding,
|
||||
notInitialWorkflow: false,
|
||||
shouldAutoOpenStartNodeSelector: false,
|
||||
setShouldAutoOpenStartNodeSelector: mockSetShouldAutoOpenStartNodeSelector,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -180,17 +183,17 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('Auto-expand Logic for Node Handles', () => {
|
||||
describe('Auto-open Logic for Node Handles', () => {
|
||||
/**
|
||||
* Test the auto-expand logic from node-handle.tsx
|
||||
* This ensures all trigger types auto-expand the block selector
|
||||
* Test the auto-open logic from node-handle.tsx
|
||||
* This ensures all trigger types auto-open the block selector when flagged
|
||||
*/
|
||||
it('should auto-expand for Start node in new workflow', () => {
|
||||
const notInitialWorkflow = true
|
||||
const shouldAutoOpenStartNodeSelector = true
|
||||
const nodeType = BlockEnum.Start
|
||||
const isChatMode = false
|
||||
|
||||
const shouldAutoExpand = notInitialWorkflow && (
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|
|
@ -201,11 +204,11 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
})
|
||||
|
||||
it('should auto-expand for TriggerSchedule in new workflow', () => {
|
||||
const notInitialWorkflow = true
|
||||
const shouldAutoOpenStartNodeSelector = true
|
||||
const nodeType = BlockEnum.TriggerSchedule
|
||||
const isChatMode = false
|
||||
|
||||
const shouldAutoExpand = notInitialWorkflow && (
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|
|
@ -216,11 +219,11 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
})
|
||||
|
||||
it('should auto-expand for TriggerWebhook in new workflow', () => {
|
||||
const notInitialWorkflow = true
|
||||
const shouldAutoOpenStartNodeSelector = true
|
||||
const nodeType = BlockEnum.TriggerWebhook
|
||||
const isChatMode = false
|
||||
|
||||
const shouldAutoExpand = notInitialWorkflow && (
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|
|
@ -231,11 +234,11 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
})
|
||||
|
||||
it('should auto-expand for TriggerPlugin in new workflow', () => {
|
||||
const notInitialWorkflow = true
|
||||
const shouldAutoOpenStartNodeSelector = true
|
||||
const nodeType = BlockEnum.TriggerPlugin
|
||||
const isChatMode = false
|
||||
|
||||
const shouldAutoExpand = notInitialWorkflow && (
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|
|
@ -246,11 +249,11 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
})
|
||||
|
||||
it('should not auto-expand for non-trigger nodes', () => {
|
||||
const notInitialWorkflow = true
|
||||
const shouldAutoOpenStartNodeSelector = true
|
||||
const nodeType = BlockEnum.LLM
|
||||
const isChatMode = false
|
||||
|
||||
const shouldAutoExpand = notInitialWorkflow && (
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|
|
@ -261,11 +264,11 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
})
|
||||
|
||||
it('should not auto-expand in chat mode', () => {
|
||||
const notInitialWorkflow = true
|
||||
const shouldAutoOpenStartNodeSelector = true
|
||||
const nodeType = BlockEnum.Start
|
||||
const isChatMode = true
|
||||
|
||||
const shouldAutoExpand = notInitialWorkflow && (
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|
|
@ -276,11 +279,11 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
})
|
||||
|
||||
it('should not auto-expand for existing workflows', () => {
|
||||
const notInitialWorkflow = false
|
||||
const shouldAutoOpenStartNodeSelector = false
|
||||
const nodeType = BlockEnum.Start
|
||||
const isChatMode = false
|
||||
|
||||
const shouldAutoExpand = notInitialWorkflow && (
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|
|
@ -289,6 +292,24 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
|
||||
expect(shouldAutoExpand).toBe(false)
|
||||
})
|
||||
it('should reset auto-open flag after triggering once', () => {
|
||||
let shouldAutoOpenStartNodeSelector = true
|
||||
const nodeType = BlockEnum.Start
|
||||
const isChatMode = false
|
||||
|
||||
const shouldAutoExpand = shouldAutoOpenStartNodeSelector && (
|
||||
nodeType === BlockEnum.Start
|
||||
|| nodeType === BlockEnum.TriggerSchedule
|
||||
|| nodeType === BlockEnum.TriggerWebhook
|
||||
|| nodeType === BlockEnum.TriggerPlugin
|
||||
) && !isChatMode
|
||||
|
||||
if (shouldAutoExpand)
|
||||
shouldAutoOpenStartNodeSelector = false
|
||||
|
||||
expect(shouldAutoExpand).toBe(true)
|
||||
expect(shouldAutoOpenStartNodeSelector).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Node Creation Without Auto-selection', () => {
|
||||
|
|
@ -450,12 +471,19 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
notInitialWorkflow: false,
|
||||
setShowOnboarding: mockSetShowOnboarding,
|
||||
setHasShownOnboarding: mockSetHasShownOnboarding,
|
||||
hasSelectedStartNode: false,
|
||||
setHasSelectedStartNode: mockSetHasSelectedStartNode,
|
||||
shouldAutoOpenStartNodeSelector: false,
|
||||
setShouldAutoOpenStartNodeSelector: mockSetShouldAutoOpenStartNodeSelector,
|
||||
getState: () => ({
|
||||
showOnboarding: false,
|
||||
hasShownOnboarding: false,
|
||||
notInitialWorkflow: false,
|
||||
setShowOnboarding: mockSetShowOnboarding,
|
||||
setHasShownOnboarding: mockSetHasShownOnboarding,
|
||||
hasSelectedStartNode: false,
|
||||
setHasSelectedStartNode: mockSetHasSelectedStartNode,
|
||||
setShouldAutoOpenStartNodeSelector: mockSetShouldAutoOpenStartNodeSelector,
|
||||
}),
|
||||
})
|
||||
|
||||
|
|
@ -526,12 +554,19 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
notInitialWorkflow: false,
|
||||
setShowOnboarding: mockSetShowOnboarding,
|
||||
setHasShownOnboarding: mockSetHasShownOnboarding,
|
||||
hasSelectedStartNode: false,
|
||||
setHasSelectedStartNode: mockSetHasSelectedStartNode,
|
||||
shouldAutoOpenStartNodeSelector: false,
|
||||
setShouldAutoOpenStartNodeSelector: mockSetShouldAutoOpenStartNodeSelector,
|
||||
getState: () => ({
|
||||
showOnboarding: false,
|
||||
hasShownOnboarding: true,
|
||||
notInitialWorkflow: false,
|
||||
setShowOnboarding: mockSetShowOnboarding,
|
||||
setHasShownOnboarding: mockSetHasShownOnboarding,
|
||||
hasSelectedStartNode: false,
|
||||
setHasSelectedStartNode: mockSetHasSelectedStartNode,
|
||||
setShouldAutoOpenStartNodeSelector: mockSetShouldAutoOpenStartNodeSelector,
|
||||
}),
|
||||
})
|
||||
|
||||
|
|
@ -553,12 +588,19 @@ describe('Workflow Onboarding Integration Logic', () => {
|
|||
notInitialWorkflow: true, // Initial workflow creation
|
||||
setShowOnboarding: mockSetShowOnboarding,
|
||||
setHasShownOnboarding: mockSetHasShownOnboarding,
|
||||
hasSelectedStartNode: false,
|
||||
setHasSelectedStartNode: mockSetHasSelectedStartNode,
|
||||
shouldAutoOpenStartNodeSelector: false,
|
||||
setShouldAutoOpenStartNodeSelector: mockSetShouldAutoOpenStartNodeSelector,
|
||||
getState: () => ({
|
||||
showOnboarding: false,
|
||||
hasShownOnboarding: false,
|
||||
notInitialWorkflow: true,
|
||||
setShowOnboarding: mockSetShowOnboarding,
|
||||
setHasShownOnboarding: mockSetHasShownOnboarding,
|
||||
hasSelectedStartNode: false,
|
||||
setHasSelectedStartNode: mockSetHasSelectedStartNode,
|
||||
setShouldAutoOpenStartNodeSelector: mockSetShouldAutoOpenStartNodeSelector,
|
||||
}),
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,10 @@ export const usePipelineInit = () => {
|
|||
if (error && error.json && !error.bodyUsed && datasetId) {
|
||||
error.json().then((err: any) => {
|
||||
if (err.code === 'draft_workflow_not_exist') {
|
||||
workflowStore.setState({ notInitialWorkflow: true })
|
||||
workflowStore.setState({
|
||||
notInitialWorkflow: true,
|
||||
shouldAutoOpenStartNodeSelector: true,
|
||||
})
|
||||
syncWorkflowDraft({
|
||||
url: `/rag/pipelines/${datasetId}/workflows/draft`,
|
||||
params: {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ const WorkflowChildren = () => {
|
|||
const showOnboarding = useStore(s => s.showOnboarding)
|
||||
const setShowOnboarding = useStore(s => s.setShowOnboarding)
|
||||
const setHasSelectedStartNode = useStore(s => s.setHasSelectedStartNode)
|
||||
const setShouldAutoOpenStartNodeSelector = useStore(s => s.setShouldAutoOpenStartNodeSelector)
|
||||
const reactFlowStore = useStoreApi()
|
||||
const availableNodesMetaData = useAvailableNodesMetaData()
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
|
|
@ -142,6 +143,7 @@ const WorkflowChildren = () => {
|
|||
|
||||
setShowOnboarding?.(false)
|
||||
setHasSelectedStartNode?.(true)
|
||||
setShouldAutoOpenStartNodeSelector?.(true)
|
||||
|
||||
handleSyncWorkflowDraft(true, false, {
|
||||
onSuccess: () => {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export const useAutoOnboarding = () => {
|
|||
notInitialWorkflow,
|
||||
setShowOnboarding,
|
||||
setHasShownOnboarding,
|
||||
setShouldAutoOpenStartNodeSelector,
|
||||
} = workflowStore.getState()
|
||||
|
||||
// Skip if already showing onboarding or it's the initial workflow creation
|
||||
|
|
@ -30,13 +31,24 @@ export const useAutoOnboarding = () => {
|
|||
if (isCompletelyEmpty && !hasShownOnboarding) {
|
||||
setShowOnboarding?.(true)
|
||||
setHasShownOnboarding?.(true)
|
||||
setShouldAutoOpenStartNodeSelector?.(true)
|
||||
}
|
||||
}, [store, workflowStore])
|
||||
|
||||
const handleOnboardingClose = useCallback(() => {
|
||||
const { setShowOnboarding, setHasShownOnboarding } = workflowStore.getState()
|
||||
const {
|
||||
setShowOnboarding,
|
||||
setHasShownOnboarding,
|
||||
setShouldAutoOpenStartNodeSelector,
|
||||
hasSelectedStartNode,
|
||||
setHasSelectedStartNode,
|
||||
} = workflowStore.getState()
|
||||
setShowOnboarding?.(false)
|
||||
setHasShownOnboarding?.(true)
|
||||
if (hasSelectedStartNode)
|
||||
setHasSelectedStartNode?.(false)
|
||||
else
|
||||
setShouldAutoOpenStartNodeSelector?.(false)
|
||||
}, [workflowStore])
|
||||
|
||||
// Check on mount and when nodes change
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ export const useWorkflowInit = () => {
|
|||
workflowStore.setState({
|
||||
notInitialWorkflow: true,
|
||||
showOnboarding: !isAdvancedChat,
|
||||
shouldAutoOpenStartNodeSelector: !isAdvancedChat,
|
||||
hasShownOnboarding: false,
|
||||
})
|
||||
const nodesData = isAdvancedChat ? nodesTemplate : []
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ export type WorkflowSliceShape = {
|
|||
appName: string
|
||||
notInitialWorkflow: boolean
|
||||
setNotInitialWorkflow: (notInitialWorkflow: boolean) => void
|
||||
shouldAutoOpenStartNodeSelector: boolean
|
||||
setShouldAutoOpenStartNodeSelector: (shouldAutoOpen: boolean) => void
|
||||
nodesDefaultConfigs: Record<string, any>
|
||||
setNodesDefaultConfigs: (nodesDefaultConfigs: Record<string, any>) => void
|
||||
showOnboarding: boolean
|
||||
|
|
@ -21,6 +23,8 @@ export const createWorkflowSlice: StateCreator<WorkflowSliceShape> = set => ({
|
|||
appName: '',
|
||||
notInitialWorkflow: false,
|
||||
setNotInitialWorkflow: notInitialWorkflow => set(() => ({ notInitialWorkflow })),
|
||||
shouldAutoOpenStartNodeSelector: false,
|
||||
setShouldAutoOpenStartNodeSelector: shouldAutoOpenStartNodeSelector => set(() => ({ shouldAutoOpenStartNodeSelector })),
|
||||
nodesDefaultConfigs: {},
|
||||
setNodesDefaultConfigs: nodesDefaultConfigs => set(() => ({ nodesDefaultConfigs })),
|
||||
showOnboarding: false,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import {
|
|||
} from '../../../hooks'
|
||||
import {
|
||||
useStore,
|
||||
useWorkflowStore,
|
||||
} from '../../../store'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
|
|
@ -127,7 +128,10 @@ export const NodeSourceHandle = memo(({
|
|||
showExceptionStatus,
|
||||
}: NodeHandleProps) => {
|
||||
const { t } = useTranslation()
|
||||
const notInitialWorkflow = useStore(s => s.notInitialWorkflow)
|
||||
const shouldAutoOpenStartNodeSelector = useStore(s => s.shouldAutoOpenStartNodeSelector)
|
||||
const setShouldAutoOpenStartNodeSelector = useStore(s => s.setShouldAutoOpenStartNodeSelector)
|
||||
const setHasSelectedStartNode = useStore(s => s.setHasSelectedStartNode)
|
||||
const workflowStoreApi = useWorkflowStore()
|
||||
const [open, setOpen] = useState(false)
|
||||
const { handleNodeAdd } = useNodesInteractions()
|
||||
const { getNodesReadOnly } = useNodesReadOnly()
|
||||
|
|
@ -157,9 +161,27 @@ export const NodeSourceHandle = memo(({
|
|||
}, [handleNodeAdd, id, handleId])
|
||||
|
||||
useEffect(() => {
|
||||
if (notInitialWorkflow && (data.type === BlockEnum.Start || data.type === BlockEnum.TriggerSchedule || data.type === BlockEnum.TriggerWebhook || data.type === BlockEnum.TriggerPlugin) && !isChatMode)
|
||||
if (!shouldAutoOpenStartNodeSelector)
|
||||
return
|
||||
|
||||
if (isChatMode) {
|
||||
setShouldAutoOpenStartNodeSelector?.(false)
|
||||
return
|
||||
}
|
||||
|
||||
if (data.type === BlockEnum.Start || data.type === BlockEnum.TriggerSchedule || data.type === BlockEnum.TriggerWebhook || data.type === BlockEnum.TriggerPlugin) {
|
||||
setOpen(true)
|
||||
}, [notInitialWorkflow, data.type, isChatMode])
|
||||
if (setShouldAutoOpenStartNodeSelector)
|
||||
setShouldAutoOpenStartNodeSelector(false)
|
||||
else
|
||||
workflowStoreApi?.setState?.({ shouldAutoOpenStartNodeSelector: false })
|
||||
|
||||
if (setHasSelectedStartNode)
|
||||
setHasSelectedStartNode(false)
|
||||
else
|
||||
workflowStoreApi?.setState?.({ hasSelectedStartNode: false })
|
||||
}
|
||||
}, [shouldAutoOpenStartNodeSelector, data.type, isChatMode, setShouldAutoOpenStartNodeSelector, setHasSelectedStartNode, workflowStoreApi])
|
||||
|
||||
return (
|
||||
<Handle
|
||||
|
|
|
|||
Loading…
Reference in New Issue