mirror of https://github.com/langgenius/dify.git
useStore to isListening status
This commit is contained in:
parent
d72a3e1879
commit
fd2f0df097
|
|
@ -215,21 +215,24 @@ export const useWorkflowRun = () => {
|
|||
|
||||
const {
|
||||
setWorkflowRunningData,
|
||||
setIsListening,
|
||||
} = workflowStore.getState()
|
||||
|
||||
if (runMode === 'webhook') {
|
||||
setIsListening(true)
|
||||
setWorkflowRunningData({
|
||||
result: {
|
||||
status: WorkflowRunningStatus.Listening,
|
||||
status: WorkflowRunningStatus.Running,
|
||||
inputs_truncated: false,
|
||||
process_data_truncated: false,
|
||||
outputs_truncated: false,
|
||||
},
|
||||
tracing: [],
|
||||
resultText: 'Listening for webhook call...',
|
||||
resultText: '',
|
||||
})
|
||||
}
|
||||
else {
|
||||
setIsListening(false)
|
||||
setWorkflowRunningData({
|
||||
result: {
|
||||
status: WorkflowRunningStatus.Running,
|
||||
|
|
@ -260,9 +263,15 @@ export const useWorkflowRun = () => {
|
|||
abortControllerRef.current = null
|
||||
}
|
||||
|
||||
const clearListeningState = () => {
|
||||
const state = workflowStore.getState()
|
||||
state.setIsListening(false)
|
||||
}
|
||||
|
||||
const wrappedOnError = (params: any) => {
|
||||
clearAbortController()
|
||||
handleWorkflowFailed()
|
||||
clearListeningState()
|
||||
|
||||
if (onError)
|
||||
onError(params)
|
||||
|
|
@ -270,6 +279,7 @@ export const useWorkflowRun = () => {
|
|||
|
||||
const wrappedOnCompleted: IOtherOptions['onCompleted'] = async (hasError?: boolean, errorMessage?: string) => {
|
||||
clearAbortController()
|
||||
clearListeningState()
|
||||
if (onCompleted)
|
||||
onCompleted(hasError, errorMessage)
|
||||
}
|
||||
|
|
@ -289,6 +299,7 @@ export const useWorkflowRun = () => {
|
|||
onWorkflowStarted(params)
|
||||
},
|
||||
onWorkflowFinished: (params) => {
|
||||
clearListeningState()
|
||||
handleWorkflowFinished(params)
|
||||
|
||||
if (onWorkflowFinished)
|
||||
|
|
@ -468,9 +479,11 @@ export const useWorkflowRun = () => {
|
|||
},
|
||||
tracing: [],
|
||||
})
|
||||
setIsListening(false)
|
||||
return
|
||||
}
|
||||
|
||||
setIsListening(false)
|
||||
handleStream(
|
||||
response,
|
||||
baseSseOptions.onData ?? noop,
|
||||
|
|
@ -518,6 +531,7 @@ export const useWorkflowRun = () => {
|
|||
},
|
||||
tracing: [],
|
||||
})
|
||||
setIsListening(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -561,7 +575,7 @@ export const useWorkflowRun = () => {
|
|||
abortControllerRef.current.abort()
|
||||
|
||||
abortControllerRef.current = null
|
||||
const { setWorkflowRunningData } = workflowStore.getState()
|
||||
const { setWorkflowRunningData, setIsListening } = workflowStore.getState()
|
||||
setWorkflowRunningData({
|
||||
result: {
|
||||
status: WorkflowRunningStatus.Stopped,
|
||||
|
|
@ -572,6 +586,7 @@ export const useWorkflowRun = () => {
|
|||
tracing: [],
|
||||
resultText: '',
|
||||
})
|
||||
setIsListening(false)
|
||||
}, [workflowStore])
|
||||
|
||||
const handleRestoreFromPublishedWorkflow = useCallback((publishedWorkflow: VersionHistory) => {
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ const RunMode = ({
|
|||
const { handleStopRun } = useWorkflowRun()
|
||||
const { validateBeforeRun } = useWorkflowRunValidation()
|
||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||
const isListening = useStore(s => s.isListening)
|
||||
|
||||
const status = workflowRunningData?.result.status
|
||||
const isListening = status === WorkflowRunningStatus.Listening
|
||||
const isRunning = status === WorkflowRunningStatus.Running || isListening
|
||||
|
||||
const dynamicOptions = useDynamicTestRunOptions()
|
||||
|
|
|
|||
|
|
@ -5,11 +5,9 @@ import { useStore } from '../store'
|
|||
import { useWorkflowUpdate } from '../hooks'
|
||||
import { useHooksStore } from '../hooks-store'
|
||||
import { formatWorkflowRunIdentifier } from '../utils'
|
||||
import { WorkflowRunningStatus } from '../types'
|
||||
|
||||
const Record = () => {
|
||||
const historyWorkflowData = useStore(s => s.historyWorkflowData)
|
||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||
const { handleUpdateWorkflowCanvas } = useWorkflowUpdate()
|
||||
const getWorkflowRunAndTraceUrl = useHooksStore(s => s.getWorkflowRunAndTraceUrl)
|
||||
|
||||
|
|
@ -22,9 +20,6 @@ const Record = () => {
|
|||
})
|
||||
}, [handleUpdateWorkflowCanvas])
|
||||
|
||||
const currentStatus = workflowRunningData?.result.status
|
||||
const activeTab = currentStatus === WorkflowRunningStatus.Listening ? 'DETAIL' : undefined
|
||||
|
||||
return (
|
||||
<div className='flex h-full w-[400px] flex-col rounded-l-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xl'>
|
||||
<div className='system-xl-semibold flex items-center justify-between p-4 pb-0 text-text-primary'>
|
||||
|
|
@ -34,8 +29,6 @@ const Record = () => {
|
|||
runDetailUrl={getWorkflowRunAndTraceUrl(historyWorkflowData?.id).runUrl}
|
||||
tracingListUrl={getWorkflowRunAndTraceUrl(historyWorkflowData?.id).traceUrl}
|
||||
getResultCallback={handleResultCallback}
|
||||
activeTab={activeTab}
|
||||
statusHint={currentStatus}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ const WorkflowPreview = () => {
|
|||
const { t } = useTranslation()
|
||||
const { handleCancelDebugAndPreviewPanel } = useWorkflowInteractions()
|
||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||
const isListening = useStore(s => s.isListening)
|
||||
const showInputsPanel = useStore(s => s.showInputsPanel)
|
||||
const workflowCanvasWidth = useStore(s => s.workflowCanvasWidth)
|
||||
const panelWidth = useStore(s => s.previewPanelWidth)
|
||||
|
|
@ -47,16 +48,16 @@ const WorkflowPreview = () => {
|
|||
setCurrentTab('INPUT')
|
||||
}, [showDebugAndPreviewPanel, showInputsPanel])
|
||||
|
||||
useEffect(() => {
|
||||
if (isListening)
|
||||
switchTab('DETAIL')
|
||||
}, [isListening])
|
||||
|
||||
useEffect(() => {
|
||||
const status = workflowRunningData?.result.status
|
||||
if (!workflowRunningData)
|
||||
return
|
||||
|
||||
if (status === WorkflowRunningStatus.Listening) {
|
||||
switchTab('DETAIL')
|
||||
return
|
||||
}
|
||||
|
||||
if ((status === WorkflowRunningStatus.Succeeded || status === WorkflowRunningStatus.Failed) && !workflowRunningData.resultText && !workflowRunningData.result.files?.length)
|
||||
switchTab('DETAIL')
|
||||
}, [workflowRunningData])
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import OutputPanel from './output-panel'
|
||||
import ResultPanel from './result-panel'
|
||||
import StatusPanel from './status'
|
||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import TracingPanel from './tracing-panel'
|
||||
import cn from '@/utils/classnames'
|
||||
import { ToastContext } from '@/app/components/base/toast'
|
||||
|
|
@ -13,14 +14,14 @@ import Loading from '@/app/components/base/loading'
|
|||
import { fetchRunDetail, fetchTracingList } from '@/service/log'
|
||||
import type { NodeTracing } from '@/types/workflow'
|
||||
import type { WorkflowRunDetailResponse } from '@/models/log'
|
||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { useStore } from '../store'
|
||||
|
||||
export type RunProps = {
|
||||
hideResult?: boolean
|
||||
activeTab?: 'RESULT' | 'DETAIL' | 'TRACING'
|
||||
getResultCallback?: (result: WorkflowRunDetailResponse) => void
|
||||
runDetailUrl: string
|
||||
tracingListUrl: string
|
||||
statusHint?: string
|
||||
}
|
||||
|
||||
const RunPanel: FC<RunProps> = ({
|
||||
|
|
@ -29,7 +30,6 @@ const RunPanel: FC<RunProps> = ({
|
|||
getResultCallback,
|
||||
runDetailUrl,
|
||||
tracingListUrl,
|
||||
statusHint,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
|
|
@ -37,6 +37,7 @@ const RunPanel: FC<RunProps> = ({
|
|||
const [loading, setLoading] = useState<boolean>(true)
|
||||
const [runDetail, setRunDetail] = useState<WorkflowRunDetailResponse>()
|
||||
const [list, setList] = useState<NodeTracing[]>([])
|
||||
const isListening = useStore(s => s.isListening)
|
||||
|
||||
const executor = useMemo(() => {
|
||||
if (runDetail?.created_by_role === 'account')
|
||||
|
|
@ -90,19 +91,17 @@ const RunPanel: FC<RunProps> = ({
|
|||
tracingListUrl && await getTracingList()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isListening)
|
||||
setCurrentTab('DETAIL')
|
||||
}, [isListening])
|
||||
|
||||
useEffect(() => {
|
||||
// fetch data
|
||||
if (runDetailUrl && tracingListUrl)
|
||||
getData()
|
||||
}, [runDetailUrl, tracingListUrl])
|
||||
|
||||
const derivedStatus = runDetail?.status ?? statusHint
|
||||
|
||||
useEffect(() => {
|
||||
if (derivedStatus === WorkflowRunningStatus.Listening && currentTab !== 'DETAIL')
|
||||
setCurrentTab('DETAIL')
|
||||
}, [currentTab, derivedStatus])
|
||||
|
||||
const [height, setHeight] = useState(0)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
|
||||
|
|
@ -174,9 +173,9 @@ const RunPanel: FC<RunProps> = ({
|
|||
exceptionCounts={runDetail.exceptions_count}
|
||||
/>
|
||||
)}
|
||||
{!loading && currentTab === 'DETAIL' && !runDetail && derivedStatus === WorkflowRunningStatus.Listening && (
|
||||
{!loading && currentTab === 'DETAIL' && !runDetail && isListening && (
|
||||
<StatusPanel
|
||||
status={WorkflowRunningStatus.Listening}
|
||||
status={WorkflowRunningStatus.Running}
|
||||
/>
|
||||
)}
|
||||
{!loading && currentTab === 'TRACING' && (
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ const StatusContainer: FC<Props> = ({
|
|||
children,
|
||||
}) => {
|
||||
const { theme } = useTheme()
|
||||
const isActive = status === 'running' || status === 'listening'
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -35,9 +34,9 @@ const StatusContainer: FC<Props> = ({
|
|||
status === 'exception' && 'border-[rgba(247,144,9,0.8)] bg-workflow-display-warning-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-warning.svg)] text-text-destructive',
|
||||
status === 'exception' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(247,144,9,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
|
||||
status === 'exception' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(247,144,9,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
|
||||
isActive && 'border-[rgba(11,165,236,0.8)] bg-workflow-display-normal-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-running.svg)] text-util-colors-blue-light-blue-light-600',
|
||||
isActive && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(11,165,236,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
|
||||
isActive && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(11,165,236,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
|
||||
status === 'running' && 'border-[rgba(11,165,236,0.8)] bg-workflow-display-normal-bg bg-[url(~@/app/components/workflow/run/assets/bg-line-running.svg)] text-util-colors-blue-light-blue-light-600',
|
||||
status === 'running' && theme === Theme.light && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.5),inset_0_1px_3px_0_rgba(0,0,0,0.12),inset_0_2px_24px_0_rgba(11,165,236,0.2),0_1px_2px_0_rgba(9,9,11,0.05),0_0_0_1px_rgba(0,0,0,0.05)]',
|
||||
status === 'running' && theme === Theme.dark && 'shadow-[inset_2px_2px_0_0_rgba(255,255,255,0.12),inset_0_1px_3px_0_rgba(0,0,0,0.4),inset_0_2px_24px_0_rgba(11,165,236,0.25),0_1px_2px_0_rgba(0,0,0,0.1),0_0_0_1px_rgba(24, 24, 27, 0.95)]',
|
||||
)}
|
||||
>
|
||||
<div className={cn(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import cn from '@/utils/classnames'
|
|||
import Indicator from '@/app/components/header/indicator'
|
||||
import StatusContainer from '@/app/components/workflow/run/status-container'
|
||||
import { useDocLink } from '@/context/i18n'
|
||||
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
|
||||
import { useStore } from '../store'
|
||||
|
||||
type ResultProps = {
|
||||
status: string
|
||||
|
|
@ -24,7 +24,35 @@ const StatusPanel: FC<ResultProps> = ({
|
|||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const docLink = useDocLink()
|
||||
const isActive = status === WorkflowRunningStatus.Running || status === WorkflowRunningStatus.Listening
|
||||
const isListening = useStore(s => s.isListening)
|
||||
|
||||
if (isListening) {
|
||||
return (
|
||||
<StatusContainer status={'running'}>
|
||||
<div className='flex'>
|
||||
<div className='max-w-[120px] flex-[33%]'>
|
||||
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.status')}</div>
|
||||
<div className='system-xs-semibold-uppercase flex items-center gap-1 text-util-colors-blue-light-blue-light-600'>
|
||||
<Indicator color='blue' />
|
||||
<span>LISTENING</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className='max-w-[152px] flex-[33%]'>
|
||||
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.time')}</div>
|
||||
<div className='system-sm-medium flex items-center gap-1 text-text-secondary'>
|
||||
<div className='h-2 w-16 rounded-sm bg-text-quaternary' />
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex-[33%]'>
|
||||
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.tokens')}</div>
|
||||
<div className='system-sm-medium flex items-center gap-1 text-text-secondary'>
|
||||
<div className='h-2 w-20 rounded-sm bg-text-quaternary' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</StatusContainer>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<StatusContainer status={status}>
|
||||
|
|
@ -41,21 +69,15 @@ const StatusPanel: FC<ResultProps> = ({
|
|||
status === 'partial-succeeded' && 'text-util-colors-green-green-600',
|
||||
status === 'failed' && 'text-util-colors-red-red-600',
|
||||
status === 'stopped' && 'text-util-colors-warning-warning-600',
|
||||
isActive && 'text-util-colors-blue-light-blue-light-600',
|
||||
status === 'running' && 'text-util-colors-blue-light-blue-light-600',
|
||||
)}
|
||||
>
|
||||
{status === WorkflowRunningStatus.Running && (
|
||||
{status === 'running' && (
|
||||
<>
|
||||
<Indicator color={'blue'} />
|
||||
<span>Running</span>
|
||||
</>
|
||||
)}
|
||||
{status === WorkflowRunningStatus.Listening && (
|
||||
<>
|
||||
<Indicator color={'blue'} />
|
||||
<span>Listening</span>
|
||||
</>
|
||||
)}
|
||||
{status === 'succeeded' && (
|
||||
<>
|
||||
<Indicator color={'green'} />
|
||||
|
|
@ -91,10 +113,10 @@ const StatusPanel: FC<ResultProps> = ({
|
|||
<div className='max-w-[152px] flex-[33%]'>
|
||||
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.time')}</div>
|
||||
<div className='system-sm-medium flex items-center gap-1 text-text-secondary'>
|
||||
{isActive && (
|
||||
{status === 'running' && (
|
||||
<div className='h-2 w-16 rounded-sm bg-text-quaternary' />
|
||||
)}
|
||||
{!isActive && (
|
||||
{status !== 'running' && (
|
||||
<span>{time ? `${time?.toFixed(3)}s` : '-'}</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -102,10 +124,10 @@ const StatusPanel: FC<ResultProps> = ({
|
|||
<div className='flex-[33%]'>
|
||||
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t('runLog.resultPanel.tokens')}</div>
|
||||
<div className='system-sm-medium flex items-center gap-1 text-text-secondary'>
|
||||
{isActive && (
|
||||
{status === 'running' && (
|
||||
<div className='h-2 w-20 rounded-sm bg-text-quaternary' />
|
||||
)}
|
||||
{!isActive && (
|
||||
{status !== 'running' && (
|
||||
<span>{`${tokens || 0} Tokens`}</span>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ type PreviewRunningData = WorkflowRunningData & {
|
|||
export type WorkflowSliceShape = {
|
||||
workflowRunningData?: PreviewRunningData
|
||||
setWorkflowRunningData: (workflowData: PreviewRunningData) => void
|
||||
isListening: boolean
|
||||
setIsListening: (listening: boolean) => void
|
||||
clipboardElements: Node[]
|
||||
setClipboardElements: (clipboardElements: Node[]) => void
|
||||
selection: null | { x1: number; y1: number; x2: number; y2: number }
|
||||
|
|
@ -36,6 +38,8 @@ export type WorkflowSliceShape = {
|
|||
export const createWorkflowSlice: StateCreator<WorkflowSliceShape> = set => ({
|
||||
workflowRunningData: undefined,
|
||||
setWorkflowRunningData: workflowRunningData => set(() => ({ workflowRunningData })),
|
||||
isListening: false,
|
||||
setIsListening: listening => set(() => ({ isListening: listening })),
|
||||
clipboardElements: [],
|
||||
setClipboardElements: clipboardElements => set(() => ({ clipboardElements })),
|
||||
selection: null,
|
||||
|
|
|
|||
|
|
@ -344,7 +344,6 @@ export type NodeDefault<T = {}> = {
|
|||
export type OnSelectBlock = (type: BlockEnum, pluginDefaultValue?: PluginDefaultValue) => void
|
||||
|
||||
export enum WorkflowRunningStatus {
|
||||
Listening = 'listening',
|
||||
Waiting = 'waiting',
|
||||
Running = 'running',
|
||||
Succeeded = 'succeeded',
|
||||
|
|
|
|||
Loading…
Reference in New Issue