mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 10:06:51 +08:00
fix(web): selected workflow name fix
This commit is contained in:
parent
552f202ca8
commit
3763efbc7c
@ -12,6 +12,7 @@ import CustomMetricEditorCard from '..'
|
||||
import { useEvaluationStore } from '../../../store'
|
||||
|
||||
const mockUseAppWorkflow = vi.hoisted(() => vi.fn())
|
||||
const mockUseAppDetail = vi.hoisted(() => vi.fn())
|
||||
const mockUseSnippetPublishedWorkflow = vi.hoisted(() => vi.fn())
|
||||
const mockUseAvailableEvaluationWorkflows = vi.hoisted(() => vi.fn())
|
||||
const mockUseInfiniteScroll = vi.hoisted(() => vi.fn())
|
||||
@ -21,6 +22,10 @@ vi.mock('@/service/use-workflow', () => ({
|
||||
useAppWorkflow: (...args: unknown[]) => mockUseAppWorkflow(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/service/use-apps', () => ({
|
||||
useAppDetail: (...args: unknown[]) => mockUseAppDetail(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/service/use-snippet-workflows', () => ({
|
||||
useSnippetPublishedWorkflow: (...args: unknown[]) => mockUseSnippetPublishedWorkflow(...args),
|
||||
}))
|
||||
@ -179,6 +184,7 @@ describe('CustomMetricEditorCard', () => {
|
||||
vi.clearAllMocks()
|
||||
useEvaluationStore.setState({ resources: {} })
|
||||
mockPublishedGraphVariablePicker.mockReset()
|
||||
mockUseAppDetail.mockReturnValue({ data: undefined })
|
||||
|
||||
mockUseInfiniteScroll.mockImplementation(() => undefined)
|
||||
mockUseAvailableEvaluationWorkflows.mockReturnValue({
|
||||
@ -305,6 +311,46 @@ describe('CustomMetricEditorCard', () => {
|
||||
expect(syncOutputsSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should show the selected workflow app name from app detail when the config only has workflow id', () => {
|
||||
const selectedWorkflow = {
|
||||
...createWorkflow([createStartNode()]),
|
||||
marked_name: '',
|
||||
}
|
||||
const baseMetric = createMetric()
|
||||
const metric = {
|
||||
...baseMetric,
|
||||
customConfig: {
|
||||
...baseMetric.customConfig!,
|
||||
workflowName: null,
|
||||
},
|
||||
}
|
||||
|
||||
mockUseAppDetail.mockReturnValue({
|
||||
data: {
|
||||
id: 'workflow-app-1',
|
||||
name: 'Review Workflow App',
|
||||
},
|
||||
})
|
||||
mockUseAppWorkflow.mockImplementation((appId: string) => {
|
||||
if (appId === 'workflow-app-1')
|
||||
return { data: selectedWorkflow }
|
||||
|
||||
return { data: undefined }
|
||||
})
|
||||
|
||||
render(
|
||||
<CustomMetricEditorCard
|
||||
resourceType="apps"
|
||||
resourceId="app-under-test"
|
||||
metric={metric}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(mockUseAppDetail).toHaveBeenCalledWith('workflow-app-1')
|
||||
expect(screen.getByText('Review Workflow App')).toBeInTheDocument()
|
||||
expect(screen.queryByText('workflow-1')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should pass the current app published graph and saved selector values to the picker', () => {
|
||||
const selectedWorkflow = createWorkflow([
|
||||
createStartNode(),
|
||||
|
||||
@ -98,12 +98,22 @@ describe('WorkflowSelector', () => {
|
||||
setupWorkflowQueryMock({ workflows: [] })
|
||||
|
||||
renderWorkflowSelector({
|
||||
value: 'workflow-1',
|
||||
value: 'app-1',
|
||||
selectedWorkflowName: 'Saved Review Workflow',
|
||||
})
|
||||
|
||||
expect(screen.getByText('Saved Review Workflow')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should resolve the selected workflow from app id', () => {
|
||||
setupWorkflowQueryMock()
|
||||
|
||||
renderWorkflowSelector({
|
||||
value: 'app-1',
|
||||
})
|
||||
|
||||
expect(screen.getByText('Review Workflow')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// Cover opening the popover and choosing one workflow option.
|
||||
@ -120,6 +130,14 @@ describe('WorkflowSelector', () => {
|
||||
|
||||
expect(onSelect).toHaveBeenCalledWith(createWorkflow())
|
||||
})
|
||||
|
||||
it('should mark the option selected when its app id matches the value', async () => {
|
||||
renderWorkflowSelector({ value: 'app-1' })
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'evaluation.metrics.custom.workflowLabel' }))
|
||||
|
||||
expect(await screen.findByRole('option', { name: 'Review Workflow', selected: true })).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// Cover the infinite-scroll callback used by the ScrollArea viewport.
|
||||
|
||||
@ -8,6 +8,7 @@ import { useEffect, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { inputVarTypeToVarType } from '@/app/components/workflow/nodes/_base/components/variable/utils'
|
||||
import { BlockEnum, InputVarType } from '@/app/components/workflow/types'
|
||||
import { useAppDetail } from '@/service/use-apps'
|
||||
import { useSnippetPublishedWorkflow } from '@/service/use-snippet-workflows'
|
||||
import { useAppWorkflow } from '@/service/use-workflow'
|
||||
import { isCustomMetricConfigured, useEvaluationStore } from '../../store'
|
||||
@ -76,7 +77,9 @@ const CustomMetricEditorCard = ({
|
||||
const syncCustomMetricMappings = useEvaluationStore(state => state.syncCustomMetricMappings)
|
||||
const syncCustomMetricOutputs = useEvaluationStore(state => state.syncCustomMetricOutputs)
|
||||
const updateCustomMetricMapping = useEvaluationStore(state => state.updateCustomMetricMapping)
|
||||
const { data: selectedWorkflow } = useAppWorkflow(metric.customConfig?.workflowAppId ?? '')
|
||||
const selectedWorkflowAppId = metric.customConfig?.workflowAppId ?? metric.customConfig?.workflowId ?? ''
|
||||
const { data: selectedWorkflowApp } = useAppDetail(selectedWorkflowAppId)
|
||||
const { data: selectedWorkflow } = useAppWorkflow(selectedWorkflowAppId)
|
||||
const { data: currentAppWorkflow } = useAppWorkflow(resourceType === 'apps' ? resourceId : '')
|
||||
const { data: currentSnippetWorkflow } = useSnippetPublishedWorkflow(resourceType === 'snippets' ? resourceId : '')
|
||||
const inputVariables = useMemo(() => {
|
||||
@ -153,9 +156,9 @@ const CustomMetricEditorCard = ({
|
||||
<div className="px-3 pt-1 pb-3">
|
||||
<WorkflowSelector
|
||||
value={metric.customConfig.workflowId}
|
||||
selectedWorkflowName={metric.customConfig.workflowName ?? (selectedWorkflow ? getWorkflowName(selectedWorkflow) : null)}
|
||||
selectedWorkflowName={metric.customConfig.workflowName ?? selectedWorkflowApp?.name ?? null}
|
||||
onSelect={workflow => setCustomMetricWorkflow(resourceType, resourceId, metric.id, {
|
||||
workflowId: workflow.id,
|
||||
workflowId: workflow.app_id,
|
||||
workflowAppId: workflow.app_id,
|
||||
workflowName: getWorkflowName(workflow),
|
||||
})}
|
||||
@ -163,7 +166,7 @@ const CustomMetricEditorCard = ({
|
||||
|
||||
<div className="mt-4">
|
||||
<div className="mb-2 flex items-center justify-between gap-3">
|
||||
<div className="system-xs-medium-uppercase text-text-secondary">{t('metrics.custom.mappingTitle')}</div>
|
||||
<div className="system-xs-medium-uppercase text-text-tertiary">{t('metrics.custom.mappingTitle')}</div>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{inputVariables.map((inputVariable) => {
|
||||
|
||||
@ -34,6 +34,11 @@ const getWorkflowName = (workflow: AvailableEvaluationWorkflow) => {
|
||||
return workflow.marked_name || workflow.app_name || workflow.id
|
||||
}
|
||||
|
||||
const isSelectedWorkflow = (
|
||||
workflow: AvailableEvaluationWorkflow,
|
||||
value: string | null,
|
||||
) => workflow.app_id === value
|
||||
|
||||
const WorkflowSelector = ({
|
||||
value,
|
||||
selectedWorkflowName,
|
||||
@ -71,7 +76,7 @@ const WorkflowSelector = ({
|
||||
if (!value)
|
||||
return null
|
||||
|
||||
const selectedWorkflow = workflows.find(workflow => workflow.id === value)
|
||||
const selectedWorkflow = workflows.find(workflow => isSelectedWorkflow(workflow, value))
|
||||
if (selectedWorkflow)
|
||||
return getWorkflowName(selectedWorkflow)
|
||||
|
||||
@ -171,7 +176,7 @@ const WorkflowSelector = ({
|
||||
key={workflow.id}
|
||||
type="button"
|
||||
role="option"
|
||||
aria-selected={workflow.id === value}
|
||||
aria-selected={isSelectedWorkflow(workflow, value)}
|
||||
className="flex w-full items-center gap-2 rounded-lg px-2 py-1 text-left hover:bg-state-base-hover"
|
||||
onClick={() => {
|
||||
onSelect(workflow)
|
||||
@ -187,7 +192,7 @@ const WorkflowSelector = ({
|
||||
<div className="min-w-0 flex-1 truncate px-1 py-1 system-sm-medium text-text-secondary">
|
||||
{getWorkflowName(workflow)}
|
||||
</div>
|
||||
{workflow.id === value && (
|
||||
{isSelectedWorkflow(workflow, value) && (
|
||||
<span aria-hidden="true" className="i-ri-check-line h-4 w-4 shrink-0 text-text-accent" />
|
||||
)}
|
||||
</button>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user