This commit is contained in:
yyh
2026-03-25 00:05:40 +08:00
parent 84005bd25b
commit 88d82b5401
3 changed files with 57 additions and 2 deletions

View File

@ -29,6 +29,9 @@ const NodeDeleteConfirmDialog = ({
}: NodeDeleteConfirmDialogProps) => {
const { t } = useTranslation('workflow')
const isFolder = nodeType === 'folder'
const handleDialogClick = React.useCallback((e: React.MouseEvent) => {
e.stopPropagation()
}, [])
return (
<AlertDialog
@ -38,7 +41,10 @@ const NodeDeleteConfirmDialog = ({
onCancel()
}}
>
<AlertDialogContent>
<AlertDialogContent
popupProps={{ onClick: handleDialogClick }}
backdropProps={{ onClick: handleDialogClick }}
>
<div className="flex flex-col gap-2 p-6 pb-4">
<AlertDialogTitle className="text-text-primary title-2xl-semi-bold">
{isFolder

View File

@ -111,9 +111,20 @@ vi.mock('../../hooks/file-tree/operations/use-file-operations', () => ({
}))
vi.mock('./node-menu', () => ({
default: ({ type, menuType, onClose }: { type: string, menuType: string, onClose: () => void }) => (
default: ({
type,
menuType,
onClose,
onDeleteClick,
}: {
type: string
menuType: string
onClose: () => void
onDeleteClick?: () => void
}) => (
<div data-testid={`node-menu-${menuType}`} data-type={type}>
<button type="button" onClick={onClose}>close-menu</button>
<button type="button" onClick={onDeleteClick}>delete-item</button>
</div>
),
}))
@ -297,6 +308,23 @@ describe('TreeNode', () => {
expect(screen.getByTestId('node-menu-dropdown')).toHaveAttribute('data-type', 'file')
})
it('should stop dropdown item clicks from bubbling to the parent row host', () => {
const props = buildProps({ id: 'file-1', name: 'readme.md', nodeType: 'file' })
const rowHostClick = vi.fn()
render(
<div onClick={rowHostClick}>
<TreeNode {...props} />
</div>,
)
fireEvent.click(screen.getByRole('button', { name: /workflow\.skillSidebar\.menu\.moreActions/i }))
fireEvent.click(screen.getByRole('button', { name: 'delete-item' }))
expect(fileOperationMocks.handleDeleteClick).toHaveBeenCalledTimes(1)
expect(rowHostClick).not.toHaveBeenCalled()
})
})
// Effects should synchronize external drag status transitions into workflow store state.
@ -361,5 +389,22 @@ describe('TreeNode', () => {
expect(fileOperationMocks.handleDeleteConfirm).toHaveBeenCalledTimes(1)
expect(fileOperationMocks.handleDeleteCancel).toHaveBeenCalledTimes(1)
})
it('should stop cancel clicks in delete confirmation from bubbling to the parent row host', () => {
fileOperationMocks.showDeleteConfirm = true
const props = buildProps({ id: 'file-1', name: 'readme.md', nodeType: 'file' })
const rowHostClick = vi.fn()
render(
<div onClick={rowHostClick}>
<TreeNode {...props} />
</div>,
)
fireEvent.click(screen.getByRole('button', { name: /common\.operation\.cancel/i }))
expect(fileOperationMocks.handleDeleteCancel).toHaveBeenCalledTimes(1)
expect(rowHostClick).not.toHaveBeenCalled()
})
})
})

View File

@ -82,6 +82,9 @@ const TreeNode = ({ node, style, dragHandle, treeChildren }: TreeNodeProps) => {
const handleMoreClick = useCallback((e: React.MouseEvent) => {
e.stopPropagation()
}, [])
const handleDropdownContentClick = useCallback((e: React.MouseEvent) => {
e.stopPropagation()
}, [])
const handleMenuClose = useCallback(() => {}, [])
const fileOperations = useFileOperations({
@ -172,6 +175,7 @@ const TreeNode = ({ node, style, dragHandle, treeChildren }: TreeNodeProps) => {
placement="bottom-start"
sideOffset={4}
popupClassName="min-w-[180px]"
popupProps={{ onClick: handleDropdownContentClick }}
>
<NodeMenu
menuType="dropdown"