Merge remote-tracking branch 'origin/feat/workflow' into feat/workflow

This commit is contained in:
jyong 2024-03-29 19:44:35 +08:00
commit a647698c32
7 changed files with 194 additions and 182 deletions

View File

@ -78,7 +78,7 @@ const WorkflowChecklist = () => {
placement='bottom-end'
offset={{
mainAxis: 12,
crossAxis: -4,
crossAxis: 4,
}}
open={open}
onOpenChange={setOpen}
@ -174,7 +174,7 @@ const WorkflowChecklist = () => {
}
{
!needWarningNodes.length && (
<div className='mx-4 mb-3 py-4 rounded-lg bg-gray-50 text-gray-400 text-center'>
<div className='mx-4 mb-3 py-4 rounded-lg bg-gray-50 text-gray-400 text-xs text-center'>
<ChecklistSquare className='mx-auto mb-[5px] w-8 h-8 text-gray-300' />
{t('workflow.panel.checklistResolved')}
</div>

View File

@ -16,14 +16,12 @@ import {
BlockEnum,
WorkflowRunningStatus,
} from '../types'
import ViewHistory from './view-history'
import {
Play,
StopCircle,
} from '@/app/components/base/icons/src/vender/line/mediaAndDevices'
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(() => {
@ -160,11 +158,7 @@ const PreviewMode = memo(() => {
PreviewMode.displayName = 'PreviewMode'
const RunAndHistory: FC = () => {
const { t } = useTranslation()
const { setCurrentLogItem, setShowMessageLogModal } = useAppStore()
const workflowStore = useWorkflowStore()
const isChatMode = useIsChatMode()
const showRunHistory = useStore(state => state.showRunHistory)
return (
<div className='flex items-center px-0.5 h-8 rounded-lg border-[0.5px] border-gray-200 bg-white shadow-xs'>
@ -175,23 +169,7 @@ const RunAndHistory: FC = () => {
isChatMode && <PreviewMode />
}
<div className='mx-0.5 w-[0.5px] h-8 bg-gray-200'></div>
<TooltipPlus
popupContent={t('workflow.common.viewRunHistory')}
>
<div
className={`
flex items-center justify-center w-7 h-7 rounded-md hover:bg-black/5 cursor-pointer
${showRunHistory && 'bg-primary-50'}
`}
onClick={() => {
workflowStore.setState({ showRunHistory: !showRunHistory })
setCurrentLogItem()
setShowMessageLogModal(false)
}}
>
<ClockPlay className={`w-4 h-4 ${showRunHistory ? 'text-primary-600' : 'text-gray-500'}`} />
</div>
</TooltipPlus>
<ViewHistory />
</div>
)
}

View File

@ -0,0 +1,174 @@
import {
memo,
useState,
} from 'react'
import cn from 'classnames'
import useSWR from 'swr'
import { useTranslation } from 'react-i18next'
import {
useIsChatMode,
useWorkflow,
useWorkflowRun,
} from '../hooks'
import { WorkflowRunningStatus } from '../types'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import TooltipPlus from '@/app/components/base/tooltip-plus'
import { useStore as useAppStore } from '@/app/components/app/store'
import {
ClockPlay,
ClockPlaySlim,
} from '@/app/components/base/icons/src/vender/line/time'
import { CheckCircle, XClose } from '@/app/components/base/icons/src/vender/line/general'
import { AlertCircle, AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
import {
fetcChatRunHistory,
fetchWorkflowRunHistory,
} from '@/service/workflow'
import Loading from '@/app/components/base/loading'
import {
useStore,
useWorkflowStore,
} from '@/app/components/workflow/store'
const ViewHistory = () => {
const { t } = useTranslation()
const isChatMode = useIsChatMode()
const [open, setOpen] = useState(false)
const { formatTimeFromNow } = useWorkflow()
const workflowStore = useWorkflowStore()
const { appDetail, setCurrentLogItem, setShowMessageLogModal } = useAppStore()
const historyWorkflowData = useStore(s => s.historyWorkflowData)
const { handleBackupDraft } = useWorkflowRun()
const { data: runList, isLoading: runListLoading } = useSWR((appDetail && !isChatMode) ? `/apps/${appDetail.id}/workflow-runs` : null, fetchWorkflowRunHistory)
const { data: chatList, isLoading: chatListLoading } = useSWR((appDetail && isChatMode) ? `/apps/${appDetail.id}/advanced-chat/workflow-runs` : null, fetcChatRunHistory)
const data = isChatMode ? chatList : runList
const isLoading = isChatMode ? chatListLoading : runListLoading
return (
(
<PortalToFollowElem
placement='bottom-end'
offset={{
mainAxis: 4,
crossAxis: 131,
}}
open={open}
onOpenChange={setOpen}
>
<PortalToFollowElemTrigger onClick={() => setOpen(v => !v)}>
<TooltipPlus
popupContent={t('workflow.common.viewRunHistory')}
>
<div
className={`
flex items-center justify-center w-7 h-7 rounded-md hover:bg-black/5 cursor-pointer
${open && 'bg-primary-50'}
`}
onClick={() => {
setCurrentLogItem()
setShowMessageLogModal(false)
}}
>
<ClockPlay className={`w-4 h-4 ${open ? 'text-primary-600' : 'text-gray-500'}`} />
</div>
</TooltipPlus>
</PortalToFollowElemTrigger>
<PortalToFollowElemContent className='z-[12]'>
<div
className='flex flex-col ml-2 w-[240px] bg-white border-[0.5px] border-gray-200 shadow-xl rounded-xl overflow-y-auto'
style={{
maxHeight: 'calc(2 / 3 * 100vh)',
}}
>
<div className='sticky top-0 bg-white flex items-center justify-between px-4 pt-3 text-base font-semibold text-gray-900'>
<div className='grow'>{t('workflow.common.runHistory')}</div>
<div
className='shrink-0 flex items-center justify-center w-6 h-6 cursor-pointer'
onClick={() => {
setCurrentLogItem()
setShowMessageLogModal(false)
setOpen(false)
}}
>
<XClose className='w-4 h-4 text-gray-500' />
</div>
</div>
{
isLoading && (
<div className='grow flex items-center justify-center h-full'>
<Loading />
</div>
)
}
<div className='p-2'>
{
!data?.data.length && (
<div className='py-12'>
<ClockPlaySlim className='mx-auto mb-2 w-8 h-8 text-gray-300' />
<div className='text-center text-[13px] text-gray-400'>
{t('workflow.common.notRunning')}
</div>
</div>
)
}
{
data?.data.map(item => (
<div
key={item.id}
className={cn(
'flex mb-0.5 px-2 py-[7px] rounded-lg hover:bg-primary-50 cursor-pointer',
item.id === historyWorkflowData?.id && 'bg-primary-50',
)}
onClick={() => {
workflowStore.setState({
historyWorkflowData: item,
})
handleBackupDraft()
setOpen(false)
}}
>
{
!isChatMode && item.status === WorkflowRunningStatus.Stopped && (
<AlertTriangle className='mt-0.5 mr-1.5 w-3.5 h-3.5 text-[#F79009]' />
)
}
{
!isChatMode && item.status === WorkflowRunningStatus.Failed && (
<AlertCircle className='mt-0.5 mr-1.5 w-3.5 h-3.5 text-[#F04438]' />
)
}
{
!isChatMode && item.status === WorkflowRunningStatus.Succeeded && (
<CheckCircle className='mt-0.5 mr-1.5 w-3.5 h-3.5 text-[#12B76A]' />
)
}
<div>
<div
className={cn(
'flex items-center text-[13px] font-medium leading-[18px]',
item.id === historyWorkflowData?.id && 'text-primary-600',
)}
>
{`Test ${isChatMode ? 'Chat' : 'Run'}#${item.sequence_number}`}
</div>
<div className='flex items-center text-xs text-gray-500 leading-[18px]'>
{item.created_by_account.name} · {formatTimeFromNow((item.finished_at || item.created_at) * 1000)}
</div>
</div>
</div>
))
}
</div>
</div>
</PortalToFollowElemContent>
</PortalToFollowElem>
)
)
}
export default memo(ViewHistory)

View File

@ -78,21 +78,23 @@ const ChatRecord = () => {
background: 'linear-gradient(156deg, rgba(242, 244, 247, 0.80) 0%, rgba(242, 244, 247, 0.00) 99.43%), var(--white, #FFF)',
}}
>
<div className='flex items-center justify-between p-4 pb-1 text-base font-semibold text-gray-900'>
<div className='shrink-0 flex items-center justify-between p-4 pb-1 text-base font-semibold text-gray-900'>
{`TEST CHAT#${historyWorkflowData?.sequence_number}`}
</div>
<Chat
config={{} as any}
chatList={chatMessageList}
chatContainerclassName='px-4'
chatContainerInnerClassName='pt-6'
chatFooterClassName='px-4 rounded-b-2xl'
chatFooterInnerClassName='pb-4'
chatNode={<UserInput />}
noChatInput
allToolIcons={{}}
showPromptLog
/>
<div className='grow h-0'>
<Chat
config={{} as any}
chatList={chatMessageList}
chatContainerclassName='px-4'
chatContainerInnerClassName='pt-6'
chatFooterClassName='px-4 rounded-b-2xl'
chatFooterInnerClassName='pb-4'
chatNode={<UserInput />}
noChatInput
allToolIcons={{}}
showPromptLog
/>
</div>
</div>
)
}

View File

@ -9,7 +9,6 @@ import { Panel as NodePanel } from '../nodes'
import { useStore } from '../store'
import { useIsChatMode } from '../hooks'
import DebugAndPreview from './debug-and-preview'
import RunHistory from './run-history'
import Record from './record'
import InputsPanel from './inputs-panel'
import WorkflowPreview from './workflow-preview'
@ -21,7 +20,6 @@ const Panel: FC = () => {
const nodes = useNodes<CommonNodeType>()
const isChatMode = useIsChatMode()
const selectedNode = nodes.find(node => node.data.selected)
const showRunHistory = useStore(state => state.showRunHistory)
const showInputsPanel = useStore(s => s.showInputsPanel)
const workflowRunningData = useStore(s => s.workflowRunningData)
const historyWorkflowData = useStore(s => s.historyWorkflowData)
@ -88,11 +86,6 @@ const Panel: FC = () => {
<NodePanel {...selectedNode!} />
)
}
{
showRunHistory && (
<RunHistory />
)
}
</div>
)
}

View File

@ -1,17 +1,12 @@
import { memo } from 'react'
import { useIsChatMode } from '../hooks'
import Run from '../run'
import { useStore } from '../store'
const Record = () => {
const isChatMode = useIsChatMode()
const historyWorkflowData = useStore(s => s.historyWorkflowData)
return (
<div className={`
flex flex-col h-full rounded-2xl border-[0.5px] border-gray-200 shadow-xl bg-white
${isChatMode ? 'w-[320px]' : 'w-[400px]'}
`}>
<div className='flex flex-col w-[400px] h-full rounded-2xl border-[0.5px] border-gray-200 shadow-xl bg-white'>
<div className='flex items-center justify-between p-4 pb-1 text-base font-semibold text-gray-900'>
{`Test Run#${historyWorkflowData?.sequence_number}`}
</div>

View File

@ -1,130 +0,0 @@
import { memo } from 'react'
import cn from 'classnames'
import { useTranslation } from 'react-i18next'
import useSWR from 'swr'
import { WorkflowRunningStatus } from '../types'
import {
useIsChatMode,
useWorkflow,
useWorkflowRun,
} from '../hooks'
import { CheckCircle, XClose } from '@/app/components/base/icons/src/vender/line/general'
import { AlertCircle, AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
import {
useStore,
useWorkflowStore,
} from '@/app/components/workflow/store'
import { useStore as useAppStore } from '@/app/components/app/store'
import { fetcChatRunHistory, fetchWorkflowRunHistory } from '@/service/workflow'
import Loading from '@/app/components/base/loading'
import { ClockPlaySlim } from '@/app/components/base/icons/src/vender/line/time'
const RunHistory = () => {
const { t } = useTranslation()
const isChatMode = useIsChatMode()
const { appDetail, setCurrentLogItem, setShowMessageLogModal } = useAppStore()
const { formatTimeFromNow } = useWorkflow()
const { handleBackupDraft } = useWorkflowRun()
const workflowStore = useWorkflowStore()
const historyWorkflowData = useStore(s => s.historyWorkflowData)
const { data: runList, isLoading: runListLoading } = useSWR((appDetail && !isChatMode) ? `/apps/${appDetail.id}/workflow-runs` : null, fetchWorkflowRunHistory)
const { data: chatList, isLoading: chatListLoading } = useSWR((appDetail && isChatMode) ? `/apps/${appDetail.id}/advanced-chat/workflow-runs` : null, fetcChatRunHistory)
const data = isChatMode ? chatList : runList
const isLoading = isChatMode ? chatListLoading : runListLoading
if (!appDetail)
return null
return (
<div className='absolute -top-2 right-2 flex flex-col ml-2 w-[240px] min-h-[214px] bg-white border-[0.5px] border-gray-200 shadow-xl rounded-xl overflow-y-auto z-[11]'>
<div className='shrink-0 flex items-center justify-between px-4 pt-3 text-base font-semibold text-gray-900'>
{t('workflow.common.runHistory')}
<div
className='flex items-center justify-center w-6 h-6 cursor-pointer'
onClick={() => {
workflowStore.setState({
showRunHistory: false,
})
setCurrentLogItem()
setShowMessageLogModal(false)
}}
>
<XClose className='w-4 h-4 text-gray-500' />
</div>
</div>
{
isLoading && (
<div className='grow flex items-center justify-center h-full'>
<Loading />
</div>
)
}
<div className='grow p-2 overflow-y-auto'>
{
!data?.data.length && (
<div className='flex justify-center items-center h-full'>
<div>
<div className='flex justify-center mb-2'>
<ClockPlaySlim className='w-8 h-8 text-gray-300' />
</div>
<div className='text-center text-[13px] text-gray-400'>
{t('workflow.common.notRunning')}
</div>
</div>
</div>
)
}
{
data?.data.map(item => (
<div
key={item.id}
className={cn(
'flex mb-0.5 px-2 py-[7px] rounded-lg hover:bg-primary-50 cursor-pointer',
item.id === historyWorkflowData?.id && 'bg-primary-50',
)}
onClick={() => {
workflowStore.setState({
historyWorkflowData: item,
})
handleBackupDraft()
}}
>
{
!isChatMode && item.status === WorkflowRunningStatus.Stopped && (
<AlertTriangle className='mt-0.5 mr-1.5 w-3.5 h-3.5 text-[#F79009]' />
)
}
{
!isChatMode && item.status === WorkflowRunningStatus.Failed && (
<AlertCircle className='mt-0.5 mr-1.5 w-3.5 h-3.5 text-[#F04438]' />
)
}
{
!isChatMode && item.status === WorkflowRunningStatus.Succeeded && (
<CheckCircle className='mt-0.5 mr-1.5 w-3.5 h-3.5 text-[#12B76A]' />
)
}
<div>
<div
className={cn(
'flex items-center text-[13px] font-medium leading-[18px]',
item.id === historyWorkflowData?.id && 'text-primary-600',
)}
>
{`Test ${isChatMode ? 'Chat' : 'Run'}#${item.sequence_number}`}
</div>
<div className='flex items-center text-xs text-gray-500 leading-[18px]'>
{item.created_by_account.name} · {formatTimeFromNow((item.finished_at || item.created_at) * 1000)}
</div>
</div>
</div>
))
}
</div>
</div>
)
}
export default memo(RunHistory)