|
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 { |
|
useDSL, |
|
useNodesInteractions, |
|
usePanelInteractions, |
|
useWorkflowStartRun, |
|
} from './hooks' |
|
import AddBlock from './operator/add-block' |
|
import { useOperator } from './operator/hooks' |
|
import cn from '@/utils/classnames' |
|
|
|
const PanelContextmenu = () => { |
|
const { t } = useTranslation() |
|
const ref = useRef(null) |
|
const panelMenu = useStore(s => s.panelMenu) |
|
const clipboardElements = useStore(s => s.clipboardElements) |
|
const setShowImportDSLModal = useStore(s => s.setShowImportDSLModal) |
|
const { handleNodesPaste } = useNodesInteractions() |
|
const { handlePaneContextmenuCancel, handleNodeContextmenuCancel } = usePanelInteractions() |
|
const { handleStartWorkflowRun } = useWorkflowStartRun() |
|
const { handleAddNote } = useOperator() |
|
const { exportCheck } = useDSL() |
|
|
|
useEffect(() => { |
|
if (panelMenu) |
|
handleNodeContextmenuCancel() |
|
}, [panelMenu, handleNodeContextmenuCancel]) |
|
|
|
useClickAway(() => { |
|
handlePaneContextmenuCancel() |
|
}, ref) |
|
|
|
const renderTrigger = () => { |
|
return ( |
|
<div |
|
className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50' |
|
> |
|
{t('workflow.common.addBlock')} |
|
</div> |
|
) |
|
} |
|
|
|
if (!panelMenu) |
|
return null |
|
|
|
return ( |
|
<div |
|
className='absolute w-[200px] rounded-lg border-[0.5px] border-gray-200 bg-white shadow-xl z-[9]' |
|
style={{ |
|
left: panelMenu.left, |
|
top: panelMenu.top, |
|
}} |
|
ref={ref} |
|
> |
|
<div className='p-1'> |
|
<AddBlock |
|
renderTrigger={renderTrigger} |
|
offset={{ |
|
mainAxis: -36, |
|
crossAxis: -4, |
|
}} |
|
/> |
|
<div |
|
className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50' |
|
onClick={(e) => { |
|
e.stopPropagation() |
|
handleAddNote() |
|
handlePaneContextmenuCancel() |
|
}} |
|
> |
|
{t('workflow.nodes.note.addNote')} |
|
</div> |
|
<div |
|
className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50' |
|
onClick={() => { |
|
handleStartWorkflowRun() |
|
handlePaneContextmenuCancel() |
|
}} |
|
> |
|
{t('workflow.common.run')} |
|
<ShortcutsName keys={['alt', 'r']} /> |
|
</div> |
|
</div> |
|
<div className='h-[1px] bg-gray-100'></div> |
|
<div className='p-1'> |
|
<div |
|
className={cn( |
|
'flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer', |
|
!clipboardElements.length ? 'opacity-50 cursor-not-allowed' : 'hover:bg-gray-50', |
|
)} |
|
onClick={() => { |
|
if (clipboardElements.length) { |
|
handleNodesPaste() |
|
handlePaneContextmenuCancel() |
|
} |
|
}} |
|
> |
|
{t('workflow.common.pasteHere')} |
|
<ShortcutsName keys={['ctrl', 'v']} /> |
|
</div> |
|
</div> |
|
<div className='h-[1px] bg-gray-100'></div> |
|
<div className='p-1'> |
|
<div |
|
className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50' |
|
onClick={() => exportCheck()} |
|
> |
|
{t('app.export')} |
|
</div> |
|
<div |
|
className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50' |
|
onClick={() => setShowImportDSLModal(true)} |
|
> |
|
{t('workflow.common.importDSL')} |
|
</div> |
|
</div> |
|
</div> |
|
) |
|
} |
|
|
|
export default memo(PanelContextmenu) |
|
|