tools.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import {
  2. memo,
  3. useCallback,
  4. useMemo,
  5. } from 'react'
  6. import { useTranslation } from 'react-i18next'
  7. import BlockIcon from '../block-icon'
  8. import { BlockEnum } from '../types'
  9. import type { ToolWithProvider } from '../types'
  10. import { useStore } from '../store'
  11. import type { ToolDefaultValue } from './types'
  12. import Tooltip from '@/app/components/base/tooltip'
  13. import { useGetLanguage } from '@/context/i18n'
  14. type ToolsProps = {
  15. isCustom?: boolean
  16. onSelect: (type: BlockEnum, tool?: ToolDefaultValue) => void
  17. searchText: string
  18. }
  19. const Blocks = ({
  20. isCustom,
  21. searchText,
  22. onSelect,
  23. }: ToolsProps) => {
  24. const { t } = useTranslation()
  25. const language = useGetLanguage()
  26. const buildInTools = useStore(s => s.buildInTools)
  27. const customTools = useStore(s => s.customTools)
  28. const tools = useMemo(() => {
  29. const currentTools = isCustom ? customTools : buildInTools
  30. return currentTools.filter((toolWithProvider) => {
  31. return toolWithProvider.tools.some((tool) => {
  32. return tool.label[language].toLowerCase().includes(searchText.toLowerCase())
  33. })
  34. })
  35. }, [isCustom, customTools, buildInTools, searchText, language])
  36. const renderGroup = useCallback((toolWithProvider: ToolWithProvider) => {
  37. const list = toolWithProvider.tools
  38. return (
  39. <div
  40. key={toolWithProvider.id}
  41. className='mb-1 last-of-type:mb-0'
  42. >
  43. <div className='flex items-start px-3 h-[22px] text-xs font-medium text-gray-500'>
  44. {toolWithProvider.label[language]}
  45. </div>
  46. {
  47. list.map(tool => (
  48. <Tooltip
  49. key={tool.name}
  50. selector={`workflow-block-tool-${tool.name}`}
  51. position='right'
  52. className='!p-0 !px-3 !py-2.5 !w-[200px] !leading-[18px] !text-xs !text-gray-700 !border-[0.5px] !border-black/5 !bg-transparent !rounded-xl !shadow-lg'
  53. htmlContent={(
  54. <div>
  55. <div className='flex items-center mb-2'>
  56. <BlockIcon
  57. size='md'
  58. className='mr-2'
  59. type={BlockEnum.Tool}
  60. toolIcon={toolWithProvider.icon}
  61. />
  62. <div className='text-sm text-gray-900'>{tool.label[language]}</div>
  63. </div>
  64. {tool.description[language]}
  65. </div>
  66. )}
  67. noArrow
  68. >
  69. <div
  70. className='flex items-center px-3 w-full h-8 rounded-lg hover:bg-gray-50 cursor-pointer'
  71. onClick={() => onSelect(BlockEnum.Tool, {
  72. provider_id: toolWithProvider.id,
  73. provider_type: toolWithProvider.type,
  74. provider_name: toolWithProvider.name,
  75. tool_name: tool.name,
  76. tool_label: tool.label[language],
  77. title: tool.label[language],
  78. })}
  79. >
  80. <BlockIcon
  81. className='mr-2'
  82. type={BlockEnum.Tool}
  83. toolIcon={toolWithProvider.icon}
  84. />
  85. <div className='text-sm text-gray-900'>{tool.label[language]}</div>
  86. </div>
  87. </Tooltip>
  88. ))
  89. }
  90. </div>
  91. )
  92. }, [onSelect, language])
  93. return (
  94. <div className='p-1 max-h-[464px] overflow-y-auto'>
  95. {
  96. !tools.length && (
  97. <div className='flex items-center px-3 h-[22px] text-xs font-medium text-gray-500'>{t('workflow.tabs.noResult')}</div>
  98. )
  99. }
  100. {
  101. !!tools.length && tools.map(renderGroup)
  102. }
  103. </div>
  104. )
  105. }
  106. export default memo(Blocks)