| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | import type { | 
					
						
							|  |  |  |   FC, | 
					
						
							|  |  |  |   ReactElement, | 
					
						
							|  |  |  | } from 'react' | 
					
						
							|  |  |  | import { | 
					
						
							|  |  |  |   cloneElement, | 
					
						
							|  |  |  |   memo, | 
					
						
							|  |  |  |   useCallback, | 
					
						
							|  |  |  | } from 'react' | 
					
						
							| 
									
										
										
										
											2024-06-20 11:05:08 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   RiCloseLine, | 
					
						
							|  |  |  |   RiPlayLargeLine, | 
					
						
							|  |  |  | } from '@remixicon/react' | 
					
						
							| 
									
										
										
										
											2024-04-28 17:09:56 +08:00
										 |  |  | import { useShallow } from 'zustand/react/shallow' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | import { useTranslation } from 'react-i18next' | 
					
						
							|  |  |  | import NextStep from './components/next-step' | 
					
						
							|  |  |  | import PanelOperator from './components/panel-operator' | 
					
						
							| 
									
										
										
										
											2024-05-30 14:24:53 +08:00
										 |  |  | import HelpLink from './components/help-link' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   DescriptionInput, | 
					
						
							|  |  |  |   TitleInput, | 
					
						
							|  |  |  | } from './components/title-description-input' | 
					
						
							|  |  |  | import { useResizePanel } from './hooks/use-resize-panel' | 
					
						
							| 
									
										
										
										
											2024-07-09 15:05:40 +08:00
										 |  |  | import cn from '@/utils/classnames' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | import BlockIcon from '@/app/components/workflow/block-icon' | 
					
						
							|  |  |  | import { | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |   WorkflowHistoryEvent, | 
					
						
							| 
									
										
										
										
											2024-06-05 14:00:47 +08:00
										 |  |  |   useAvailableBlocks, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   useNodeDataUpdate, | 
					
						
							|  |  |  |   useNodesInteractions, | 
					
						
							|  |  |  |   useNodesReadOnly, | 
					
						
							|  |  |  |   useNodesSyncDraft, | 
					
						
							|  |  |  |   useToolIcon, | 
					
						
							| 
									
										
										
										
											2024-04-26 14:23:13 +08:00
										 |  |  |   useWorkflow, | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |   useWorkflowHistory, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | } from '@/app/components/workflow/hooks' | 
					
						
							|  |  |  | import { canRunBySingle } from '@/app/components/workflow/utils' | 
					
						
							| 
									
										
										
										
											2024-08-26 13:00:02 +08:00
										 |  |  | import Tooltip from '@/app/components/base/tooltip' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | import type { Node } from '@/app/components/workflow/types' | 
					
						
							| 
									
										
										
										
											2024-04-28 17:09:56 +08:00
										 |  |  | import { useStore as useAppStore } from '@/app/components/app/store' | 
					
						
							| 
									
										
										
										
											2024-06-25 16:41:49 +08:00
										 |  |  | import { useStore } from '@/app/components/workflow/store' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type BasePanelProps = { | 
					
						
							|  |  |  |   children: ReactElement | 
					
						
							|  |  |  | } & Node | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const BasePanel: FC<BasePanelProps> = ({ | 
					
						
							|  |  |  |   id, | 
					
						
							|  |  |  |   data, | 
					
						
							|  |  |  |   children, | 
					
						
							|  |  |  | }) => { | 
					
						
							|  |  |  |   const { t } = useTranslation() | 
					
						
							| 
									
										
										
										
											2024-04-28 17:09:56 +08:00
										 |  |  |   const { showMessageLogModal } = useAppStore(useShallow(state => ({ | 
					
						
							|  |  |  |     showMessageLogModal: state.showMessageLogModal, | 
					
						
							|  |  |  |   }))) | 
					
						
							| 
									
										
										
										
											2024-06-25 16:41:49 +08:00
										 |  |  |   const showSingleRunPanel = useStore(s => s.showSingleRunPanel) | 
					
						
							| 
									
										
										
										
											2024-04-26 14:23:13 +08:00
										 |  |  |   const panelWidth = localStorage.getItem('workflow-node-panel-width') ? parseFloat(localStorage.getItem('workflow-node-panel-width')!) : 420 | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     setPanelWidth, | 
					
						
							|  |  |  |   } = useWorkflow() | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   const { handleNodeSelect } = useNodesInteractions() | 
					
						
							|  |  |  |   const { handleSyncWorkflowDraft } = useNodesSyncDraft() | 
					
						
							|  |  |  |   const { nodesReadOnly } = useNodesReadOnly() | 
					
						
							| 
									
										
										
										
											2024-06-05 14:00:47 +08:00
										 |  |  |   const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   const toolIcon = useToolIcon(data) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-26 14:23:13 +08:00
										 |  |  |   const handleResize = useCallback((width: number) => { | 
					
						
							|  |  |  |     setPanelWidth(width) | 
					
						
							|  |  |  |   }, [setPanelWidth]) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const { | 
					
						
							|  |  |  |     triggerRef, | 
					
						
							|  |  |  |     containerRef, | 
					
						
							|  |  |  |   } = useResizePanel({ | 
					
						
							|  |  |  |     direction: 'horizontal', | 
					
						
							|  |  |  |     triggerDirection: 'left', | 
					
						
							|  |  |  |     minWidth: 420, | 
					
						
							|  |  |  |     maxWidth: 720, | 
					
						
							| 
									
										
										
										
											2024-04-26 14:23:13 +08:00
										 |  |  |     onResize: handleResize, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |   const { saveStateToHistory } = useWorkflowHistory() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   const { | 
					
						
							|  |  |  |     handleNodeDataUpdate, | 
					
						
							|  |  |  |     handleNodeDataUpdateWithSyncDraft, | 
					
						
							|  |  |  |   } = useNodeDataUpdate() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleTitleBlur = useCallback((title: string) => { | 
					
						
							|  |  |  |     handleNodeDataUpdateWithSyncDraft({ id, data: { title } }) | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |     saveStateToHistory(WorkflowHistoryEvent.NodeTitleChange) | 
					
						
							|  |  |  |   }, [handleNodeDataUpdateWithSyncDraft, id, saveStateToHistory]) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |   const handleDescriptionChange = useCallback((desc: string) => { | 
					
						
							|  |  |  |     handleNodeDataUpdateWithSyncDraft({ id, data: { desc } }) | 
					
						
							| 
									
										
										
										
											2024-06-26 08:37:12 +02:00
										 |  |  |     saveStateToHistory(WorkflowHistoryEvent.NodeDescriptionChange) | 
					
						
							|  |  |  |   }, [handleNodeDataUpdateWithSyncDraft, id, saveStateToHistory]) | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							| 
									
										
										
										
											2024-04-28 17:09:56 +08:00
										 |  |  |     <div className={cn( | 
					
						
							|  |  |  |       'relative mr-2 h-full', | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |       showMessageLogModal && '!absolute !mr-0 w-[384px] overflow-hidden -top-[5px] right-[416px] z-0 shadow-lg border-[0.5px] border-components-panel-border rounded-2xl transition-all', | 
					
						
							| 
									
										
										
										
											2024-04-28 17:09:56 +08:00
										 |  |  |     )}> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |       <div | 
					
						
							|  |  |  |         ref={triggerRef} | 
					
						
							|  |  |  |         className='absolute top-1/2 -translate-y-1/2 -left-2 w-3 h-6 cursor-col-resize resize-x'> | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |         <div className='w-1 h-6 bg-divider-regular rounded-sm'></div> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |       </div> | 
					
						
							|  |  |  |       <div | 
					
						
							|  |  |  |         ref={containerRef} | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |         className={cn('h-full bg-components-panel-bg shadow-lg border-[0.5px] border-components-panel-border rounded-2xl', showSingleRunPanel ? 'overflow-hidden' : 'overflow-y-auto')} | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         style={{ | 
					
						
							| 
									
										
										
										
											2024-04-26 14:23:13 +08:00
										 |  |  |           width: `${panelWidth}px`, | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |         }} | 
					
						
							|  |  |  |       > | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |         <div className='sticky top-0 bg-components-panel-bg border-b-[0.5px] border-black/5 z-10'> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |           <div className='flex items-center px-4 pt-4 pb-1'> | 
					
						
							|  |  |  |             <BlockIcon | 
					
						
							|  |  |  |               className='shrink-0 mr-1' | 
					
						
							|  |  |  |               type={data.type} | 
					
						
							|  |  |  |               toolIcon={toolIcon} | 
					
						
							|  |  |  |               size='md' | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |             <TitleInput | 
					
						
							|  |  |  |               value={data.title || ''} | 
					
						
							|  |  |  |               onBlur={handleTitleBlur} | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |             <div className='shrink-0 flex items-center text-gray-500'> | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |                 canRunBySingle(data.type) && !nodesReadOnly && ( | 
					
						
							| 
									
										
										
										
											2024-08-26 13:00:02 +08:00
										 |  |  |                   <Tooltip | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                     popupContent={t('workflow.panel.runThisStep')} | 
					
						
							| 
									
										
										
										
											2024-08-26 13:00:02 +08:00
										 |  |  |                     popupClassName='mr-1' | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                   > | 
					
						
							|  |  |  |                     <div | 
					
						
							|  |  |  |                       className='flex items-center justify-center mr-1 w-6 h-6 rounded-md hover:bg-black/5 cursor-pointer' | 
					
						
							|  |  |  |                       onClick={() => { | 
					
						
							|  |  |  |                         handleNodeDataUpdate({ id, data: { _isSingleRun: true } }) | 
					
						
							|  |  |  |                         handleSyncWorkflowDraft(true) | 
					
						
							|  |  |  |                       }} | 
					
						
							|  |  |  |                     > | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |                       <RiPlayLargeLine className='w-4 h-4 text-text-tertiary' /> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                     </div> | 
					
						
							| 
									
										
										
										
											2024-08-26 13:00:02 +08:00
										 |  |  |                   </Tooltip> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                 ) | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2024-05-30 14:24:53 +08:00
										 |  |  |               <HelpLink nodeType={data.type} /> | 
					
						
							|  |  |  |               <PanelOperator id={id} data={data} showHelpLink={false} /> | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |               <div className='mx-3 w-[1px] h-3.5 bg-divider-regular' /> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |               <div | 
					
						
							|  |  |  |                 className='flex items-center justify-center w-6 h-6 cursor-pointer' | 
					
						
							|  |  |  |                 onClick={() => handleNodeSelect(id, true)} | 
					
						
							|  |  |  |               > | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |                 <RiCloseLine className='w-4 h-4 text-text-tertiary' /> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |               </div> | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |           <div className='p-2'> | 
					
						
							|  |  |  |             <DescriptionInput | 
					
						
							|  |  |  |               value={data.desc || ''} | 
					
						
							|  |  |  |               onChange={handleDescriptionChange} | 
					
						
							|  |  |  |             /> | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |         <div className='py-2'> | 
					
						
							|  |  |  |           {cloneElement(children, { id, data })} | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2024-06-05 14:00:47 +08:00
										 |  |  |           !!availableNextBlocks.length && ( | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |             <div className='p-4 border-t-[0.5px] border-t-black/5'> | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |               <div className='flex items-center mb-1 system-sm-semibold-uppercase text-text-secondary'> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                 {t('workflow.panel.nextStep').toLocaleUpperCase()} | 
					
						
							|  |  |  |               </div> | 
					
						
							| 
									
										
										
										
											2024-07-19 16:39:49 +08:00
										 |  |  |               <div className='mb-2 system-xs-regular text-text-tertiary'> | 
					
						
							| 
									
										
										
										
											2024-04-08 18:51:46 +08:00
										 |  |  |                 {t('workflow.panel.addNextStep')} | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |               <NextStep selectedNode={{ id, data } as Node} /> | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           ) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default memo(BasePanel) |