import { memo, useCallback, useMemo, } from 'react' import { useStoreApi } from 'reactflow' import { useTranslation } from 'react-i18next' import { groupBy } from 'lodash-es' import BlockIcon from '../block-icon' import { BlockEnum } from '../types' import type { NodeDefault } from '../types' import { BLOCK_CLASSIFICATIONS } from './constants' import type { ToolDefaultValue } from './types' import Tooltip from '@/app/components/base/tooltip' import Badge from '@/app/components/base/badge' type BlocksProps = { searchText: string onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void availableBlocksTypes?: BlockEnum[] blocks: NodeDefault[] } const Blocks = ({ searchText, onSelect, availableBlocksTypes = [], blocks, }: BlocksProps) => { const { t } = useTranslation() const store = useStoreApi() const groups = useMemo(() => { return BLOCK_CLASSIFICATIONS.reduce((acc, classification) => { const list = groupBy(blocks, 'metaData.classification')[classification].filter((block) => { return block.metaData.title.toLowerCase().includes(searchText.toLowerCase()) && availableBlocksTypes.includes(block.metaData.type) }) return { ...acc, [classification]: list, } }, {} as Record) }, [blocks, searchText, availableBlocksTypes]) const isEmpty = Object.values(groups).every(list => !list.length) const renderGroup = useCallback((classification: string) => { const list = groups[classification].sort((a, b) => a.metaData.sort - b.metaData.sort) const { getNodes } = store.getState() const nodes = getNodes() const hasKnowledgeBaseNode = nodes.some(node => node.data.type === BlockEnum.KnowledgeBase) const filteredList = list.filter((block) => { if (hasKnowledgeBaseNode) return block.metaData.type !== BlockEnum.KnowledgeBase return true }) return (
{ classification !== '-' && !!filteredList.length && (
{t(`workflow.tabs.${classification}`)}
) } { filteredList.map(block => (
{block.metaData.title}
{block.metaData.description}
)} >
onSelect(block.metaData.type)} >
{block.metaData.title}
{ block.metaData.type === BlockEnum.LoopEnd && ( ) }
)) } ) }, [groups, onSelect, t, store]) return (
{ isEmpty && (
{t('workflow.tabs.noResult')}
) } { !isEmpty && BLOCK_CLASSIFICATIONS.map(renderGroup) }
) } export default memo(Blocks)