Spaces:
Build error
Build error
File size: 6,583 Bytes
a8b3f00 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
import {
memo,
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
import {
RiAddLine,
} from '@remixicon/react'
import cn from '@/utils/classnames'
import { ArrowUpRight } from '@/app/components/base/icons/src/vender/line/arrows'
import { Check } from '@/app/components/base/icons/src/vender/line/general'
import { Tag01 } from '@/app/components/base/icons/src/vender/line/financeAndECommerce'
import type { ToolWithProvider } from '@/app/components/workflow/types'
import { BlockEnum } from '@/app/components/workflow/types'
import BlockIcon from '@/app/components/workflow/block-icon'
import Tooltip from '@/app/components/base/tooltip'
import Button from '@/app/components/base/button'
import { useGetLanguage } from '@/context/i18n'
import { useStore as useLabelStore } from '@/app/components/tools/labels/store'
import Empty from '@/app/components/tools/add-tool-modal/empty'
import type { Tool } from '@/app/components/tools/types'
import { CollectionType } from '@/app/components/tools/types'
import type { AgentTool } from '@/types/app'
import { MAX_TOOLS_NUM } from '@/config'
type ToolsProps = {
showWorkflowEmpty: boolean
tools: ToolWithProvider[]
addedTools: AgentTool[]
onSelect: (provider: ToolWithProvider, tool: Tool) => void
onAuthSetup: (provider: ToolWithProvider) => void
}
const Blocks = ({
showWorkflowEmpty,
tools,
addedTools,
onSelect,
onAuthSetup,
}: ToolsProps) => {
const { t } = useTranslation()
const language = useGetLanguage()
const labelList = useLabelStore(s => s.labelList)
const addable = addedTools.length < MAX_TOOLS_NUM
const renderGroup = useCallback((toolWithProvider: ToolWithProvider) => {
const list = toolWithProvider.tools
const needAuth = toolWithProvider.allow_delete && !toolWithProvider.is_team_authorization && toolWithProvider.type === CollectionType.builtIn
return (
<div
key={toolWithProvider.id}
className='group mb-1 last-of-type:mb-0'
>
<div className='flex items-center justify-between w-full pl-3 pr-1 h-[22px] text-xs font-medium text-gray-500'>
{toolWithProvider.label[language]}
<a className='hidden cursor-pointer items-center group-hover:flex' href={`/tools?category=${toolWithProvider.type}`} target='_blank'>{t('tools.addToolModal.manageInTools')}<ArrowUpRight className='ml-0.5 w-3 h-3' /></a>
</div>
{list.map((tool) => {
const labelContent = (() => {
if (!tool.labels)
return ''
return tool.labels.map((name) => {
const label = labelList.find(item => item.name === name)
return label?.label[language]
}).filter(Boolean).join(', ')
})()
const added = !!addedTools?.find(v => v.provider_id === toolWithProvider.id && v.provider_type === toolWithProvider.type && v.tool_name === tool.name)
return (
<Tooltip
key={tool.name}
position='bottom'
popupClassName='!p-0 !px-3 !py-2.5 !w-[210px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !bg-transparent !rounded-xl !shadow-lg translate-x-[108px]'
popupContent={(
<div>
<BlockIcon
size='md'
className='mb-2'
type={BlockEnum.Tool}
toolIcon={toolWithProvider.icon}
/>
<div className='mb-1 text-sm leading-5 text-gray-900'>{tool.label[language]}</div>
<div className='text-xs text-gray-700 leading-[18px]'>{tool.description[language]}</div>
{tool.labels?.length > 0 && (
<div className='flex items-center shrink-0 mt-1'>
<div className='relative w-full flex items-center gap-1 py-1 rounded-md text-gray-500' title={labelContent}>
<Tag01 className='shrink-0 w-3 h-3 text-gray-500' />
<div className='grow text-xs text-start leading-[18px] font-normal truncate'>{labelContent}</div>
</div>
</div>
)}
</div>
)}
>
<div className='group/item flex items-center w-full pl-3 pr-1 h-8 rounded-lg hover:bg-gray-50 cursor-pointer'>
<BlockIcon
className={cn('mr-2 shrink-0', needAuth && 'opacity-30')}
type={BlockEnum.Tool}
toolIcon={toolWithProvider.icon}
/>
<div className={cn('grow text-sm text-gray-900 truncate', needAuth && 'opacity-30')}>{tool.label[language]}</div>
{!needAuth && added && (
<div className='flex items-center gap-1 rounded-[6px] border border-gray-100 px-2 py-[3px] bg-white text-gray-300 text-xs font-medium leading-[18px]'>
<Check className='w-3 h-3' />
{t('tools.addToolModal.added').toLocaleUpperCase()}
</div>
)}
{!needAuth && !added && addable && (
<Button
variant='secondary-accent'
size='small'
className={cn('hidden shrink-0 items-center group-hover/item:flex')}
onClick={() => onSelect(toolWithProvider, tool)}
>
<RiAddLine className='w-3 h-3' />
{t('tools.addToolModal.add').toLocaleUpperCase()}
</Button>
)}
{needAuth && (
<Button
variant='secondary-accent'
size='small'
className={cn('hidden shrink-0 group-hover/item:flex')}
onClick={() => onAuthSetup(toolWithProvider)}
>{t('tools.auth.setup')}</Button>
)}
</div>
</Tooltip>
)
})}
</div>
)
}, [addable, language, t, labelList, addedTools, onAuthSetup, onSelect])
return (
<div className='p-1 pb-6 max-w-[440px]'>
{!tools.length && !showWorkflowEmpty && (
<div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>{t('workflow.tabs.noResult')}</div>
)}
{!tools.length && showWorkflowEmpty && (
<div className='pt-[280px]'>
<Empty />
</div>
)}
{!!tools.length && tools.map(renderGroup)}
</div>
)
}
export default memo(Blocks)
|