mirror of
https://github.com/langgenius/dify.git
synced 2026-05-09 04:36:31 +08:00
fix(workflow): use correct field ID in KB metadata filter selection (#34149)
Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
3ebb449d25
commit
376c43e5ac
@ -4194,11 +4194,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/workflow/nodes/knowledge-retrieval/components/metadata/condition-list/condition-value-method.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/workflow/nodes/knowledge-retrieval/components/metadata/metadata-filter/index.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
|
||||
@ -19,6 +19,7 @@ import { BlockEnum, VarType } from '../../../types'
|
||||
import AddDataset from '../components/add-dataset'
|
||||
import DatasetItem from '../components/dataset-item'
|
||||
import DatasetList from '../components/dataset-list'
|
||||
import AddCondition from '../components/metadata/add-condition'
|
||||
import ConditionCommonVariableSelector from '../components/metadata/condition-list/condition-common-variable-selector'
|
||||
import ConditionDate from '../components/metadata/condition-list/condition-date'
|
||||
import ConditionItem from '../components/metadata/condition-list/condition-item'
|
||||
@ -462,6 +463,29 @@ describe('knowledge-retrieval path', () => {
|
||||
expect(screen.getByText('metadata-panel')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should call handleAddCondition with the correct metadata item when clicking any part of the row', async () => {
|
||||
const user = userEvent.setup()
|
||||
const handleAddCondition = vi.fn()
|
||||
const permissionMetadata = createMetadata({ id: 'meta-perm', name: 'permission', type: MetadataFilteringVariableType.string })
|
||||
const topicMetadata = createMetadata({ id: 'meta-topic', name: 'topic', type: MetadataFilteringVariableType.string })
|
||||
|
||||
render(
|
||||
<AddCondition
|
||||
metadataList={[permissionMetadata, topicMetadata]}
|
||||
handleAddCondition={handleAddCondition}
|
||||
/>,
|
||||
)
|
||||
|
||||
await user.click(screen.getByRole('button', { name: /workflow.nodes.knowledgeRetrieval.metadata.panel.add/i }))
|
||||
await user.click(screen.getAllByText('string', { selector: 'div.shrink-0' })[0]!)
|
||||
|
||||
expect(handleAddCondition).toHaveBeenCalledTimes(1)
|
||||
expect(handleAddCondition).toHaveBeenCalledWith(expect.objectContaining({
|
||||
id: 'meta-perm',
|
||||
name: 'permission',
|
||||
}))
|
||||
})
|
||||
|
||||
it('should render automatic and manual metadata filter states', async () => {
|
||||
const user = userEvent.setup()
|
||||
const baseProps: MetadataShape = {
|
||||
@ -591,6 +615,24 @@ describe('knowledge-retrieval path', () => {
|
||||
expect(onUpdateCondition).toHaveBeenCalledWith('condition-1', expect.objectContaining({ value: 'updated-agent' }))
|
||||
expect(onRemoveCondition).toHaveBeenCalledWith('condition-1')
|
||||
})
|
||||
|
||||
it('should resolve built-in metadata fields by name because their ids are shared', () => {
|
||||
render(
|
||||
<ConditionItem
|
||||
metadataList={[
|
||||
createMetadata({ id: 'built-in', name: 'document_name' }),
|
||||
createMetadata({ id: 'built-in', name: 'uploader' }),
|
||||
]}
|
||||
condition={createCondition({
|
||||
metadata_id: 'built-in',
|
||||
name: 'uploader',
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('uploader')).toBeInTheDocument()
|
||||
expect(screen.queryByText('document_name')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('Node rendering', () => {
|
||||
|
||||
@ -65,6 +65,7 @@ const AddCondition = ({
|
||||
<div
|
||||
key={metadata.name}
|
||||
className="flex h-6 cursor-pointer items-center rounded-md px-3 system-sm-medium text-text-secondary hover:bg-state-base-hover"
|
||||
onClick={() => handleAddConditionWrapped(metadata)}
|
||||
>
|
||||
<div className="mr-1 p-px">
|
||||
<MetadataIcon type={metadata.type} />
|
||||
@ -72,7 +73,6 @@ const AddCondition = ({
|
||||
<div
|
||||
className="grow truncate"
|
||||
title={metadata.name}
|
||||
onClick={() => handleAddConditionWrapped(metadata)}
|
||||
>
|
||||
{metadata.name}
|
||||
</div>
|
||||
|
||||
@ -62,13 +62,16 @@ const ConditionItem = ({
|
||||
}, [onRemoveCondition, condition.id])
|
||||
|
||||
const currentMetadata = useMemo(() => {
|
||||
// Try to match by metadata_id first (reliable reference)
|
||||
if (condition.metadata_id) {
|
||||
const found = metadataList.find(metadata => metadata.id === condition.metadata_id)
|
||||
if (found)
|
||||
return found
|
||||
const foundByIdAndName = metadataList.find(metadata => metadata.id === condition.metadata_id && metadata.name === condition.name)
|
||||
if (foundByIdAndName)
|
||||
return foundByIdAndName
|
||||
|
||||
const foundById = metadataList.filter(metadata => metadata.id === condition.metadata_id)
|
||||
if (foundById.length === 1)
|
||||
return foundById[0]
|
||||
}
|
||||
// Fallback to name matching for backward compatibility with old conditions
|
||||
|
||||
return metadataList.find(metadata => metadata.name === condition.name)
|
||||
}, [metadataList, condition.metadata_id, condition.name])
|
||||
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from '@langgenius/dify-ui/popover'
|
||||
import { RiArrowDownSLine } from '@remixicon/react'
|
||||
import { capitalize } from 'es-toolkit/string'
|
||||
import { useState } from 'react'
|
||||
import {
|
||||
PortalToFollowElem,
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
|
||||
export type ConditionValueMethodProps = {
|
||||
valueMethod?: string
|
||||
@ -24,23 +24,27 @@ const ConditionValueMethod = ({
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<PortalToFollowElem
|
||||
<Popover
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
placement="bottom-start"
|
||||
offset={{ mainAxis: 4, crossAxis: 0 }}
|
||||
>
|
||||
<PortalToFollowElemTrigger asChild onClick={() => setOpen(v => !v)}>
|
||||
<Button
|
||||
className="shrink-0"
|
||||
variant="ghost"
|
||||
size="small"
|
||||
>
|
||||
{capitalize(valueMethod)}
|
||||
<RiArrowDownSLine className="ml-px h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</PortalToFollowElemTrigger>
|
||||
<PortalToFollowElemContent className="z-1000">
|
||||
<PopoverTrigger
|
||||
render={(
|
||||
<Button
|
||||
className="shrink-0"
|
||||
variant="ghost"
|
||||
size="small"
|
||||
>
|
||||
{capitalize(valueMethod)}
|
||||
<RiArrowDownSLine className="ml-px h-3.5 w-3.5" />
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
<PopoverContent
|
||||
placement="bottom-start"
|
||||
sideOffset={4}
|
||||
popupClassName="border-none bg-transparent p-0 shadow-none backdrop-blur-none"
|
||||
>
|
||||
<div className="w-[112px] rounded-xl border-[0.5px] border-components-panel-border bg-components-panel-bg-blur p-1 shadow-lg">
|
||||
{
|
||||
options.map(option => (
|
||||
@ -63,8 +67,8 @@ const ConditionValueMethod = ({
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</PortalToFollowElemContent>
|
||||
</PortalToFollowElem>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user