Spaces:
Paused
Paused
| import { | |
| memo, | |
| useCallback, | |
| useMemo, | |
| } from 'react' | |
| import { useTranslation } from 'react-i18next' | |
| import { groupBy } from 'lodash-es' | |
| import BlockIcon from '../block-icon' | |
| import { BlockEnum } from '../types' | |
| import { | |
| useIsChatMode, | |
| useNodesExtraData, | |
| } from '../hooks' | |
| import { BLOCK_CLASSIFICATIONS } from './constants' | |
| import { useBlocks } from './hooks' | |
| import type { ToolDefaultValue } from './types' | |
| import Tooltip from '@/app/components/base/tooltip' | |
| type BlocksProps = { | |
| searchText: string | |
| onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void | |
| availableBlocksTypes?: BlockEnum[] | |
| } | |
| const Blocks = ({ | |
| searchText, | |
| onSelect, | |
| availableBlocksTypes = [], | |
| }: BlocksProps) => { | |
| const { t } = useTranslation() | |
| const isChatMode = useIsChatMode() | |
| const nodesExtraData = useNodesExtraData() | |
| const blocks = useBlocks() | |
| const groups = useMemo(() => { | |
| return BLOCK_CLASSIFICATIONS.reduce((acc, classification) => { | |
| const list = groupBy(blocks, 'classification')[classification].filter((block) => { | |
| if (block.type === BlockEnum.Answer && !isChatMode) | |
| return false | |
| return block.title.toLowerCase().includes(searchText.toLowerCase()) && availableBlocksTypes.includes(block.type) | |
| }) | |
| return { | |
| ...acc, | |
| [classification]: list, | |
| } | |
| }, {} as Record<string, typeof blocks>) | |
| }, [blocks, isChatMode, searchText, availableBlocksTypes]) | |
| const isEmpty = Object.values(groups).every(list => !list.length) | |
| const renderGroup = useCallback((classification: string) => { | |
| const list = groups[classification] | |
| return ( | |
| <div | |
| key={classification} | |
| className='mb-1 last-of-type:mb-0' | |
| > | |
| { | |
| classification !== '-' && !!list.length && ( | |
| <div className='flex items-start px-3 h-[22px] text-xs font-medium text-gray-500'> | |
| {t(`workflow.tabs.${classification}`)} | |
| </div> | |
| ) | |
| } | |
| { | |
| list.map(block => ( | |
| <Tooltip | |
| key={block.type} | |
| position='right' | |
| popupClassName='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !rounded-xl !shadow-lg' | |
| popupContent={( | |
| <div> | |
| <BlockIcon | |
| size='md' | |
| className='mb-2' | |
| type={block.type} | |
| /> | |
| <div className='mb-1 text-sm leading-5 text-gray-900'>{block.title}</div> | |
| <div className='text-xs text-gray-700 leading-[18px]'>{nodesExtraData[block.type].about}</div> | |
| </div> | |
| )} | |
| > | |
| <div | |
| key={block.type} | |
| className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-gray-50 cursor-pointer' | |
| onClick={() => onSelect(block.type)} | |
| > | |
| <BlockIcon | |
| className='mr-2 shrink-0' | |
| type={block.type} | |
| /> | |
| <div className='text-sm text-gray-900'>{block.title}</div> | |
| </div> | |
| </Tooltip> | |
| )) | |
| } | |
| </div> | |
| ) | |
| }, [groups, nodesExtraData, onSelect, t]) | |
| return ( | |
| <div className='p-1'> | |
| { | |
| isEmpty && ( | |
| <div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>{t('workflow.tabs.noResult')}</div> | |
| ) | |
| } | |
| { | |
| !isEmpty && BLOCK_CLASSIFICATIONS.map(renderGroup) | |
| } | |
| </div> | |
| ) | |
| } | |
| export default memo(Blocks) | |