chore: workflow syncing modal (#5108)

This commit is contained in:
zxhlyh 2024-06-12 16:35:19 +08:00 committed by GitHub
parent 0ce97e6315
commit 95443bd551
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 48 additions and 3 deletions

View File

@ -10,6 +10,7 @@ const EditingTitle = () => {
const { formatTimeFromNow } = useWorkflow() const { formatTimeFromNow } = useWorkflow()
const draftUpdatedAt = useStore(state => state.draftUpdatedAt) const draftUpdatedAt = useStore(state => state.draftUpdatedAt)
const publishedAt = useStore(state => state.publishedAt) const publishedAt = useStore(state => state.publishedAt)
const isSyncingWorkflowDraft = useStore(s => s.isSyncingWorkflowDraft)
return ( return (
<div className='flex items-center h-[18px] text-xs text-gray-500'> <div className='flex items-center h-[18px] text-xs text-gray-500'>
@ -26,6 +27,14 @@ const EditingTitle = () => {
? `${t('workflow.common.published')} ${formatTimeFromNow(publishedAt)}` ? `${t('workflow.common.published')} ${formatTimeFromNow(publishedAt)}`
: t('workflow.common.unpublished') : t('workflow.common.unpublished')
} }
{
isSyncingWorkflowDraft && (
<>
<span className='flex items-center mx-1'>·</span>
{t('workflow.common.syncingData')}
</>
)
}
</div> </div>
) )
} }

View File

@ -57,11 +57,13 @@ export const useWorkflowUpdate = () => {
const { const {
appId, appId,
setSyncWorkflowDraftHash, setSyncWorkflowDraftHash,
setIsSyncingWorkflowDraft,
} = workflowStore.getState() } = workflowStore.getState()
setIsSyncingWorkflowDraft(true)
fetchWorkflowDraft(`/apps/${appId}/workflows/draft`).then((response) => { fetchWorkflowDraft(`/apps/${appId}/workflows/draft`).then((response) => {
handleUpdateWorkflowCanvas(response.graph as WorkflowDataUpdator) handleUpdateWorkflowCanvas(response.graph as WorkflowDataUpdator)
setSyncWorkflowDraftHash(response.hash) setSyncWorkflowDraftHash(response.hash)
}) }).finally(() => setIsSyncingWorkflowDraft(false))
}, [handleUpdateWorkflowCanvas, workflowStore]) }, [handleUpdateWorkflowCanvas, workflowStore])
return { return {

View File

@ -55,6 +55,7 @@ import HelpLine from './help-line'
import CandidateNode from './candidate-node' import CandidateNode from './candidate-node'
import PanelContextmenu from './panel-contextmenu' import PanelContextmenu from './panel-contextmenu'
import NodeContextmenu from './node-contextmenu' import NodeContextmenu from './node-contextmenu'
import SyncingDataModal from './syncing-data-modal'
import { import {
useStore, useStore,
useWorkflowStore, useWorkflowStore,
@ -99,7 +100,10 @@ const Workflow: FC<WorkflowProps> = memo(({
const controlMode = useStore(s => s.controlMode) const controlMode = useStore(s => s.controlMode)
const nodeAnimation = useStore(s => s.nodeAnimation) const nodeAnimation = useStore(s => s.nodeAnimation)
const showConfirm = useStore(s => s.showConfirm) const showConfirm = useStore(s => s.showConfirm)
const { setShowConfirm } = workflowStore.getState() const {
setShowConfirm,
setControlPromptEditorRerenderKey,
} = workflowStore.getState()
const { const {
handleSyncWorkflowDraft, handleSyncWorkflowDraft,
syncWorkflowDraftWhenPageClose, syncWorkflowDraftWhenPageClose,
@ -113,6 +117,7 @@ const Workflow: FC<WorkflowProps> = memo(({
if (v.type === WORKFLOW_DATA_UPDATE) { if (v.type === WORKFLOW_DATA_UPDATE) {
setNodes(v.payload.nodes) setNodes(v.payload.nodes)
setEdges(v.payload.edges) setEdges(v.payload.edges)
setTimeout(() => setControlPromptEditorRerenderKey(Date.now()))
} }
}) })
@ -135,7 +140,7 @@ const Workflow: FC<WorkflowProps> = memo(({
if (document.visibilityState === 'hidden') if (document.visibilityState === 'hidden')
syncWorkflowDraftWhenPageClose() syncWorkflowDraftWhenPageClose()
else if (document.visibilityState === 'visible') else if (document.visibilityState === 'visible')
handleRefreshWorkflowDraft() setTimeout(() => handleRefreshWorkflowDraft(), 500)
}, [syncWorkflowDraftWhenPageClose, handleRefreshWorkflowDraft]) }, [syncWorkflowDraftWhenPageClose, handleRefreshWorkflowDraft])
useEffect(() => { useEffect(() => {
@ -223,6 +228,7 @@ const Workflow: FC<WorkflowProps> = memo(({
`} `}
ref={workflowContainerRef} ref={workflowContainerRef}
> >
<SyncingDataModal />
<CandidateNode /> <CandidateNode />
<Header /> <Header />
<Panel /> <Panel />

View File

@ -27,6 +27,7 @@ import TooltipPlus from '@/app/components/base/tooltip-plus'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor/editor-support-vars'
import Switch from '@/app/components/base/switch' import Switch from '@/app/components/base/switch'
import { Jinja } from '@/app/components/base/icons/src/vender/workflow' import { Jinja } from '@/app/components/base/icons/src/vender/workflow'
import { useStore } from '@/app/components/workflow/store'
type Props = { type Props = {
className?: string className?: string
@ -82,6 +83,7 @@ const Editor: FC<Props> = ({
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { eventEmitter } = useEventEmitterContextContext() const { eventEmitter } = useEventEmitterContextContext()
const controlPromptEditorRerenderKey = useStore(s => s.controlPromptEditorRerenderKey)
const isShowHistory = !isChatModel && isChatApp const isShowHistory = !isChatModel && isChatApp
@ -173,6 +175,7 @@ const Editor: FC<Props> = ({
? ( ? (
<div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative px-3 min-h-[56px] overflow-y-auto')}> <div className={cn(isExpand ? 'grow' : 'max-h-[536px]', 'relative px-3 min-h-[56px] overflow-y-auto')}>
<PromptEditor <PromptEditor
key={controlPromptEditorRerenderKey}
instanceId={instanceId} instanceId={instanceId}
compact compact
className='min-h-[56px]' className='min-h-[56px]'

View File

@ -125,6 +125,10 @@ type Shape = {
nodeData: VariableAssignerNodeType nodeData: VariableAssignerNodeType
} }
setEnteringNodePayload: (enteringNodePayload?: Shape['enteringNodePayload']) => void setEnteringNodePayload: (enteringNodePayload?: Shape['enteringNodePayload']) => void
isSyncingWorkflowDraft: boolean
setIsSyncingWorkflowDraft: (isSyncingWorkflowDraft: boolean) => void
controlPromptEditorRerenderKey: number
setControlPromptEditorRerenderKey: (controlPromptEditorRerenderKey: number) => void
} }
export const createWorkflowStore = () => { export const createWorkflowStore = () => {
@ -209,6 +213,10 @@ export const createWorkflowStore = () => {
setConnectingNodePayload: connectingNodePayload => set(() => ({ connectingNodePayload })), setConnectingNodePayload: connectingNodePayload => set(() => ({ connectingNodePayload })),
enteringNodePayload: undefined, enteringNodePayload: undefined,
setEnteringNodePayload: enteringNodePayload => set(() => ({ enteringNodePayload })), setEnteringNodePayload: enteringNodePayload => set(() => ({ enteringNodePayload })),
isSyncingWorkflowDraft: false,
setIsSyncingWorkflowDraft: isSyncingWorkflowDraft => set(() => ({ isSyncingWorkflowDraft })),
controlPromptEditorRerenderKey: 0,
setControlPromptEditorRerenderKey: controlPromptEditorRerenderKey => set(() => ({ controlPromptEditorRerenderKey })),
})) }))
} }

View File

@ -0,0 +1,15 @@
import { useStore } from './store'
const SyncingDataModal = () => {
const isSyncingWorkflowDraft = useStore(s => s.isSyncingWorkflowDraft)
if (!isSyncingWorkflowDraft)
return null
return (
<div className='absolute inset-0 z-[9999]'>
</div>
)
}
export default SyncingDataModal

View File

@ -67,6 +67,7 @@ const translation = {
manageInTools: 'Manage in Tools', manageInTools: 'Manage in Tools',
workflowAsToolTip: 'Tool reconfiguration is required after the workflow update.', workflowAsToolTip: 'Tool reconfiguration is required after the workflow update.',
viewDetailInTracingPanel: 'View details', viewDetailInTracingPanel: 'View details',
syncingData: 'Syncing data, just a few seconds.',
}, },
errorMsg: { errorMsg: {
fieldRequired: '{{field}} is required', fieldRequired: '{{field}} is required',

View File

@ -67,6 +67,7 @@ const translation = {
manageInTools: '访问工具页', manageInTools: '访问工具页',
workflowAsToolTip: '工作流更新后需要重新配置工具参数', workflowAsToolTip: '工作流更新后需要重新配置工具参数',
viewDetailInTracingPanel: '查看详细信息', viewDetailInTracingPanel: '查看详细信息',
syncingData: '同步数据中,只需几秒钟。',
}, },
errorMsg: { errorMsg: {
fieldRequired: '{{field}} 不能为空', fieldRequired: '{{field}} 不能为空',