fix(app-cards): restrict toggle enable to Start nodes only (#24918)

This commit is contained in:
lyzno1 2025-09-01 22:52:23 +08:00 committed by GitHub
parent bccaf939e6
commit e925a8ab99
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 40 deletions

View File

@ -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')}
</div>
</div>
{isApp ? (
<Tooltip
popupContent={
toggleDisabled && (appUnpublished || missingEntryNode) ? (
<>
<div className="mb-1 text-xs font-normal text-text-secondary">
{t('appOverview.overview.appInfo.enableTooltip.description')}
</div>
<div
className="cursor-pointer text-xs font-normal text-text-accent hover:underline"
onClick={() => window.open(docLink('/guides/workflow/node/start'), '_blank')}
>
{t('appOverview.overview.appInfo.enableTooltip.learnMore')}
</div>
</>
) : ''
}
position="right"
popupClassName="w-58 max-w-60 rounded-xl border-[0.5px] p-3.5 shadow-lg backdrop-blur-[10px]"
offset={24}
>
<div>
<Switch defaultValue={runningStatus} onChange={onChangeStatus} disabled={toggleDisabled} />
</div>
</Tooltip>
) : (
<Switch defaultValue={runningStatus} onChange={onChangeStatus} disabled={toggleDisabled} />
)}
<Tooltip
popupContent={
toggleDisabled && (appUnpublished || missingStartNode) ? (
<>
<div className="mb-1 text-xs font-normal text-text-secondary">
{t('appOverview.overview.appInfo.enableTooltip.description')}
</div>
<div
className="cursor-pointer text-xs font-normal text-text-accent hover:underline"
onClick={() => window.open(docLink('/guides/workflow/node/start'), '_blank')}
>
{t('appOverview.overview.appInfo.enableTooltip.learnMore')}
</div>
</>
) : ''
}
position="right"
popupClassName="w-58 max-w-60 rounded-xl border-[0.5px] p-3.5 shadow-lg backdrop-blur-[10px]"
offset={24}
>
<div>
<Switch defaultValue={runningStatus} onChange={onChangeStatus} disabled={toggleDisabled} />
</div>
</Tooltip>
</div>
{!isMinimalState && (
<div className='flex flex-col items-start justify-center self-stretch'>

View File

@ -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<AppSSO>
@ -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({
</div>
</div>
<Tooltip
popupContent={appUnpublished ? t('tools.mcp.server.publishTip') : ''}
popupContent={
toggleDisabled ? (
appUnpublished ? (
t('tools.mcp.server.publishTip')
) : missingStartNode ? (
<>
<div className="mb-1 text-xs font-normal text-text-secondary">
{t('appOverview.overview.appInfo.enableTooltip.description')}
</div>
<div
className="cursor-pointer text-xs font-normal text-text-accent hover:underline"
onClick={() => window.open(docLink('/guides/workflow/node/start'), '_blank')}
>
{t('appOverview.overview.appInfo.enableTooltip.learnMore')}
</div>
</>
) : ''
) : ''
}
position="right"
popupClassName="w-58 max-w-60 rounded-xl border-[0.5px] p-3.5 shadow-lg backdrop-blur-[10px]"
offset={24}
>
<div>
<Switch defaultValue={activated} onChange={onChangeStatus} disabled={toggleDisabled} />