mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 18:27:19 +08:00
fix(web): position of selection context menu in workflow graph
This commit is contained in:
parent
26bc108bf1
commit
df3b960505
@ -81,19 +81,31 @@ describe('SelectionContextmenu', () => {
|
||||
expect(screen.queryByText('operator.vertical')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should keep the menu inside the workflow container bounds', () => {
|
||||
it('should still render the menu when the requested position exceeds workflow container bounds', () => {
|
||||
const nodes = [
|
||||
createNode({ id: 'n1', selected: true, width: 80, height: 40 }),
|
||||
createNode({ id: 'n2', selected: true, position: { x: 140, y: 0 }, width: 80, height: 40 }),
|
||||
]
|
||||
const { store } = renderSelectionMenu({ nodes })
|
||||
const container = document.querySelector('#workflow-container') as HTMLDivElement
|
||||
|
||||
vi.spyOn(container, 'getBoundingClientRect').mockReturnValue({
|
||||
x: 16,
|
||||
y: 24,
|
||||
left: 16,
|
||||
top: 24,
|
||||
right: 816,
|
||||
bottom: 624,
|
||||
width: 800,
|
||||
height: 600,
|
||||
toJSON: () => ({}),
|
||||
})
|
||||
|
||||
act(() => {
|
||||
store.setState({ selectionMenu: { left: 780, top: 590 } })
|
||||
})
|
||||
|
||||
const menu = screen.getByTestId('selection-contextmenu')
|
||||
expect(menu).toHaveStyle({ left: '540px', top: '210px' })
|
||||
expect(screen.getByTestId('selection-contextmenu-item-left')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should close itself when only one node is selected', async () => {
|
||||
|
||||
@ -25,7 +25,6 @@ import {
|
||||
ContextMenuGroupLabel,
|
||||
ContextMenuItem,
|
||||
ContextMenuSeparator,
|
||||
ContextMenuTrigger,
|
||||
} from '@/app/components/base/ui/context-menu'
|
||||
import CreateSnippetDialog from './create-snippet-dialog'
|
||||
import { useNodesReadOnly, useNodesSyncDraft } from './hooks'
|
||||
@ -295,6 +294,25 @@ const SelectionContextmenu = () => {
|
||||
return getMenuPosition(selectionMenu, container?.getBoundingClientRect())
|
||||
}, [selectionMenu])
|
||||
|
||||
const anchor = useMemo(() => {
|
||||
if (!selectionMenu)
|
||||
return null
|
||||
|
||||
const container = document.querySelector('#workflow-container')
|
||||
const containerRect = container?.getBoundingClientRect()
|
||||
if (!containerRect)
|
||||
return null
|
||||
|
||||
return {
|
||||
getBoundingClientRect: () => DOMRect.fromRect({
|
||||
width: 0,
|
||||
height: 0,
|
||||
x: containerRect.left + menuPosition.left,
|
||||
y: containerRect.top + menuPosition.top,
|
||||
}),
|
||||
}
|
||||
}, [menuPosition.left, menuPosition.top, selectionMenu])
|
||||
|
||||
useEffect(() => {
|
||||
if (selectionMenu && selectedNodes.length <= 1)
|
||||
handleSelectionContextmenuCancel()
|
||||
@ -382,18 +400,11 @@ const SelectionContextmenu = () => {
|
||||
}
|
||||
}, [store, workflowStore, selectedNodes, getNodesReadOnly, handleSyncWorkflowDraft, saveStateToHistory, handleSelectionContextmenuCancel])
|
||||
|
||||
if (!selectionMenu && !isCreateSnippetDialogOpen)
|
||||
if ((!selectionMenu || !anchor) && !isCreateSnippetDialogOpen)
|
||||
return null
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute z-[9]"
|
||||
data-testid="selection-contextmenu"
|
||||
style={{
|
||||
left: menuPosition.left,
|
||||
top: menuPosition.top,
|
||||
}}
|
||||
>
|
||||
<div data-testid="selection-contextmenu">
|
||||
<ContextMenu
|
||||
open
|
||||
onOpenChange={(open) => {
|
||||
@ -401,10 +412,10 @@ const SelectionContextmenu = () => {
|
||||
handleSelectionContextmenuCancel()
|
||||
}}
|
||||
>
|
||||
<ContextMenuTrigger>
|
||||
<span aria-hidden className="block size-px opacity-0" />
|
||||
</ContextMenuTrigger>
|
||||
<ContextMenuContent popupClassName="w-[240px]">
|
||||
<ContextMenuContent
|
||||
positionerProps={{ anchor }}
|
||||
popupClassName="w-[240px]"
|
||||
>
|
||||
{menuSections.map((section, sectionIndex) => (
|
||||
<ContextMenuGroup key={section.titleKey}>
|
||||
{sectionIndex > 0 && <ContextMenuSeparator />}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user