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 draftUpdatedAt = useStore(state => state.draftUpdatedAt)
const publishedAt = useStore(state => state.publishedAt)
const isSyncingWorkflowDraft = useStore(s => s.isSyncingWorkflowDraft)
return (
<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.unpublished')
}
{
isSyncingWorkflowDraft && (
<>
<span className='flex items-center mx-1'>·</span>
{t('workflow.common.syncingData')}
</>
)
}
</div>
)
}

View File

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

View File

@ -55,6 +55,7 @@ import HelpLine from './help-line'
import CandidateNode from './candidate-node'
import PanelContextmenu from './panel-contextmenu'
import NodeContextmenu from './node-contextmenu'
import SyncingDataModal from './syncing-data-modal'
import {
useStore,
useWorkflowStore,
@ -99,7 +100,10 @@ const Workflow: FC<WorkflowProps> = memo(({
const controlMode = useStore(s => s.controlMode)
const nodeAnimation = useStore(s => s.nodeAnimation)
const showConfirm = useStore(s => s.showConfirm)
const { setShowConfirm } = workflowStore.getState()
const {
setShowConfirm,
setControlPromptEditorRerenderKey,
} = workflowStore.getState()
const {
handleSyncWorkflowDraft,
syncWorkflowDraftWhenPageClose,
@ -113,6 +117,7 @@ const Workflow: FC<WorkflowProps> = memo(({
if (v.type === WORKFLOW_DATA_UPDATE) {
setNodes(v.payload.nodes)
setEdges(v.payload.edges)
setTimeout(() => setControlPromptEditorRerenderKey(Date.now()))
}
})
@ -135,7 +140,7 @@ const Workflow: FC<WorkflowProps> = memo(({
if (document.visibilityState === 'hidden')
syncWorkflowDraftWhenPageClose()
else if (document.visibilityState === 'visible')
handleRefreshWorkflowDraft()
setTimeout(() => handleRefreshWorkflowDraft(), 500)
}, [syncWorkflowDraftWhenPageClose, handleRefreshWorkflowDraft])
useEffect(() => {
@ -223,6 +228,7 @@ const Workflow: FC<WorkflowProps> = memo(({
`}
ref={workflowContainerRef}
>
<SyncingDataModal />
<CandidateNode />
<Header />
<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 Switch from '@/app/components/base/switch'
import { Jinja } from '@/app/components/base/icons/src/vender/workflow'
import { useStore } from '@/app/components/workflow/store'
type Props = {
className?: string
@ -82,6 +83,7 @@ const Editor: FC<Props> = ({
}) => {
const { t } = useTranslation()
const { eventEmitter } = useEventEmitterContextContext()
const controlPromptEditorRerenderKey = useStore(s => s.controlPromptEditorRerenderKey)
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')}>
<PromptEditor
key={controlPromptEditorRerenderKey}
instanceId={instanceId}
compact
className='min-h-[56px]'

View File

@ -125,6 +125,10 @@ type Shape = {
nodeData: VariableAssignerNodeType
}
setEnteringNodePayload: (enteringNodePayload?: Shape['enteringNodePayload']) => void
isSyncingWorkflowDraft: boolean
setIsSyncingWorkflowDraft: (isSyncingWorkflowDraft: boolean) => void
controlPromptEditorRerenderKey: number
setControlPromptEditorRerenderKey: (controlPromptEditorRerenderKey: number) => void
}
export const createWorkflowStore = () => {
@ -209,6 +213,10 @@ export const createWorkflowStore = () => {
setConnectingNodePayload: connectingNodePayload => set(() => ({ connectingNodePayload })),
enteringNodePayload: undefined,
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',
workflowAsToolTip: 'Tool reconfiguration is required after the workflow update.',
viewDetailInTracingPanel: 'View details',
syncingData: 'Syncing data, just a few seconds.',
},
errorMsg: {
fieldRequired: '{{field}} is required',

View File

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