feat: copy cross page
parent
c05e47ebc0
commit
c490e774b1
@ -0,0 +1,36 @@
|
||||
import type { MouseEvent } from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useWorkflowStore } from '../store'
|
||||
|
||||
export const useSelectionGraphMenu = () => {
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
||||
const { setSelectPanelMenu, setNodeMenu, setPanelMenu } = workflowStore.getState()
|
||||
|
||||
const handleSelectPanelContextMenu = useCallback((e: MouseEvent) => {
|
||||
e.preventDefault()
|
||||
console.log('handleSelectPanelContextMenu', e.clientX, e.clientY)
|
||||
const container = document.querySelector('#workflow-container')
|
||||
const { x, y } = container!.getBoundingClientRect()
|
||||
|
||||
setSelectPanelMenu({
|
||||
top: e.clientY - y,
|
||||
left: e.clientX - x,
|
||||
})
|
||||
}, [setSelectPanelMenu])
|
||||
|
||||
const handleSelectPanelContextmenuCancel = useCallback(() => {
|
||||
setSelectPanelMenu(undefined)
|
||||
}, [setSelectPanelMenu])
|
||||
|
||||
const handleOtherContextmenuCancel = useCallback(() => {
|
||||
setNodeMenu(undefined)
|
||||
setPanelMenu(undefined)
|
||||
}, [setNodeMenu, setPanelMenu])
|
||||
|
||||
return {
|
||||
handleSelectPanelContextMenu,
|
||||
handleSelectPanelContextmenuCancel,
|
||||
handleOtherContextmenuCancel,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
import {
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import type {
|
||||
OnSelectionChangeParams,
|
||||
} from 'reactflow'
|
||||
import { useOnSelectionChange } from 'reactflow'
|
||||
import { useWorkflowStore } from '../store'
|
||||
|
||||
export const useSelectionGraph = () => {
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { setSelectGraph } = workflowStore.getState()
|
||||
|
||||
const onChange = useCallback((params: OnSelectionChangeParams) => {
|
||||
const { nodes, edges } = params
|
||||
setSelectGraph({
|
||||
nodes,
|
||||
edges,
|
||||
})
|
||||
}, [])
|
||||
|
||||
useOnSelectionChange({
|
||||
onChange,
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
import type { RefObject } from 'react'
|
||||
import { useEffect } from'react'
|
||||
import {
|
||||
useStore,
|
||||
} from 'reactflow'
|
||||
|
||||
type UseSelectionPasteProps = {
|
||||
workflowContainerRef: RefObject<HTMLDivElement>
|
||||
}
|
||||
|
||||
export const useSelectionPaste = ({ workflowContainerRef }: UseSelectionPasteProps) => {
|
||||
const domNode = useStore(s => s.domNode)
|
||||
const handlePaste = (e: ClipboardEvent) => {
|
||||
e.preventDefault()
|
||||
console.log(e.clipboardData?.getData('text'))
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (domNode) {
|
||||
console.log('workflowContainerRef.current', domNode)
|
||||
domNode.addEventListener('paste', handlePaste)
|
||||
}
|
||||
return () => {
|
||||
if (domNode)
|
||||
domNode.removeEventListener('paste', handlePaste)
|
||||
}
|
||||
}, [domNode])
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
import {
|
||||
memo,
|
||||
useEffect,
|
||||
useRef,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useClickAway } from 'ahooks'
|
||||
import ShortcutsName from './shortcuts-name'
|
||||
import { useStore } from './store'
|
||||
import {
|
||||
useNodesInteractions,
|
||||
useSelectionGraphMenu,
|
||||
useWorkflowStartRun,
|
||||
} from './hooks'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
|
||||
const PanelContextmenu = () => {
|
||||
const { t } = useTranslation()
|
||||
const ref = useRef(null)
|
||||
const selectPanelMenu = useStore(s => s.selectPanelMenu)
|
||||
const selectGraph = useStore(s => s.selectGraph)
|
||||
const clipboardElements = useStore(s => s.clipboardElements)
|
||||
const { handleNodesPaste } = useNodesInteractions()
|
||||
const { handleSelectPanelContextmenuCancel, handleOtherContextmenuCancel } = useSelectionGraphMenu()
|
||||
const { handleStartWorkflowRun } = useWorkflowStartRun()
|
||||
|
||||
const appDetail = useAppStore(state => state.appDetail)
|
||||
|
||||
console.log(appDetail?.mode, selectGraph)
|
||||
|
||||
useEffect(() => {
|
||||
if (selectPanelMenu)
|
||||
handleOtherContextmenuCancel()
|
||||
}, [selectPanelMenu, handleOtherContextmenuCancel])
|
||||
|
||||
useClickAway(() => {
|
||||
handleSelectPanelContextmenuCancel()
|
||||
}, ref)
|
||||
|
||||
if (!selectPanelMenu)
|
||||
return null
|
||||
|
||||
return (
|
||||
<div
|
||||
className='absolute z-[9] w-[200px] rounded-lg border-[0.5px] border-components-panel-border bg-components-panel-bg-blur shadow-lg'
|
||||
style={{
|
||||
left: selectPanelMenu.left,
|
||||
top: selectPanelMenu.top,
|
||||
}}
|
||||
ref={ref}
|
||||
>
|
||||
<div className='p-1'>
|
||||
<div
|
||||
className='flex h-8 cursor-pointer items-center justify-between rounded-lg px-3 text-sm text-text-secondary hover:bg-state-base-hover'
|
||||
onClick={() => {
|
||||
handleStartWorkflowRun()
|
||||
handleSelectPanelContextmenuCancel()
|
||||
}}
|
||||
>
|
||||
{t('workflow.common.run')}
|
||||
<ShortcutsName keys={['alt', 'r']} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(PanelContextmenu)
|
||||
@ -0,0 +1,25 @@
|
||||
import type { Edge, Node } from 'reactflow'
|
||||
import type { StateCreator } from 'zustand'
|
||||
|
||||
export type SelectPanelSliceShape = {
|
||||
selectGraph: {
|
||||
nodes: Node[],
|
||||
edges: Edge[],
|
||||
},
|
||||
selectPanelMenu?: {
|
||||
top: number
|
||||
left: number
|
||||
},
|
||||
setSelectPanelMenu: (panelMenu: SelectPanelSliceShape['selectPanelMenu']) => void,
|
||||
setSelectGraph: (selectGraph: SelectPanelSliceShape['selectGraph']) => void,
|
||||
}
|
||||
|
||||
export const createSelectPanelSlice: StateCreator<SelectPanelSliceShape> = set => ({
|
||||
selectPanelMenu: undefined,
|
||||
setSelectPanelMenu: selectPanelMenu => set(() => ({ selectPanelMenu })),
|
||||
selectGraph: {
|
||||
nodes: [],
|
||||
edges: [],
|
||||
},
|
||||
setSelectGraph: selectGraph => set(() => ({ selectGraph })),
|
||||
})
|
||||
Loading…
Reference in New Issue