mirror of
https://github.com/langgenius/dify.git
synced 2025-12-25 01:00:42 -05:00
feat: introduce trigger functionality (#27644)
Signed-off-by: lyzno1 <yuanyouhuilyz@gmail.com> Co-authored-by: Stream <Stream_2@qq.com> Co-authored-by: lyzno1 <92089059+lyzno1@users.noreply.github.com> Co-authored-by: zhsama <torvalds@linux.do> Co-authored-by: Harry <xh001x@hotmail.com> Co-authored-by: lyzno1 <yuanyouhuilyz@gmail.com> Co-authored-by: yessenia <yessenia.contact@gmail.com> Co-authored-by: hjlarry <hjlarry@163.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: WTW0313 <twwu@dify.ai> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -24,7 +24,7 @@ import { fetchAppDetailDirect } from '@/service/apps'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||
import type { App } from '@/types/app'
|
||||
import { type App, AppModeEnum } from '@/types/app'
|
||||
import useDocumentTitle from '@/hooks/use-document-title'
|
||||
import { useStore as useTagStore } from '@/app/components/base/tag-management/store'
|
||||
import dynamic from 'next/dynamic'
|
||||
@@ -64,12 +64,12 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
selectedIcon: NavIcon
|
||||
}>>([])
|
||||
|
||||
const getNavigationConfig = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => {
|
||||
const getNavigationConfig = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: AppModeEnum) => {
|
||||
const navConfig = [
|
||||
...(isCurrentWorkspaceEditor
|
||||
? [{
|
||||
name: t('common.appMenus.promptEng'),
|
||||
href: `/app/${appId}/${(mode === 'workflow' || mode === 'advanced-chat') ? 'workflow' : 'configuration'}`,
|
||||
href: `/app/${appId}/${(mode === AppModeEnum.WORKFLOW || mode === AppModeEnum.ADVANCED_CHAT) ? 'workflow' : 'configuration'}`,
|
||||
icon: RiTerminalWindowLine,
|
||||
selectedIcon: RiTerminalWindowFill,
|
||||
}]
|
||||
@@ -83,7 +83,7 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
},
|
||||
...(isCurrentWorkspaceEditor
|
||||
? [{
|
||||
name: mode !== 'workflow'
|
||||
name: mode !== AppModeEnum.WORKFLOW
|
||||
? t('common.appMenus.logAndAnn')
|
||||
: t('common.appMenus.logs'),
|
||||
href: `/app/${appId}/logs`,
|
||||
@@ -110,7 +110,7 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
const mode = isMobile ? 'collapse' : 'expand'
|
||||
setAppSidebarExpand(isMobile ? mode : localeMode)
|
||||
// TODO: consider screen size and mode
|
||||
// if ((appDetail.mode === 'advanced-chat' || appDetail.mode === 'workflow') && (pathname).endsWith('workflow'))
|
||||
// if ((appDetail.mode === AppModeEnum.ADVANCED_CHAT || appDetail.mode === 'workflow') && (pathname).endsWith('workflow'))
|
||||
// setAppSidebarExpand('collapse')
|
||||
}
|
||||
}, [appDetail, isMobile])
|
||||
@@ -138,10 +138,10 @@ const AppDetailLayout: FC<IAppDetailLayoutProps> = (props) => {
|
||||
router.replace(`/app/${appId}/overview`)
|
||||
return
|
||||
}
|
||||
if ((res.mode === 'workflow' || res.mode === 'advanced-chat') && (pathname).endsWith('configuration')) {
|
||||
if ((res.mode === AppModeEnum.WORKFLOW || res.mode === AppModeEnum.ADVANCED_CHAT) && (pathname).endsWith('configuration')) {
|
||||
router.replace(`/app/${appId}/workflow`)
|
||||
}
|
||||
else if ((res.mode !== 'workflow' && res.mode !== 'advanced-chat') && (pathname).endsWith('workflow')) {
|
||||
else if ((res.mode !== AppModeEnum.WORKFLOW && res.mode !== AppModeEnum.ADVANCED_CHAT) && (pathname).endsWith('workflow')) {
|
||||
router.replace(`/app/${appId}/configuration`)
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
'use client'
|
||||
import type { FC } from 'react'
|
||||
import React from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import AppCard from '@/app/components/app/overview/app-card'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import MCPServiceCard from '@/app/components/tools/mcp/mcp-service-card'
|
||||
import TriggerCard from '@/app/components/app/overview/trigger-card'
|
||||
import { ToastContext } from '@/app/components/base/toast'
|
||||
import {
|
||||
fetchAppDetail,
|
||||
@@ -14,11 +15,15 @@ import {
|
||||
updateAppSiteStatus,
|
||||
} from '@/service/apps'
|
||||
import type { App } from '@/types/app'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import type { UpdateAppSiteCodeResponse } from '@/models/app'
|
||||
import { asyncRunSafe } from '@/utils'
|
||||
import { NEED_REFRESH_APP_LIST_KEY } from '@/config'
|
||||
import type { IAppCardProps } from '@/app/components/app/overview/app-card'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { useAppWorkflow } from '@/service/use-workflow'
|
||||
import type { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { isTriggerNode } from '@/app/components/workflow/types'
|
||||
|
||||
export type ICardViewProps = {
|
||||
appId: string
|
||||
@@ -33,6 +38,17 @@ const CardView: FC<ICardViewProps> = ({ appId, isInPanel, className }) => {
|
||||
const setAppDetail = useAppStore(state => state.setAppDetail)
|
||||
|
||||
const showMCPCard = isInPanel
|
||||
const showTriggerCard = isInPanel && appDetail?.mode === AppModeEnum.WORKFLOW
|
||||
const { data: currentWorkflow } = useAppWorkflow(appDetail?.mode === AppModeEnum.WORKFLOW ? appDetail.id : '')
|
||||
const hasTriggerNode = useMemo(() => {
|
||||
if (appDetail?.mode !== AppModeEnum.WORKFLOW)
|
||||
return false
|
||||
const nodes = currentWorkflow?.graph?.nodes || []
|
||||
return nodes.some((node) => {
|
||||
const nodeType = node.data?.type as BlockEnum | undefined
|
||||
return !!nodeType && isTriggerNode(nodeType)
|
||||
})
|
||||
}, [appDetail?.mode, currentWorkflow])
|
||||
|
||||
const updateAppDetail = async () => {
|
||||
try {
|
||||
@@ -106,23 +122,35 @@ const CardView: FC<ICardViewProps> = ({ appId, isInPanel, className }) => {
|
||||
|
||||
return (
|
||||
<div className={className || 'mb-6 grid w-full grid-cols-1 gap-6 xl:grid-cols-2'}>
|
||||
<AppCard
|
||||
appInfo={appDetail}
|
||||
cardType="webapp"
|
||||
isInPanel={isInPanel}
|
||||
onChangeStatus={onChangeSiteStatus}
|
||||
onGenerateCode={onGenerateCode}
|
||||
onSaveSiteConfig={onSaveSiteConfig}
|
||||
/>
|
||||
<AppCard
|
||||
cardType="api"
|
||||
appInfo={appDetail}
|
||||
isInPanel={isInPanel}
|
||||
onChangeStatus={onChangeApiStatus}
|
||||
/>
|
||||
{showMCPCard && (
|
||||
<MCPServiceCard
|
||||
{
|
||||
!hasTriggerNode && (
|
||||
<>
|
||||
<AppCard
|
||||
appInfo={appDetail}
|
||||
cardType="webapp"
|
||||
isInPanel={isInPanel}
|
||||
onChangeStatus={onChangeSiteStatus}
|
||||
onGenerateCode={onGenerateCode}
|
||||
onSaveSiteConfig={onSaveSiteConfig}
|
||||
/>
|
||||
<AppCard
|
||||
cardType="api"
|
||||
appInfo={appDetail}
|
||||
isInPanel={isInPanel}
|
||||
onChangeStatus={onChangeApiStatus}
|
||||
/>
|
||||
{showMCPCard && (
|
||||
<MCPServiceCard
|
||||
appInfo={appDetail}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
{showTriggerCard && (
|
||||
<TriggerCard
|
||||
appInfo={appDetail}
|
||||
onToggleResult={handleCallbackResult}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ProviderContextProvider } from '@/context/provider-context'
|
||||
import { ModalContextProvider } from '@/context/modal-context'
|
||||
import GotoAnything from '@/app/components/goto-anything'
|
||||
import Zendesk from '@/app/components/base/zendesk'
|
||||
import ReadmePanel from '@/app/components/plugins/readme-panel'
|
||||
import Splash from '../components/splash'
|
||||
|
||||
const Layout = ({ children }: { children: ReactNode }) => {
|
||||
@@ -25,6 +26,7 @@ const Layout = ({ children }: { children: ReactNode }) => {
|
||||
<Header />
|
||||
</HeaderWrapper>
|
||||
{children}
|
||||
<ReadmePanel />
|
||||
<GotoAnything />
|
||||
<Splash />
|
||||
</ModalContextProvider>
|
||||
|
||||
Reference in New Issue
Block a user