| 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) | |