mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 10:06:51 +08:00
fix(web): workflow switch to evaluation
This commit is contained in:
parent
00319f0e43
commit
b0478f4df7
@ -1,7 +1,6 @@
|
||||
import type { AppPublisherProps } from '@/app/components/app/app-publisher'
|
||||
import type { ModelAndParameter } from '@/app/components/app/configuration/debug/types'
|
||||
import type { FileUpload } from '@/app/components/base/features/types'
|
||||
import type { PublishWorkflowParams } from '@/types/workflow'
|
||||
import type { AppPublisherProps, AppPublisherPublishParams } from '@/app/components/app/app-publisher'
|
||||
import type { Features, FileUpload } from '@/app/components/base/features/types'
|
||||
import type { ModelConfig } from '@/models/debug'
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogActions,
|
||||
@ -21,9 +20,15 @@ import { FILE_EXTS } from '@/app/components/base/prompt-editor/constants'
|
||||
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
|
||||
import { Resolution } from '@/types/app'
|
||||
|
||||
type PublishedModelConfig = ModelConfig & {
|
||||
resetAppConfig?: () => void
|
||||
}
|
||||
|
||||
type Props = Omit<AppPublisherProps, 'onPublish'> & {
|
||||
onPublish?: (params?: ModelAndParameter | PublishWorkflowParams, features?: any) => Promise<any> | any
|
||||
publishedConfig?: any
|
||||
onPublish?: (params?: AppPublisherPublishParams, features?: Features) => Promise<unknown> | unknown
|
||||
publishedConfig: {
|
||||
modelConfig: PublishedModelConfig
|
||||
}
|
||||
resetAppConfig?: () => void
|
||||
}
|
||||
|
||||
@ -71,7 +76,7 @@ const FeaturesWrappedAppPublisher = (props: Props) => {
|
||||
setRestoreConfirmOpen(false)
|
||||
}, [featuresStore, props])
|
||||
|
||||
const handlePublish = useCallback((params?: ModelAndParameter | PublishWorkflowParams) => {
|
||||
const handlePublish = useCallback((params?: AppPublisherPublishParams) => {
|
||||
return props.onPublish?.(params, features)
|
||||
}, [features, props])
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import type { ModelAndParameter } from '../configuration/debug/types'
|
||||
import type { CollaborationUpdate } from '@/app/components/workflow/collaboration/types/collaboration'
|
||||
import type { InputVar, Variable } from '@/app/components/workflow/types'
|
||||
import type { EvaluationWorkflowAssociatedTarget } from '@/types/evaluation'
|
||||
import type { I18nKeysWithPrefix } from '@/types/i18n'
|
||||
import type { PublishWorkflowParams, WorkflowTypeConversionTarget } from '@/types/workflow'
|
||||
import type { PublishWorkflowParams } from '@/types/workflow'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
@ -32,11 +30,9 @@ import { useAppWhiteListSubjects, useGetUserCanAccessApp } from '@/service/acces
|
||||
import { fetchAppDetailDirect, publishToCreatorsPlatform } from '@/service/apps'
|
||||
import { fetchInstalledAppList } from '@/service/explore'
|
||||
import { systemFeaturesQueryOptions } from '@/service/system-features'
|
||||
import { useConvertWorkflowTypeMutation } from '@/service/use-apps'
|
||||
import { useEvaluationWorkflowAssociatedTargets } from '@/service/use-evaluation'
|
||||
import { useInvalidateAppWorkflow } from '@/service/use-workflow'
|
||||
import { fetchPublishedWorkflow } from '@/service/workflow'
|
||||
import { AppModeEnum, AppTypeEnum } from '@/types/app'
|
||||
import { AppModeEnum } from '@/types/app'
|
||||
import { basePath } from '@/utils/var'
|
||||
import { getKeyboardKeyCodeBySystem } from '../../workflow/utils'
|
||||
import AccessControl from '../app-access-control'
|
||||
@ -47,12 +43,20 @@ import {
|
||||
PublisherSummarySection,
|
||||
} from './sections'
|
||||
import SuggestedAction from './suggested-action'
|
||||
import { useWorkflowTypeSwitch } from './use-workflow-type-switch'
|
||||
import {
|
||||
getDisabledFunctionTooltip,
|
||||
getPublisherAppUrl,
|
||||
isPublisherAccessConfigured,
|
||||
} from './utils'
|
||||
|
||||
export type AppPublisherPublishParams
|
||||
= | ModelAndParameter
|
||||
| (Pick<PublishWorkflowParams, 'title' | 'releaseNotes'> & {
|
||||
url?: string
|
||||
id?: string
|
||||
})
|
||||
|
||||
export type AppPublisherProps = {
|
||||
disabled?: boolean
|
||||
publishDisabled?: boolean
|
||||
@ -62,8 +66,8 @@ export type AppPublisherProps = {
|
||||
debugWithMultipleModel?: boolean
|
||||
multipleModelConfigs?: ModelAndParameter[]
|
||||
/** modelAndParameter is passed when debugWithMultipleModel is true */
|
||||
onPublish?: (params?: any) => Promise<any> | any
|
||||
onRestore?: () => Promise<any> | any
|
||||
onPublish?: (params?: AppPublisherPublishParams) => Promise<unknown> | unknown
|
||||
onRestore?: () => Promise<unknown> | unknown
|
||||
onToggle?: (state: boolean) => void
|
||||
crossAxisOffset?: number
|
||||
toolPublished?: boolean
|
||||
@ -79,32 +83,6 @@ export type AppPublisherProps = {
|
||||
|
||||
const PUBLISH_SHORTCUT = ['ctrl', '⇧', 'P']
|
||||
|
||||
type WorkflowTypeSwitchLabelKey = I18nKeysWithPrefix<'workflow', 'common.'>
|
||||
|
||||
const WORKFLOW_TYPE_SWITCH_CONFIG: Record<WorkflowTypeConversionTarget, {
|
||||
targetType: WorkflowTypeConversionTarget
|
||||
publishLabelKey: WorkflowTypeSwitchLabelKey
|
||||
switchLabelKey: WorkflowTypeSwitchLabelKey
|
||||
tipKey: WorkflowTypeSwitchLabelKey
|
||||
}> = {
|
||||
workflow: {
|
||||
targetType: 'evaluation',
|
||||
publishLabelKey: 'common.publishAsEvaluationWorkflow',
|
||||
switchLabelKey: 'common.switchToEvaluationWorkflow',
|
||||
tipKey: 'common.switchToEvaluationWorkflowTip',
|
||||
},
|
||||
evaluation: {
|
||||
targetType: 'workflow',
|
||||
publishLabelKey: 'common.publishAsStandardWorkflow',
|
||||
switchLabelKey: 'common.switchToStandardWorkflow',
|
||||
tipKey: 'common.switchToStandardWorkflowTip',
|
||||
},
|
||||
} as const
|
||||
|
||||
const isWorkflowTypeConversionTarget = (type?: AppTypeEnum): type is WorkflowTypeConversionTarget => {
|
||||
return type === 'workflow' || type === 'evaluation'
|
||||
}
|
||||
|
||||
const AppPublisher = ({
|
||||
disabled = false,
|
||||
publishDisabled = false,
|
||||
@ -131,8 +109,6 @@ const AppPublisher = ({
|
||||
const [published, setPublished] = useState(false)
|
||||
const [open, setOpen] = useState(false)
|
||||
const [showAppAccessControl, setShowAppAccessControl] = useState(false)
|
||||
const [showEvaluationWorkflowSwitchConfirm, setShowEvaluationWorkflowSwitchConfirm] = useState(false)
|
||||
const [evaluationWorkflowSwitchTargets, setEvaluationWorkflowSwitchTargets] = useState<EvaluationWorkflowAssociatedTarget[]>([])
|
||||
|
||||
const [embeddingModalOpen, setEmbeddingModalOpen] = useState(false)
|
||||
const [publishingToMarketplace, setPublishingToMarketplace] = useState(false)
|
||||
@ -144,36 +120,9 @@ const AppPublisher = ({
|
||||
const { data: systemFeatures } = useSuspenseQuery(systemFeaturesQueryOptions())
|
||||
const { formatTimeFromNow } = useFormatTimeFromNow()
|
||||
const { app_base_url: appBaseURL = '', access_token: accessToken = '' } = appDetail?.site ?? {}
|
||||
const { mutateAsync: convertWorkflowType, isPending: isConvertingWorkflowType } = useConvertWorkflowTypeMutation()
|
||||
|
||||
const appURL = getPublisherAppUrl({ appBaseUrl: appBaseURL, accessToken, mode: appDetail?.mode })
|
||||
const isChatApp = [AppModeEnum.CHAT, AppModeEnum.AGENT_CHAT, AppModeEnum.COMPLETION].includes(appDetail?.mode || AppModeEnum.CHAT)
|
||||
const workflowTypeSwitchConfig = useMemo(() => {
|
||||
if (!appDetail?.workflow_kind)
|
||||
return WORKFLOW_TYPE_SWITCH_CONFIG.workflow
|
||||
|
||||
if (!isWorkflowTypeConversionTarget(appDetail?.workflow_kind))
|
||||
return undefined
|
||||
|
||||
return WORKFLOW_TYPE_SWITCH_CONFIG[appDetail.workflow_kind]
|
||||
}, [appDetail?.workflow_kind])
|
||||
const isEvaluationWorkflowType = appDetail?.workflow_kind === AppTypeEnum.EVALUATION
|
||||
const {
|
||||
refetch: refetchEvaluationWorkflowAssociatedTargets,
|
||||
isFetching: isFetchingEvaluationWorkflowAssociatedTargets,
|
||||
} = useEvaluationWorkflowAssociatedTargets(appDetail?.id, { enabled: false })
|
||||
const workflowTypeSwitchDisabledReason = useMemo(() => {
|
||||
if (workflowTypeSwitchConfig?.targetType !== AppTypeEnum.EVALUATION)
|
||||
return undefined
|
||||
|
||||
if (!canAccessSnippetsAndEvaluation)
|
||||
return t('compliance.sandboxUpgradeTooltip', { ns: 'common' })
|
||||
|
||||
if (!hasHumanInputNode && !hasTriggerNode)
|
||||
return undefined
|
||||
|
||||
return t('common.switchToEvaluationWorkflowDisabledTip', { ns: 'workflow' })
|
||||
}, [canAccessSnippetsAndEvaluation, hasHumanInputNode, hasTriggerNode, t, workflowTypeSwitchConfig?.targetType])
|
||||
|
||||
const { data: userCanAccessApp, isLoading: isGettingUserCanAccessApp, refetch } = useGetUserCanAccessApp({ appId: appDetail?.id, enabled: false })
|
||||
const { data: appAccessSubjects, isLoading: isGettingAppWhiteListSubjects } = useAppWhiteListSubjects(appDetail?.id, open && systemFeatures.webapp_auth.enabled && appDetail?.access_mode === AccessMode.SPECIFIC_GROUPS_MEMBERS)
|
||||
@ -201,7 +150,7 @@ const AppPublisher = ({
|
||||
refetch()
|
||||
}, [open, appDetail, refetch, systemFeatures])
|
||||
|
||||
const handlePublish = useCallback(async (params?: ModelAndParameter | PublishWorkflowParams) => {
|
||||
const handlePublish = useCallback(async (params?: AppPublisherPublishParams) => {
|
||||
try {
|
||||
await onPublish?.(params)
|
||||
setPublished(true)
|
||||
@ -283,110 +232,34 @@ const AppPublisher = ({
|
||||
}
|
||||
}, [appDetail, setAppDetail])
|
||||
|
||||
const getWorkflowTypeSwitchPublishUrl = useCallback(() => {
|
||||
if (!appDetail?.id || !workflowTypeSwitchConfig)
|
||||
return undefined
|
||||
|
||||
if (workflowTypeSwitchConfig.targetType === AppTypeEnum.EVALUATION)
|
||||
return `/apps/${appDetail.id}/workflows/publish/evaluation`
|
||||
|
||||
return `/apps/${appDetail.id}/workflows/publish`
|
||||
}, [appDetail?.id, workflowTypeSwitchConfig])
|
||||
|
||||
const performWorkflowTypeSwitch = useCallback(async () => {
|
||||
if (!appDetail?.id || !workflowTypeSwitchConfig)
|
||||
return false
|
||||
|
||||
try {
|
||||
if (!publishedAt) {
|
||||
const publishUrl = getWorkflowTypeSwitchPublishUrl()
|
||||
if (!publishUrl)
|
||||
return false
|
||||
|
||||
await handlePublish({
|
||||
url: publishUrl,
|
||||
title: '',
|
||||
releaseNotes: '',
|
||||
})
|
||||
|
||||
const latestAppDetail = await fetchAppDetailDirect({
|
||||
url: '/apps',
|
||||
id: appDetail.id,
|
||||
})
|
||||
setAppDetail(latestAppDetail)
|
||||
setShowEvaluationWorkflowSwitchConfirm(false)
|
||||
setEvaluationWorkflowSwitchTargets([])
|
||||
return true
|
||||
}
|
||||
|
||||
await convertWorkflowType({
|
||||
params: {
|
||||
appId: appDetail.id,
|
||||
},
|
||||
query: {
|
||||
target_type: workflowTypeSwitchConfig.targetType,
|
||||
},
|
||||
})
|
||||
|
||||
const latestAppDetail = await fetchAppDetailDirect({
|
||||
url: '/apps',
|
||||
id: appDetail.id,
|
||||
})
|
||||
setAppDetail(latestAppDetail)
|
||||
|
||||
if (publishedAt)
|
||||
setOpen(false)
|
||||
|
||||
setShowEvaluationWorkflowSwitchConfirm(false)
|
||||
setEvaluationWorkflowSwitchTargets([])
|
||||
return true
|
||||
}
|
||||
catch {
|
||||
return false
|
||||
}
|
||||
}, [appDetail?.id, convertWorkflowType, getWorkflowTypeSwitchPublishUrl, handlePublish, publishedAt, setAppDetail, workflowTypeSwitchConfig])
|
||||
|
||||
const handleWorkflowTypeSwitch = useCallback(async () => {
|
||||
if (!appDetail?.id || !workflowTypeSwitchConfig)
|
||||
return
|
||||
if (workflowTypeSwitchDisabledReason) {
|
||||
toast.error(workflowTypeSwitchDisabledReason)
|
||||
return
|
||||
}
|
||||
|
||||
if (appDetail.workflow_kind === AppTypeEnum.EVALUATION && workflowTypeSwitchConfig.targetType === AppTypeEnum.WORKFLOW) {
|
||||
const associatedTargetsResult = await refetchEvaluationWorkflowAssociatedTargets()
|
||||
|
||||
if (associatedTargetsResult.isError) {
|
||||
toast.error(t('common.switchToStandardWorkflowConfirm.loadFailed', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
|
||||
const associatedTargets = associatedTargetsResult.data?.items ?? []
|
||||
if (associatedTargets.length > 0) {
|
||||
setEvaluationWorkflowSwitchTargets(associatedTargets)
|
||||
setShowEvaluationWorkflowSwitchConfirm(true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
await performWorkflowTypeSwitch()
|
||||
}, [
|
||||
appDetail?.id,
|
||||
appDetail?.workflow_kind,
|
||||
performWorkflowTypeSwitch,
|
||||
refetchEvaluationWorkflowAssociatedTargets,
|
||||
t,
|
||||
workflowTypeSwitchConfig,
|
||||
workflowTypeSwitchDisabledReason,
|
||||
])
|
||||
|
||||
const handleEvaluationWorkflowSwitchConfirmOpenChange = useCallback((nextOpen: boolean) => {
|
||||
setShowEvaluationWorkflowSwitchConfirm(nextOpen)
|
||||
|
||||
if (!nextOpen)
|
||||
setEvaluationWorkflowSwitchTargets([])
|
||||
const handlePublishedWorkflowTypeSwitch = useCallback(() => {
|
||||
setOpen(false)
|
||||
}, [])
|
||||
|
||||
const {
|
||||
evaluationWorkflowSwitchTargets,
|
||||
handleEvaluationWorkflowSwitchConfirmOpenChange,
|
||||
handleWorkflowTypeSwitch,
|
||||
isConvertingWorkflowType,
|
||||
isEvaluationWorkflowType,
|
||||
performWorkflowTypeSwitch,
|
||||
showEvaluationWorkflowSwitchConfirm,
|
||||
workflowTypeSwitchConfig,
|
||||
workflowTypeSwitchDisabled,
|
||||
workflowTypeSwitchDisabledReason,
|
||||
} = useWorkflowTypeSwitch({
|
||||
appDetail,
|
||||
canAccessSnippetsAndEvaluation,
|
||||
hasHumanInputNode,
|
||||
hasTriggerNode,
|
||||
onPublish: handlePublish,
|
||||
onPublishedSwitch: handlePublishedWorkflowTypeSwitch,
|
||||
published,
|
||||
publishedAt,
|
||||
publishDisabled,
|
||||
setAppDetail,
|
||||
})
|
||||
|
||||
const handlePublishToMarketplace = useCallback(async () => {
|
||||
if (!appDetail?.id || publishingToMarketplace)
|
||||
return
|
||||
@ -485,7 +358,7 @@ const AppPublisher = ({
|
||||
startNodeLimitExceeded={startNodeLimitExceeded}
|
||||
upgradeHighlightStyle={upgradeHighlightStyle}
|
||||
workflowTypeSwitchConfig={workflowTypeSwitchConfig}
|
||||
workflowTypeSwitchDisabled={publishDisabled || published || isConvertingWorkflowType || isFetchingEvaluationWorkflowAssociatedTargets || Boolean(workflowTypeSwitchDisabledReason)}
|
||||
workflowTypeSwitchDisabled={workflowTypeSwitchDisabled}
|
||||
workflowTypeSwitchDisabledReason={workflowTypeSwitchDisabledReason}
|
||||
onWorkflowTypeSwitch={handleWorkflowTypeSwitch}
|
||||
/>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import type { CSSProperties, ReactNode } from 'react'
|
||||
import type { ModelAndParameter } from '../configuration/debug/types'
|
||||
import type { AppPublisherProps } from './index'
|
||||
import type { I18nKeysWithPrefix } from '@/types/i18n'
|
||||
import type { PublishWorkflowParams, WorkflowTypeConversionTarget } from '@/types/workflow'
|
||||
import type { WorkflowTypeSwitchConfig } from './use-workflow-type-switch'
|
||||
import type { PublishWorkflowParams } from '@/types/workflow'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import {
|
||||
Tooltip,
|
||||
@ -21,8 +21,6 @@ import PublishWithMultipleModel from './publish-with-multiple-model'
|
||||
import SuggestedAction from './suggested-action'
|
||||
import { ACCESS_MODE_MAP } from './utils'
|
||||
|
||||
type WorkflowTypeSwitchLabelKey = I18nKeysWithPrefix<'workflow', 'common.'>
|
||||
|
||||
type SummarySectionProps = Pick<AppPublisherProps, | 'debugWithMultipleModel'
|
||||
| 'draftUpdatedAt'
|
||||
| 'multipleModelConfigs'
|
||||
@ -37,12 +35,7 @@ type SummarySectionProps = Pick<AppPublisherProps, | 'debugWithMultipleModel'
|
||||
published: boolean
|
||||
publishShortcut: string[]
|
||||
upgradeHighlightStyle: CSSProperties
|
||||
workflowTypeSwitchConfig?: {
|
||||
targetType: WorkflowTypeConversionTarget
|
||||
publishLabelKey: WorkflowTypeSwitchLabelKey
|
||||
switchLabelKey: WorkflowTypeSwitchLabelKey
|
||||
tipKey: WorkflowTypeSwitchLabelKey
|
||||
}
|
||||
workflowTypeSwitchConfig?: WorkflowTypeSwitchConfig
|
||||
workflowTypeSwitchDisabled: boolean
|
||||
workflowTypeSwitchDisabledReason?: string
|
||||
}
|
||||
|
||||
229
web/app/components/app/app-publisher/use-workflow-type-switch.ts
Normal file
229
web/app/components/app/app-publisher/use-workflow-type-switch.ts
Normal file
@ -0,0 +1,229 @@
|
||||
import type { ModelAndParameter } from '../configuration/debug/types'
|
||||
import type { App, AppSSO } from '@/types/app'
|
||||
import type { EvaluationWorkflowAssociatedTarget } from '@/types/evaluation'
|
||||
import type { I18nKeysWithPrefix } from '@/types/i18n'
|
||||
import type { PublishWorkflowParams, WorkflowKind, WorkflowTypeConversionTarget } from '@/types/workflow'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { fetchAppDetailDirect } from '@/service/apps'
|
||||
import { useConvertWorkflowTypeMutation } from '@/service/use-apps'
|
||||
import { useEvaluationWorkflowAssociatedTargets } from '@/service/use-evaluation'
|
||||
import { AppTypeEnum } from '@/types/app'
|
||||
|
||||
type WorkflowTypeSwitchLabelKey = I18nKeysWithPrefix<'workflow', 'common.'>
|
||||
|
||||
export type WorkflowTypeSwitchConfig = {
|
||||
targetType: WorkflowTypeConversionTarget
|
||||
publishLabelKey: WorkflowTypeSwitchLabelKey
|
||||
switchLabelKey: WorkflowTypeSwitchLabelKey
|
||||
tipKey: WorkflowTypeSwitchLabelKey
|
||||
}
|
||||
|
||||
const WORKFLOW_TYPE_SWITCH_CONFIG: Record<WorkflowTypeConversionTarget, WorkflowTypeSwitchConfig> = {
|
||||
workflow: {
|
||||
targetType: 'evaluation',
|
||||
publishLabelKey: 'common.publishAsEvaluationWorkflow',
|
||||
switchLabelKey: 'common.switchToEvaluationWorkflow',
|
||||
tipKey: 'common.switchToEvaluationWorkflowTip',
|
||||
},
|
||||
evaluation: {
|
||||
targetType: 'workflow',
|
||||
publishLabelKey: 'common.publishAsStandardWorkflow',
|
||||
switchLabelKey: 'common.switchToStandardWorkflow',
|
||||
tipKey: 'common.switchToStandardWorkflowTip',
|
||||
},
|
||||
} as const
|
||||
|
||||
const getWorkflowTypeSwitchConfig = (workflowKind?: WorkflowKind | null) => {
|
||||
if (!workflowKind || workflowKind === 'standard')
|
||||
return WORKFLOW_TYPE_SWITCH_CONFIG.workflow
|
||||
|
||||
if (workflowKind === 'evaluation')
|
||||
return WORKFLOW_TYPE_SWITCH_CONFIG.evaluation
|
||||
}
|
||||
|
||||
type UseWorkflowTypeSwitchParams = {
|
||||
appDetail?: App & Partial<AppSSO>
|
||||
canAccessSnippetsAndEvaluation: boolean
|
||||
hasHumanInputNode: boolean
|
||||
hasTriggerNode: boolean
|
||||
onPublish: (params?: ModelAndParameter | PublishWorkflowParams) => Promise<void>
|
||||
onPublishedSwitch: () => void
|
||||
published: boolean
|
||||
publishedAt?: number
|
||||
publishDisabled: boolean
|
||||
setAppDetail: (appDetail?: App & Partial<AppSSO>) => void
|
||||
}
|
||||
|
||||
export const useWorkflowTypeSwitch = ({
|
||||
appDetail,
|
||||
canAccessSnippetsAndEvaluation,
|
||||
hasHumanInputNode,
|
||||
hasTriggerNode,
|
||||
onPublish,
|
||||
onPublishedSwitch,
|
||||
published,
|
||||
publishedAt,
|
||||
publishDisabled,
|
||||
setAppDetail,
|
||||
}: UseWorkflowTypeSwitchParams) => {
|
||||
const { t } = useTranslation()
|
||||
const [showEvaluationWorkflowSwitchConfirm, setShowEvaluationWorkflowSwitchConfirm] = useState(false)
|
||||
const [evaluationWorkflowSwitchTargets, setEvaluationWorkflowSwitchTargets] = useState<EvaluationWorkflowAssociatedTarget[]>([])
|
||||
const { mutateAsync: convertWorkflowType, isPending: isConvertingWorkflowType } = useConvertWorkflowTypeMutation()
|
||||
const {
|
||||
refetch: refetchEvaluationWorkflowAssociatedTargets,
|
||||
isFetching: isFetchingEvaluationWorkflowAssociatedTargets,
|
||||
} = useEvaluationWorkflowAssociatedTargets(appDetail?.id, { enabled: false })
|
||||
|
||||
const workflowTypeSwitchConfig = useMemo(() => {
|
||||
return getWorkflowTypeSwitchConfig(appDetail?.workflow_kind)
|
||||
}, [appDetail?.workflow_kind])
|
||||
|
||||
const workflowTypeSwitchDisabledReason = useMemo(() => {
|
||||
if (workflowTypeSwitchConfig?.targetType !== AppTypeEnum.EVALUATION)
|
||||
return undefined
|
||||
|
||||
if (!canAccessSnippetsAndEvaluation)
|
||||
return t('compliance.sandboxUpgradeTooltip', { ns: 'common' })
|
||||
|
||||
if (!hasHumanInputNode && !hasTriggerNode)
|
||||
return undefined
|
||||
|
||||
return t('common.switchToEvaluationWorkflowDisabledTip', { ns: 'workflow' })
|
||||
}, [canAccessSnippetsAndEvaluation, hasHumanInputNode, hasTriggerNode, t, workflowTypeSwitchConfig?.targetType])
|
||||
|
||||
const getWorkflowTypeSwitchPublishUrl = useCallback(() => {
|
||||
if (!appDetail?.id || !workflowTypeSwitchConfig)
|
||||
return undefined
|
||||
|
||||
if (workflowTypeSwitchConfig.targetType === AppTypeEnum.EVALUATION)
|
||||
return `/apps/${appDetail.id}/workflows/publish/evaluation`
|
||||
|
||||
return `/apps/${appDetail.id}/workflows/publish`
|
||||
}, [appDetail?.id, workflowTypeSwitchConfig])
|
||||
|
||||
const resetEvaluationWorkflowSwitchConfirm = useCallback(() => {
|
||||
setShowEvaluationWorkflowSwitchConfirm(false)
|
||||
setEvaluationWorkflowSwitchTargets([])
|
||||
}, [])
|
||||
|
||||
const performWorkflowTypeSwitch = useCallback(async () => {
|
||||
if (!appDetail?.id || !workflowTypeSwitchConfig)
|
||||
return false
|
||||
|
||||
try {
|
||||
if (!publishedAt) {
|
||||
const publishUrl = getWorkflowTypeSwitchPublishUrl()
|
||||
if (!publishUrl)
|
||||
return false
|
||||
|
||||
await onPublish({
|
||||
url: publishUrl,
|
||||
title: '',
|
||||
releaseNotes: '',
|
||||
})
|
||||
|
||||
const latestAppDetail = await fetchAppDetailDirect({
|
||||
url: '/apps',
|
||||
id: appDetail.id,
|
||||
})
|
||||
setAppDetail(latestAppDetail)
|
||||
resetEvaluationWorkflowSwitchConfirm()
|
||||
return true
|
||||
}
|
||||
|
||||
await convertWorkflowType({
|
||||
params: {
|
||||
appId: appDetail.id,
|
||||
},
|
||||
query: {
|
||||
target_type: workflowTypeSwitchConfig.targetType,
|
||||
},
|
||||
})
|
||||
|
||||
const latestAppDetail = await fetchAppDetailDirect({
|
||||
url: '/apps',
|
||||
id: appDetail.id,
|
||||
})
|
||||
setAppDetail(latestAppDetail)
|
||||
onPublishedSwitch()
|
||||
resetEvaluationWorkflowSwitchConfirm()
|
||||
return true
|
||||
}
|
||||
catch {
|
||||
return false
|
||||
}
|
||||
}, [
|
||||
appDetail?.id,
|
||||
convertWorkflowType,
|
||||
getWorkflowTypeSwitchPublishUrl,
|
||||
onPublish,
|
||||
onPublishedSwitch,
|
||||
publishedAt,
|
||||
resetEvaluationWorkflowSwitchConfirm,
|
||||
setAppDetail,
|
||||
workflowTypeSwitchConfig,
|
||||
])
|
||||
|
||||
const handleWorkflowTypeSwitch = useCallback(async () => {
|
||||
if (!appDetail?.id || !workflowTypeSwitchConfig)
|
||||
return
|
||||
|
||||
if (workflowTypeSwitchDisabledReason) {
|
||||
toast.error(workflowTypeSwitchDisabledReason)
|
||||
return
|
||||
}
|
||||
|
||||
if (appDetail.workflow_kind === AppTypeEnum.EVALUATION && workflowTypeSwitchConfig.targetType === AppTypeEnum.WORKFLOW) {
|
||||
const associatedTargetsResult = await refetchEvaluationWorkflowAssociatedTargets()
|
||||
|
||||
if (associatedTargetsResult.isError) {
|
||||
toast.error(t('common.switchToStandardWorkflowConfirm.loadFailed', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
|
||||
const associatedTargets = associatedTargetsResult.data?.items ?? []
|
||||
if (associatedTargets.length > 0) {
|
||||
setEvaluationWorkflowSwitchTargets(associatedTargets)
|
||||
setShowEvaluationWorkflowSwitchConfirm(true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
await performWorkflowTypeSwitch()
|
||||
}, [
|
||||
appDetail?.id,
|
||||
appDetail?.workflow_kind,
|
||||
performWorkflowTypeSwitch,
|
||||
refetchEvaluationWorkflowAssociatedTargets,
|
||||
t,
|
||||
workflowTypeSwitchConfig,
|
||||
workflowTypeSwitchDisabledReason,
|
||||
])
|
||||
|
||||
const handleEvaluationWorkflowSwitchConfirmOpenChange = useCallback((nextOpen: boolean) => {
|
||||
setShowEvaluationWorkflowSwitchConfirm(nextOpen)
|
||||
|
||||
if (!nextOpen)
|
||||
setEvaluationWorkflowSwitchTargets([])
|
||||
}, [])
|
||||
|
||||
return {
|
||||
evaluationWorkflowSwitchTargets,
|
||||
handleEvaluationWorkflowSwitchConfirmOpenChange,
|
||||
handleWorkflowTypeSwitch,
|
||||
isConvertingWorkflowType,
|
||||
isEvaluationWorkflowType: appDetail?.workflow_kind === AppTypeEnum.EVALUATION,
|
||||
performWorkflowTypeSwitch,
|
||||
showEvaluationWorkflowSwitchConfirm,
|
||||
workflowTypeSwitchConfig,
|
||||
workflowTypeSwitchDisabled: publishDisabled
|
||||
|| published
|
||||
|| isConvertingWorkflowType
|
||||
|| isFetchingEvaluationWorkflowAssociatedTargets
|
||||
|| Boolean(workflowTypeSwitchDisabledReason),
|
||||
workflowTypeSwitchDisabledReason,
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
'use client'
|
||||
import type { ComponentProps } from 'react'
|
||||
import type { AppPublisherPublishParams } from '@/app/components/app/app-publisher'
|
||||
import type AppPublisher from '@/app/components/app/app-publisher/features-wrapper'
|
||||
import type { ModelAndParameter } from '@/app/components/app/configuration/debug/types'
|
||||
import type { Features as FeaturesData, OnFeaturesChange } from '@/app/components/base/features/types'
|
||||
@ -21,7 +22,6 @@ import type {
|
||||
TextToSpeechConfig,
|
||||
} from '@/models/debug'
|
||||
import type { VisionSettings } from '@/types/app'
|
||||
import type { PublishWorkflowParams } from '@/types/workflow'
|
||||
import { useBoolean, useGetState } from 'ahooks'
|
||||
import { clone } from 'es-toolkit/object'
|
||||
import { produce } from 'immer'
|
||||
@ -481,7 +481,7 @@ export const useConfiguration = (): ConfigurationViewModel => {
|
||||
resolvedModelModeType,
|
||||
])
|
||||
|
||||
const onPublish = useCallback(async (params?: ModelAndParameter | PublishWorkflowParams, features?: FeaturesData) => {
|
||||
const onPublish = useCallback(async (params?: AppPublisherPublishParams, features?: FeaturesData) => {
|
||||
const modelAndParameter = params && 'model' in params && 'provider' in params && 'parameters' in params
|
||||
? params
|
||||
: undefined
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import type { ModelAndParameter } from '@/app/components/app/configuration/debug/types'
|
||||
import type { AppPublisherPublishParams } from '@/app/components/app/app-publisher'
|
||||
import type { EndNodeType } from '@/app/components/workflow/nodes/end/types'
|
||||
import type { StartNodeType } from '@/app/components/workflow/nodes/start/types'
|
||||
import type {
|
||||
CommonEdgeType,
|
||||
Node,
|
||||
} from '@/app/components/workflow/types'
|
||||
import type { PublishWorkflowParams } from '@/types/workflow'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
@ -144,7 +143,7 @@ const FeaturesTrigger = () => {
|
||||
const needWarningNodes = useChecklist(nodes, edges)
|
||||
|
||||
const updatePublishedWorkflow = useInvalidateAppWorkflow()
|
||||
const onPublish = useCallback(async (params?: ModelAndParameter | PublishWorkflowParams) => {
|
||||
const onPublish = useCallback(async (params?: AppPublisherPublishParams) => {
|
||||
const publishParams = params && 'title' in params ? params : undefined
|
||||
// First check if there are any items in the checklist
|
||||
// if (!validateBeforeRun())
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { WorkflowKind } from '@/types/workflow'
|
||||
import { AppTypeEnum } from '@/types/app'
|
||||
import { BlockEnum, TRIGGER_NODE_TYPES } from '../types'
|
||||
|
||||
@ -6,7 +7,7 @@ const EVALUATION_WORKFLOW_RESTRICTED_NODE_TYPES = new Set<string>([
|
||||
...TRIGGER_NODE_TYPES,
|
||||
])
|
||||
|
||||
export const isEvaluationWorkflow = (appType?: string) => appType === AppTypeEnum.EVALUATION
|
||||
export const isEvaluationWorkflow = (appType?: WorkflowKind | null) => appType === AppTypeEnum.EVALUATION
|
||||
|
||||
export const isEvaluationWorkflowRestrictedNodeType = (nodeType?: string) => {
|
||||
if (!nodeType)
|
||||
|
||||
@ -9,6 +9,7 @@ import type {
|
||||
WeightedScoreEnum,
|
||||
} from '@/models/datasets'
|
||||
import type { AnnotationReplyConfig, ChatPromptConfig, CompletionPromptConfig, DatasetConfigs, PromptMode } from '@/models/debug'
|
||||
import type { WorkflowKind } from '@/types/workflow'
|
||||
|
||||
export type Theme = 'light' | 'dark' | 'system'
|
||||
export const Theme = {
|
||||
@ -392,7 +393,7 @@ export type App = {
|
||||
/** whether workflow trigger has un-published draft */
|
||||
has_draft_trigger?: boolean
|
||||
/** Type */
|
||||
workflow_kind?: AppTypeEnum
|
||||
workflow_kind?: WorkflowKind | null
|
||||
}
|
||||
|
||||
export type AppSSO = {
|
||||
|
||||
@ -429,6 +429,8 @@ export type PublishWorkflowParams = {
|
||||
|
||||
export type WorkflowTypeConversionTarget = 'workflow' | 'evaluation'
|
||||
|
||||
export type WorkflowKind = 'standard' | 'evaluation'
|
||||
|
||||
export type UpdateWorkflowParams = {
|
||||
url: string
|
||||
title: string
|
||||
|
||||
Loading…
Reference in New Issue
Block a user