From e925a8ab99fcd62ac24725769384997c95489d10 Mon Sep 17 00:00:00 2001
From: lyzno1 <92089059+lyzno1@users.noreply.github.com>
Date: Mon, 1 Sep 2025 22:52:23 +0800
Subject: [PATCH] fix(app-cards): restrict toggle enable to Start nodes only
(#24918)
---
web/app/components/app/overview/app-card.tsx | 64 +++++++++----------
.../components/tools/mcp/mcp-service-card.tsx | 34 ++++++++--
2 files changed, 58 insertions(+), 40 deletions(-)
diff --git a/web/app/components/app/overview/app-card.tsx b/web/app/components/app/overview/app-card.tsx
index 95159cf039..05650d5a94 100644
--- a/web/app/components/app/overview/app-card.tsx
+++ b/web/app/components/app/overview/app-card.tsx
@@ -41,7 +41,7 @@ import AccessControl from '../app-access-control'
import { useAppWhiteListSubjects } from '@/service/access-control'
import { useAppWorkflow } from '@/service/use-workflow'
import { useGlobalPublicStore } from '@/context/global-public-context'
-import { getWorkflowEntryNode } from '@/app/components/workflow/utils/workflow-entry'
+import { BlockEnum } from '@/app/components/workflow/types'
import { useDocLink } from '@/context/i18n'
export type IAppCardProps = {
@@ -107,12 +107,12 @@ function AppCard({
: t('appOverview.overview.apiInfo.title')
const isWorkflowApp = appInfo.mode === 'workflow'
const appUnpublished = isWorkflowApp && !currentWorkflow?.graph
- const hasEntryNode = getWorkflowEntryNode(currentWorkflow?.graph?.nodes || [])
- const missingEntryNode = isWorkflowApp && !hasEntryNode
+ const hasStartNode = currentWorkflow?.graph?.nodes?.some(node => node.data.type === BlockEnum.Start)
+ const missingStartNode = isWorkflowApp && !hasStartNode
const hasInsufficientPermissions = isApp ? !isCurrentWorkspaceEditor : !isCurrentWorkspaceManager
- const toggleDisabled = hasInsufficientPermissions || appUnpublished || missingEntryNode
- const runningStatus = (appUnpublished || missingEntryNode) ? false : (isApp ? appInfo.enable_site : appInfo.enable_api)
- const isMinimalState = appUnpublished || missingEntryNode
+ const toggleDisabled = hasInsufficientPermissions || appUnpublished || missingStartNode
+ const runningStatus = (appUnpublished || missingStartNode) ? false : (isApp ? appInfo.enable_site : appInfo.enable_api)
+ const isMinimalState = appUnpublished || missingStartNode
const { app_base_url, access_token } = appInfo.site ?? {}
const appMode = (appInfo.mode !== 'completion' && appInfo.mode !== 'workflow') ? 'chat' : appInfo.mode
const appUrl = `${app_base_url}${basePath}/${appMode}/${access_token}`
@@ -211,34 +211,30 @@ function AppCard({
: t('appOverview.overview.status.disable')}
- {isApp ? (
-
-
- {t('appOverview.overview.appInfo.enableTooltip.description')}
-
- window.open(docLink('/guides/workflow/node/start'), '_blank')}
- >
- {t('appOverview.overview.appInfo.enableTooltip.learnMore')}
-
- >
- ) : ''
- }
- position="right"
- popupClassName="w-58 max-w-60 rounded-xl border-[0.5px] p-3.5 shadow-lg backdrop-blur-[10px]"
- offset={24}
- >
-
-
-
-
- ) : (
-
- )}
+
+
+ {t('appOverview.overview.appInfo.enableTooltip.description')}
+
+ window.open(docLink('/guides/workflow/node/start'), '_blank')}
+ >
+ {t('appOverview.overview.appInfo.enableTooltip.learnMore')}
+
+ >
+ ) : ''
+ }
+ position="right"
+ popupClassName="w-58 max-w-60 rounded-xl border-[0.5px] p-3.5 shadow-lg backdrop-blur-[10px]"
+ offset={24}
+ >
+
+
+
+
{!isMinimalState && (
diff --git a/web/app/components/tools/mcp/mcp-service-card.tsx b/web/app/components/tools/mcp/mcp-service-card.tsx
index 3041072342..cfff222bb8 100644
--- a/web/app/components/tools/mcp/mcp-service-card.tsx
+++ b/web/app/components/tools/mcp/mcp-service-card.tsx
@@ -24,9 +24,9 @@ import {
useUpdateMCPServer,
} from '@/service/use-tools'
import { BlockEnum } from '@/app/components/workflow/types'
-import { getWorkflowEntryNode } from '@/app/components/workflow/utils/workflow-entry'
import cn from '@/utils/classnames'
import { fetchAppDetail } from '@/service/apps'
+import { useDocLink } from '@/context/i18n'
export type IAppCardProps = {
appInfo: AppDetailResponse & Partial
@@ -36,6 +36,7 @@ function MCPServiceCard({
appInfo,
}: IAppCardProps) {
const { t } = useTranslation()
+ const docLink = useDocLink()
const appId = appInfo.id
const { mutateAsync: updateMCPServer } = useUpdateMCPServer()
const { mutateAsync: refreshMCPServerCode, isPending: genLoading } = useRefreshMCPServerCode()
@@ -75,11 +76,11 @@ function MCPServiceCard({
const serverPublished = !!id
const serverActivated = status === 'active'
const serverURL = serverPublished ? `${appInfo.api_base_url.replace('/v1', '')}/mcp/server/${server_code}/mcp` : '***********'
- const hasEntryNode = getWorkflowEntryNode(currentWorkflow?.graph?.nodes || [])
- const missingEntryNode = isWorkflowApp && !hasEntryNode
+ const hasStartNode = currentWorkflow?.graph?.nodes?.some(node => node.data.type === BlockEnum.Start)
+ const missingStartNode = isWorkflowApp && !hasStartNode
const hasInsufficientPermissions = !isCurrentWorkspaceEditor
- const toggleDisabled = hasInsufficientPermissions || appUnpublished || missingEntryNode
- const isMinimalState = appUnpublished || missingEntryNode
+ const toggleDisabled = hasInsufficientPermissions || appUnpublished || missingStartNode
+ const isMinimalState = appUnpublished || missingStartNode
const [activated, setActivated] = useState(serverActivated)
@@ -165,7 +166,28 @@ function MCPServiceCard({
+
+ {t('appOverview.overview.appInfo.enableTooltip.description')}
+
+ window.open(docLink('/guides/workflow/node/start'), '_blank')}
+ >
+ {t('appOverview.overview.appInfo.enableTooltip.learnMore')}
+
+ >
+ ) : ''
+ ) : ''
+ }
+ position="right"
+ popupClassName="w-58 max-w-60 rounded-xl border-[0.5px] p-3.5 shadow-lg backdrop-blur-[10px]"
+ offset={24}
>