mirror of https://github.com/langgenius/dify.git
run history
This commit is contained in:
parent
17f572f23f
commit
94ca0edb68
|
|
@ -30,6 +30,7 @@ const Header: FC = () => {
|
|||
const appSidebarExpand = useAppStore(s => s.appSidebarExpand)
|
||||
const {
|
||||
nodesReadOnly,
|
||||
getNodesReadOnly,
|
||||
} = useNodesReadOnly()
|
||||
const isRestoring = useStore(s => s.isRestoring)
|
||||
const {
|
||||
|
|
@ -39,8 +40,15 @@ const Header: FC = () => {
|
|||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
|
||||
const handleShowFeatures = useCallback(() => {
|
||||
workflowStore.setState({ showFeaturesPanel: true })
|
||||
}, [workflowStore])
|
||||
const {
|
||||
isRestoring,
|
||||
setShowFeaturesPanel,
|
||||
} = workflowStore.getState()
|
||||
if (getNodesReadOnly() && !isRestoring)
|
||||
return
|
||||
|
||||
setShowFeaturesPanel(true)
|
||||
}, [workflowStore, getNodesReadOnly])
|
||||
|
||||
const handleGoBackToEdit = useCallback(() => {
|
||||
handleRunSetting(true)
|
||||
|
|
@ -102,6 +110,7 @@ const Header: FC = () => {
|
|||
className={`
|
||||
mr-2 px-3 py-0 h-8 bg-white text-[13px] font-medium text-gray-700
|
||||
border-[0.5px] border-gray-200 shadow-xs
|
||||
${nodesReadOnly && !isRestoring && 'opacity-50 !cursor-not-allowed'}
|
||||
`}
|
||||
onClick={handleShowFeatures}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { FC } from 'react'
|
||||
import { memo } from 'react'
|
||||
import { memo, useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStoreApi } from 'reactflow'
|
||||
import {
|
||||
useStore,
|
||||
useWorkflowStore,
|
||||
|
|
@ -11,7 +12,10 @@ import {
|
|||
useNodesSyncDraft,
|
||||
useWorkflowRun,
|
||||
} from '../hooks'
|
||||
import { WorkflowRunningStatus } from '../types'
|
||||
import {
|
||||
BlockEnum,
|
||||
WorkflowRunningStatus,
|
||||
} from '../types'
|
||||
import {
|
||||
Play,
|
||||
StopCircle,
|
||||
|
|
@ -20,20 +24,59 @@ import { ClockPlay } from '@/app/components/base/icons/src/vender/line/time'
|
|||
import TooltipPlus from '@/app/components/base/tooltip-plus'
|
||||
import { Loading02 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
|
||||
const RunMode = memo(() => {
|
||||
const { t } = useTranslation()
|
||||
const store = useStoreApi()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { handleStopRun } = useWorkflowRun()
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const featuresStore = useFeaturesStore()
|
||||
const {
|
||||
handleStopRun,
|
||||
handleRunSetting,
|
||||
handleRun,
|
||||
} = useWorkflowRun()
|
||||
const {
|
||||
doSyncWorkflowDraft,
|
||||
handleSyncWorkflowDraft,
|
||||
} = useNodesSyncDraft()
|
||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||
const showInputsPanel = useStore(s => s.showInputsPanel)
|
||||
const isRunning = workflowRunningData?.result.status === WorkflowRunningStatus.Running
|
||||
|
||||
const handleClick = () => {
|
||||
workflowStore.setState({ showInputsPanel: true })
|
||||
handleSyncWorkflowDraft(true)
|
||||
}
|
||||
const handleClick = useCallback(async () => {
|
||||
const {
|
||||
setShowInputsPanel,
|
||||
workflowRunningData,
|
||||
} = workflowStore.getState()
|
||||
|
||||
if (workflowRunningData?.result.status === WorkflowRunningStatus.Running)
|
||||
return
|
||||
|
||||
const { getNodes } = store.getState()
|
||||
const nodes = getNodes()
|
||||
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
|
||||
const startVariables = startNode?.data.variables || []
|
||||
const fileSettings = featuresStore!.getState().features.file
|
||||
|
||||
if (!startVariables.length && !fileSettings.image.enabled) {
|
||||
await doSyncWorkflowDraft()
|
||||
handleRunSetting()
|
||||
handleRun({ inputs: {}, files: [] })
|
||||
}
|
||||
else {
|
||||
setShowInputsPanel(true)
|
||||
handleSyncWorkflowDraft(true)
|
||||
}
|
||||
}, [
|
||||
workflowStore,
|
||||
handleSyncWorkflowDraft,
|
||||
handleRunSetting,
|
||||
handleRun,
|
||||
doSyncWorkflowDraft,
|
||||
store,
|
||||
featuresStore,
|
||||
])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -44,7 +87,7 @@ const RunMode = memo(() => {
|
|||
${showInputsPanel && 'bg-primary-50'}
|
||||
${isRunning && 'bg-primary-50 !cursor-not-allowed'}
|
||||
`}
|
||||
onClick={() => !isRunning && handleClick()}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{
|
||||
isRunning
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export const useNodesSyncDraft = () => {
|
|||
const { getNodesReadOnly } = useNodesReadOnly()
|
||||
const debouncedSyncWorkflowDraft = useStore(s => s.debouncedSyncWorkflowDraft)
|
||||
|
||||
const doSyncWorkflowDraft = useCallback(() => {
|
||||
const doSyncWorkflowDraft = useCallback(async () => {
|
||||
const {
|
||||
getNodes,
|
||||
edges,
|
||||
|
|
@ -90,6 +90,7 @@ export const useNodesSyncDraft = () => {
|
|||
}, [debouncedSyncWorkflowDraft, doSyncWorkflowDraft, getNodesReadOnly])
|
||||
|
||||
return {
|
||||
doSyncWorkflowDraft,
|
||||
handleSyncWorkflowDraft,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,19 +36,22 @@ export const useWorkflowRun = () => {
|
|||
const handleBackupDraft = useCallback(() => {
|
||||
const {
|
||||
getNodes,
|
||||
getEdges,
|
||||
getViewport,
|
||||
} = reactflow
|
||||
edges,
|
||||
} = store.getState()
|
||||
const { getViewport } = reactflow
|
||||
const {
|
||||
backupDraft,
|
||||
setBackupDraft,
|
||||
} = workflowStore.getState()
|
||||
|
||||
setBackupDraft({
|
||||
nodes: getNodes(),
|
||||
edges: getEdges(),
|
||||
viewport: getViewport(),
|
||||
})
|
||||
}, [reactflow, workflowStore])
|
||||
if (!backupDraft) {
|
||||
setBackupDraft({
|
||||
nodes: getNodes(),
|
||||
edges,
|
||||
viewport: getViewport(),
|
||||
})
|
||||
}
|
||||
}, [reactflow, workflowStore, store])
|
||||
|
||||
const handleLoadBackupDraft = useCallback(() => {
|
||||
const {
|
||||
|
|
@ -56,7 +59,10 @@ export const useWorkflowRun = () => {
|
|||
setEdges,
|
||||
} = store.getState()
|
||||
const { setViewport } = reactflow
|
||||
const { backupDraft } = workflowStore.getState()
|
||||
const {
|
||||
backupDraft,
|
||||
setBackupDraft,
|
||||
} = workflowStore.getState()
|
||||
|
||||
if (backupDraft) {
|
||||
const {
|
||||
|
|
@ -67,6 +73,8 @@ export const useWorkflowRun = () => {
|
|||
setNodes(nodes)
|
||||
setEdges(edges)
|
||||
setViewport(viewport)
|
||||
|
||||
setBackupDraft(undefined)
|
||||
}
|
||||
}, [store, reactflow, workflowStore])
|
||||
|
||||
|
|
|
|||
|
|
@ -13,13 +13,21 @@ import {
|
|||
useReactFlow,
|
||||
useStoreApi,
|
||||
} from 'reactflow'
|
||||
import type { Connection } from 'reactflow'
|
||||
import type {
|
||||
Connection,
|
||||
Viewport,
|
||||
} from 'reactflow'
|
||||
import type { ToolsMap } from '../block-selector/types'
|
||||
import {
|
||||
generateNewNode,
|
||||
getLayoutByDagre,
|
||||
initialEdges,
|
||||
initialNodes,
|
||||
} from '../utils'
|
||||
import type { Node } from '../types'
|
||||
import type {
|
||||
Edge,
|
||||
Node,
|
||||
} from '../types'
|
||||
import {
|
||||
BlockEnum,
|
||||
WorkflowRunningStatus,
|
||||
|
|
@ -270,6 +278,17 @@ export const useWorkflow = () => {
|
|||
}
|
||||
}, [store])
|
||||
|
||||
const renderTreeFromRecord = useCallback((nodes: Node[], edges: Edge[], viewport?: Viewport) => {
|
||||
const { setNodes } = store.getState()
|
||||
const { setViewport, setEdges } = reactflow
|
||||
|
||||
setNodes(initialNodes(nodes, edges))
|
||||
setEdges(initialEdges(edges, nodes))
|
||||
|
||||
if (viewport)
|
||||
setViewport(viewport)
|
||||
}, [store, reactflow])
|
||||
|
||||
return {
|
||||
handleLayout,
|
||||
getTreeLeafNodes,
|
||||
|
|
@ -278,6 +297,7 @@ export const useWorkflow = () => {
|
|||
isValidConnection,
|
||||
formatTimeFromNow,
|
||||
getValidTreeNodes,
|
||||
renderTreeFromRecord,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,24 @@
|
|||
import { memo } from 'react'
|
||||
import { useIsChatMode } from '../hooks'
|
||||
import { memo, useCallback } from 'react'
|
||||
import {
|
||||
useIsChatMode,
|
||||
useWorkflow,
|
||||
} from '../hooks'
|
||||
import Run from '../run'
|
||||
import { useStore } from '../store'
|
||||
import ChatRecord from './chat-record'
|
||||
import type { WorkflowRunDetailResponse } from '@/models/log'
|
||||
|
||||
const Record = () => {
|
||||
const isChatMode = useIsChatMode()
|
||||
const { renderTreeFromRecord } = useWorkflow()
|
||||
const historyWorkflowData = useStore(s => s.historyWorkflowData)
|
||||
|
||||
const getResultCallback = useCallback((res: WorkflowRunDetailResponse) => {
|
||||
const { graph } = res
|
||||
|
||||
renderTreeFromRecord(graph.nodes, graph.edges, graph.viewport)
|
||||
}, [renderTreeFromRecord])
|
||||
|
||||
return (
|
||||
<div className={`
|
||||
flex flex-col h-full rounded-2xl border-[0.5px] border-gray-200 shadow-xl bg-white
|
||||
|
|
@ -19,7 +30,12 @@ const Record = () => {
|
|||
{
|
||||
isChatMode
|
||||
? <ChatRecord />
|
||||
: <Run runID={historyWorkflowData?.id || ''} />
|
||||
: (
|
||||
<Run
|
||||
runID={historyWorkflowData?.id || ''}
|
||||
getResultCallback={getResultCallback}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@ import { useStore as useAppStore } from '@/app/components/app/store'
|
|||
export type RunProps = {
|
||||
activeTab?: 'RESULT' | 'TRACING'
|
||||
runID: string
|
||||
getResultCallback?: (result: WorkflowRunDetailResponse) => void
|
||||
}
|
||||
|
||||
const RunPanel: FC<RunProps> = ({ activeTab = 'RESULT', runID }) => {
|
||||
const RunPanel: FC<RunProps> = ({ activeTab = 'RESULT', runID, getResultCallback }) => {
|
||||
const { t } = useTranslation()
|
||||
const { notify } = useContext(ToastContext)
|
||||
const [currentTab, setCurrentTab] = useState<string>(activeTab)
|
||||
|
|
@ -42,6 +43,8 @@ const RunPanel: FC<RunProps> = ({ activeTab = 'RESULT', runID }) => {
|
|||
runID,
|
||||
})
|
||||
setRunDetail(res)
|
||||
if (getResultCallback)
|
||||
getResultCallback(res)
|
||||
}
|
||||
catch (err) {
|
||||
notify({
|
||||
|
|
@ -49,7 +52,7 @@ const RunPanel: FC<RunProps> = ({ activeTab = 'RESULT', runID }) => {
|
|||
message: `${err}`,
|
||||
})
|
||||
}
|
||||
}, [notify])
|
||||
}, [notify, getResultCallback])
|
||||
|
||||
const getTracingList = useCallback(async (appID: string, runID: string) => {
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in New Issue