Compare commits
3 Commits
codex/refa
...
codex/refa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81f0d69c83 | ||
|
|
8a61561159 | ||
|
|
88895b6dfa |
@@ -5269,14 +5269,6 @@
|
||||
"count": 4
|
||||
}
|
||||
},
|
||||
"web/app/components/workflow/panel/version-history-panel/filter/filter-item.tsx": {
|
||||
"jsx_a11y/click-events-have-key-events": {
|
||||
"count": 1
|
||||
},
|
||||
"jsx_a11y/no-static-element-interactions": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/workflow/panel/version-history-panel/index.tsx": {
|
||||
"jsx_a11y/click-events-have-key-events": {
|
||||
"count": 2
|
||||
|
||||
@@ -105,8 +105,10 @@ describe('ExternalAPIPanel', () => {
|
||||
})
|
||||
|
||||
it('should render close button', () => {
|
||||
render(<ExternalAPIPanel {...defaultProps} />)
|
||||
expect(screen.getByRole('button', { name: 'common.operation.close' })).toBeInTheDocument()
|
||||
const { container } = render(<ExternalAPIPanel {...defaultProps} />)
|
||||
const closeButton =
|
||||
container.querySelector('[class*="action-button"]') || screen.getAllByRole('button')[0]
|
||||
expect(closeButton)!.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -169,7 +171,11 @@ describe('ExternalAPIPanel', () => {
|
||||
it('should call onClose when close button is clicked', () => {
|
||||
const onClose = vi.fn()
|
||||
render(<ExternalAPIPanel canManageExternalKnowledgeApi={true} onClose={onClose} />)
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.close' }))
|
||||
// Find the close button (ActionButton with close icon)
|
||||
const buttons = screen.getAllByRole('button')
|
||||
const closeButton =
|
||||
buttons.find((btn) => btn.querySelector('svg[class*="ri-close"]')) || buttons[0]
|
||||
fireEvent.click(closeButton!)
|
||||
expect(onClose).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { RiAddLine, RiBookOpenLine, RiCloseLine } from '@remixicon/react'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
@@ -14,7 +16,10 @@ type ExternalAPIPanelProps = {
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const ExternalAPIPanel = ({ canManageExternalKnowledgeApi, onClose }: ExternalAPIPanelProps) => {
|
||||
const ExternalAPIPanel: React.FC<ExternalAPIPanelProps> = ({
|
||||
canManageExternalKnowledgeApi,
|
||||
onClose,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const docLink = useDocLink()
|
||||
const { setShowExternalKnowledgeAPIModal } = useModalContext()
|
||||
@@ -59,18 +64,15 @@ const ExternalAPIPanel = ({ canManageExternalKnowledgeApi, onClose }: ExternalAP
|
||||
href={docLink('/use-dify/knowledge/external-knowledge-api')}
|
||||
target="_blank"
|
||||
>
|
||||
<span aria-hidden className="i-ri-book-open-line size-3 text-text-accent" />
|
||||
<RiBookOpenLine className="size-3 text-text-accent" />
|
||||
<div className="grow body-xs-regular text-text-accent">
|
||||
{t(($) => $.externalAPIPanelDocumentation, { ns: 'dataset' })}
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<ActionButton
|
||||
aria-label={t(($) => $['operation.close'], { ns: 'common' })}
|
||||
onClick={() => onClose()}
|
||||
>
|
||||
<span aria-hidden className="i-ri-close-line size-4 text-text-tertiary" />
|
||||
<ActionButton onClick={() => onClose()}>
|
||||
<RiCloseLine className="size-4 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
@@ -81,10 +83,7 @@ const ExternalAPIPanel = ({ canManageExternalKnowledgeApi, onClose }: ExternalAP
|
||||
className="flex items-center justify-center px-3 py-2"
|
||||
onClick={handleOpenExternalAPIModal}
|
||||
>
|
||||
<span
|
||||
aria-hidden
|
||||
className="i-ri-add-line size-4 text-components-button-primary-text"
|
||||
/>
|
||||
<RiAddLine className="size-4 text-components-button-primary-text" />
|
||||
<div className="system-sm-medium text-components-button-primary-text">
|
||||
{t(($) => $.createExternalAPI, { ns: 'dataset' })}
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('FilterItem', () => {
|
||||
it('renders the label, fires selection, and shows the check mark when selected', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onClick = vi.fn()
|
||||
const { container } = render(
|
||||
render(
|
||||
<FilterItem
|
||||
item={{
|
||||
key: WorkflowVersionFilterOptions.onlyYours,
|
||||
@@ -18,9 +18,12 @@ describe('FilterItem', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
await user.click(screen.getByText('Only yours'))
|
||||
const option = screen.getByRole('button', { name: 'Only yours' })
|
||||
expect(option).toHaveAttribute('aria-pressed', 'true')
|
||||
|
||||
option.focus()
|
||||
await user.keyboard(' ')
|
||||
|
||||
expect(onClick).toHaveBeenCalledWith(WorkflowVersionFilterOptions.onlyYours)
|
||||
expect(container.querySelector('svg')).not.toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { WorkflowVersionFilterOptions } from '../../../../types'
|
||||
import FilterItem from '../filter-item'
|
||||
import FilterSwitch from '../filter-switch'
|
||||
import Filter from '../index'
|
||||
|
||||
@@ -29,32 +28,6 @@ describe('VersionHistory Filter Components', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// Filter items should show the current selection and forward the option key.
|
||||
describe('FilterItem', () => {
|
||||
it('should call onClick with the selected filter key', async () => {
|
||||
const user = userEvent.setup()
|
||||
const onClick = vi.fn()
|
||||
|
||||
const { container } = render(
|
||||
<FilterItem
|
||||
item={{
|
||||
key: WorkflowVersionFilterOptions.onlyYours,
|
||||
name: 'Only Yours',
|
||||
}}
|
||||
isSelected
|
||||
onClick={onClick}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('Only Yours')).toBeInTheDocument()
|
||||
expect(container.querySelector('svg')).toBeInTheDocument()
|
||||
|
||||
await user.click(screen.getByText('Only Yours'))
|
||||
|
||||
expect(onClick).toHaveBeenCalledWith(WorkflowVersionFilterOptions.onlyYours)
|
||||
})
|
||||
})
|
||||
|
||||
// The composed filter popover should open, list options, and delegate actions.
|
||||
describe('Filter', () => {
|
||||
it('should open the menu and forward option and switch actions', async () => {
|
||||
@@ -79,7 +52,9 @@ describe('VersionHistory Filter Components', () => {
|
||||
expect(screen.getByText('workflow.versionHistory.filter.all')).toBeInTheDocument()
|
||||
expect(screen.getByText('workflow.versionHistory.filter.onlyYours')).toBeInTheDocument()
|
||||
|
||||
await user.click(screen.getByText('workflow.versionHistory.filter.onlyYours'))
|
||||
await user.click(
|
||||
screen.getByRole('button', { name: 'workflow.versionHistory.filter.onlyYours' }),
|
||||
)
|
||||
expect(onClickFilterItem).toHaveBeenCalledWith(WorkflowVersionFilterOptions.onlyYours)
|
||||
|
||||
fireEvent.click(screen.getByRole('switch'))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { FC } from 'react'
|
||||
import type { WorkflowVersionFilterOptions } from '../../../types'
|
||||
import { RiCheckLine } from '@remixicon/react'
|
||||
import * as React from 'react'
|
||||
|
||||
type FilterItemProps = {
|
||||
@@ -14,15 +13,19 @@ type FilterItemProps = {
|
||||
|
||||
const FilterItem: FC<FilterItemProps> = ({ item, isSelected = false, onClick }) => {
|
||||
return (
|
||||
<div
|
||||
className="flex cursor-pointer items-center justify-between gap-x-1 rounded-lg px-2 py-1.5 hover:bg-state-base-hover"
|
||||
<button
|
||||
type="button"
|
||||
aria-pressed={isSelected}
|
||||
className="flex w-full cursor-pointer appearance-none items-center justify-between gap-x-1 rounded-lg px-2 py-1.5 text-left outline-hidden hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid"
|
||||
onClick={() => {
|
||||
onClick(item.key)
|
||||
}}
|
||||
>
|
||||
<div className="flex-1 system-md-regular text-text-primary">{item.name}</div>
|
||||
{isSelected && <RiCheckLine className="size-4 shrink-0 text-text-accent" />}
|
||||
</div>
|
||||
<span className="flex-1 system-md-regular text-text-primary">{item.name}</span>
|
||||
{isSelected && (
|
||||
<span aria-hidden className="i-ri-check-line size-4 shrink-0 text-text-accent" />
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user