diff --git a/web/app/components/workflow-app/components/workflow-header/index.tsx b/web/app/components/workflow-app/components/workflow-header/index.tsx index 993cbb6d78..3fe679925a 100644 --- a/web/app/components/workflow-app/components/workflow-header/index.tsx +++ b/web/app/components/workflow-app/components/workflow-header/index.tsx @@ -11,7 +11,6 @@ import { useResetWorkflowVersionHistory } from '@/service/use-workflow' import { useIsChatMode } from '../../hooks' import ChatVariableTrigger from './chat-variable-trigger' import FeaturesTrigger from './features-trigger' -import ViewPickerTrigger from './view-picker-trigger' const WorkflowHeader = () => { const { appDetail, setCurrentLogItem, setShowMessageLogModal } = useAppStore(useShallow(state => ({ @@ -38,7 +37,6 @@ const WorkflowHeader = () => { return { normal: { components: { - left: , middle: , chatVariableTrigger: , }, diff --git a/web/app/components/workflow-app/components/workflow-header/view-picker-trigger.tsx b/web/app/components/workflow-app/components/workflow-header/view-picker-trigger.tsx deleted file mode 100644 index dcb69d2a7a..0000000000 --- a/web/app/components/workflow-app/components/workflow-header/view-picker-trigger.tsx +++ /dev/null @@ -1,28 +0,0 @@ -'use client' - -import type { ViewType } from '@/app/components/workflow/types' -import { useQueryState } from 'nuqs' -import { useCallback } from 'react' -import { useFeatures } from '@/app/components/base/features/hooks' -import ViewPicker from '@/app/components/workflow/view-picker' -import { parseAsViewType, WORKFLOW_VIEW_PARAM_KEY } from '../../search-params' - -const ViewPickerTrigger = () => { - const isSupportSandbox = useFeatures(s => !!s.features.sandbox?.enabled) - const [viewType, doSetViewType] = useQueryState(WORKFLOW_VIEW_PARAM_KEY, parseAsViewType) - const handleViewTypeChange = useCallback((type: ViewType) => { - doSetViewType(type) - }, [doSetViewType]) - - if (!isSupportSandbox) - return null - - return ( - - ) -} - -export default ViewPickerTrigger diff --git a/web/app/components/workflow-app/index.tsx b/web/app/components/workflow-app/index.tsx index c6b280064d..08972bad5b 100644 --- a/web/app/components/workflow-app/index.tsx +++ b/web/app/components/workflow-app/index.tsx @@ -10,8 +10,8 @@ import { useCallback, useEffect, useMemo, - useReducer, useRef, + useState, } from 'react' import { useStore as useAppStore } from '@/app/components/app/store' import { FeaturesProvider } from '@/app/components/base/features' @@ -21,7 +21,6 @@ import WorkflowWithDefaultContext from '@/app/components/workflow' import { WorkflowContextProvider, } from '@/app/components/workflow/context' -import { HeaderShell } from '@/app/components/workflow/header' import { useWorkflowStore } from '@/app/components/workflow/store' import { useTriggerStatusStore } from '@/app/components/workflow/store/trigger-status' import { @@ -37,7 +36,7 @@ import { fetchRunDetail } from '@/service/log' import { useAppTriggers } from '@/service/use-tools' import { AppModeEnum } from '@/types/app' import { useFeatures } from '../base/features/hooks' -import ViewPickerTrigger from './components/workflow-header/view-picker-trigger' +import ViewPicker from '../workflow/view-picker' import WorkflowAppMain from './components/workflow-main' import { useGetRunAndTraceUrl } from './hooks/use-get-run-and-trace-url' import { useNodesSyncDraft } from './hooks/use-nodes-sync-draft' @@ -56,85 +55,52 @@ type WorkflowViewContentProps = { reload: () => Promise } -const WorkflowViewPickerDock = () => { - return ( - -
-
- -
-
-
- ) -} - const WorkflowViewContent = ({ graphContent, reload, }: WorkflowViewContentProps) => { const features = useFeatures(s => s.features) const isSupportSandbox = !!features.sandbox?.enabled - const [viewType] = useQueryState(WORKFLOW_VIEW_PARAM_KEY, parseAsViewType) + const [viewType, doSetViewType] = useQueryState(WORKFLOW_VIEW_PARAM_KEY, parseAsViewType) const { syncWorkflowDraftImmediately } = useNodesSyncDraft() - const [isGraphRefreshing, setGraphRefreshing] = useReducer((_: boolean, next: boolean) => next, false) const pendingSyncRef = useRef | null>(null) - const refreshInFlightRef = useRef | null>(null) - const previousViewTypeRef = useRef(viewType) - const viewTypeRef = useRef(viewType) + const [isGraphRefreshing, setIsGraphRefreshing] = useState(false) - const refreshGraph = useCallback((waitFor?: Promise) => { - if (refreshInFlightRef.current) - return refreshInFlightRef.current - - setGraphRefreshing(true) - const runRefresh = () => { - if (viewTypeRef.current !== ViewType.graph) { - refreshInFlightRef.current = null - setGraphRefreshing(false) - return Promise.resolve() - } - - return reload().finally(() => { - refreshInFlightRef.current = null - setGraphRefreshing(false) - }) - } - refreshInFlightRef.current = waitFor ? waitFor.then(runRefresh, runRefresh) : runRefresh() - return refreshInFlightRef.current + const refreshGraph = useCallback(() => { + setIsGraphRefreshing(true) + return reload().finally(() => { + setIsGraphRefreshing(false) + }) }, [reload]) - useEffect(() => { - viewTypeRef.current = viewType - if (!isSupportSandbox) { - previousViewTypeRef.current = viewType - return - } + const handleViewTypeChange = useCallback((type: ViewType) => { + if (viewType === ViewType.graph && type !== viewType) + pendingSyncRef.current = syncWorkflowDraftImmediately(true).catch(() => { }) - const previousView = previousViewTypeRef.current - if (previousView === ViewType.graph && viewType !== ViewType.graph) { - if (!pendingSyncRef.current) { - const pending = syncWorkflowDraftImmediately(true).catch(() => { }) - pendingSyncRef.current = pending + doSetViewType(type) + if (type === ViewType.graph) { + const pending = pendingSyncRef.current + if (pending) { pending.finally(() => { - if (pendingSyncRef.current === pending) - pendingSyncRef.current = null + refreshGraph() }) + pendingSyncRef.current = null + } + else { + refreshGraph() } } + }, [doSetViewType, refreshGraph, syncWorkflowDraftImmediately, viewType]) - if (previousView !== ViewType.graph && viewType === ViewType.graph) { - refreshGraph(pendingSyncRef.current ?? undefined) - } - - previousViewTypeRef.current = viewType - }, [isSupportSandbox, refreshGraph, syncWorkflowDraftImmediately, viewType]) - - if (!isSupportSandbox) + if (!isSupportSandbox) { return graphContent - + } return ( -
- {viewType !== ViewType.graph ? : null} +
+ {viewType === ViewType.graph ? ( isGraphRefreshing diff --git a/web/app/components/workflow/header/header-in-normal.tsx b/web/app/components/workflow/header/header-in-normal.tsx index e48228030f..be4985fb83 100644 --- a/web/app/components/workflow/header/header-in-normal.tsx +++ b/web/app/components/workflow/header/header-in-normal.tsx @@ -61,18 +61,18 @@ const HeaderInNormal = ({ setShowChatVariablePanel(false) setShowGlobalVariablePanel(false) closeAllInputFieldPanels() - }, [workflowStore, handleBackupDraft, selectedNode, handleNodeSelect, setShowWorkflowVersionHistoryPanel, setShowEnvPanel, setShowDebugAndPreviewPanel, setShowVariableInspectPanel, setShowChatVariablePanel, setShowGlobalVariablePanel, closeAllInputFieldPanels]) + }, [workflowStore, handleBackupDraft, selectedNode, handleNodeSelect, setShowWorkflowVersionHistoryPanel, setShowEnvPanel, setShowDebugAndPreviewPanel, setShowVariableInspectPanel, setShowChatVariablePanel, setShowGlobalVariablePanel]) return (
-
- {components?.left} +
+ {components?.left}
diff --git a/web/app/components/workflow/header/index.tsx b/web/app/components/workflow/header/index.tsx index d0f91a69ff..0590c016f2 100644 --- a/web/app/components/workflow/header/index.tsx +++ b/web/app/components/workflow/header/index.tsx @@ -1,4 +1,3 @@ -import type { ReactNode } from 'react' import type { HeaderInNormalProps } from './header-in-normal' import type { HeaderInRestoringProps } from './header-in-restoring' import type { HeaderInHistoryProps } from './header-in-view-history' @@ -17,26 +16,6 @@ const HeaderInRestoring = dynamic(() => import('./header-in-restoring'), { ssr: false, }) -type HeaderShellProps = { - children: ReactNode -} - -export const HeaderShell = ({ children }: HeaderShellProps) => { - const pathname = usePathname() - const inWorkflowCanvas = pathname.endsWith('/workflow') - const isPipelineCanvas = pathname.endsWith('/pipeline') - const maximizeCanvas = useStore(s => s.maximizeCanvas) - - return ( -
- {(inWorkflowCanvas || isPipelineCanvas) && maximizeCanvas &&
} - {children} -
- ) -} - export type HeaderProps = { normal?: HeaderInNormalProps viewHistory?: HeaderInHistoryProps @@ -47,14 +26,21 @@ const Header = ({ viewHistory: viewHistoryProps, restoring: restoringProps, }: HeaderProps) => { + const pathname = usePathname() + const inWorkflowCanvas = pathname.endsWith('/workflow') + const isPipelineCanvas = pathname.endsWith('/pipeline') const { normal, restoring, viewHistory, } = useWorkflowMode() + const maximizeCanvas = useStore(s => s.maximizeCanvas) return ( - +
+ {(inWorkflowCanvas || isPipelineCanvas) && maximizeCanvas &&
} { normal && ( ) } - +
) } diff --git a/web/app/components/workflow/view-picker.tsx b/web/app/components/workflow/view-picker.tsx index e81b35774e..43b20d52fb 100644 --- a/web/app/components/workflow/view-picker.tsx +++ b/web/app/components/workflow/view-picker.tsx @@ -33,7 +33,7 @@ const ViewPicker: FC = ({ return (