wwf
昨天 a430284aa21e3ae1f0d5654e55b2ad2852519cc2
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
import Tooltip from '@/app/components/base/tooltip'
import Indicator from '@/app/components/header/indicator'
import classNames from '@/utils/classnames'
import { memo, useMemo, useRef, useState } from 'react'
import { useAllBuiltInTools, useAllCustomTools, useAllWorkflowTools } from '@/service/use-tools'
import { getIconFromMarketPlace } from '@/utils/get-icon'
import { useTranslation } from 'react-i18next'
import { Group } from '@/app/components/base/icons/src/vender/other'
 
type Status = 'not-installed' | 'not-authorized' | undefined
 
export type ToolIconProps = {
  id: string
  providerName: string
}
 
export const ToolIcon = memo(({ providerName }: ToolIconProps) => {
  const containerRef = useRef<HTMLDivElement>(null)
  const { data: buildInTools } = useAllBuiltInTools()
  const { data: customTools } = useAllCustomTools()
  const { data: workflowTools } = useAllWorkflowTools()
  const isDataReady = !!buildInTools && !!customTools && !!workflowTools
  const currentProvider = useMemo(() => {
    const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])]
    return mergedTools.find((toolWithProvider) => {
      return toolWithProvider.name === providerName
    })
  }, [buildInTools, customTools, providerName, workflowTools])
  const providerNameParts = providerName.split('/')
  const author = providerNameParts[0]
  const name = providerNameParts[1]
  const icon = useMemo(() => {
    if (!isDataReady) return ''
    if (currentProvider) return currentProvider.icon as string
    const iconFromMarketPlace = getIconFromMarketPlace(`${author}/${name}`)
    return iconFromMarketPlace
  }, [author, currentProvider, name, isDataReady])
  const status: Status = useMemo(() => {
    if (!isDataReady) return undefined
    if (!currentProvider) return 'not-installed'
    if (currentProvider.is_team_authorization === false) return 'not-authorized'
    return undefined
  }, [currentProvider, isDataReady])
  const indicator = status === 'not-installed' ? 'red' : status === 'not-authorized' ? 'yellow' : undefined
  const notSuccess = (['not-installed', 'not-authorized'] as Array<Status>).includes(status)
  const { t } = useTranslation()
  const tooltip = useMemo(() => {
    if (!notSuccess) return undefined
    if (status === 'not-installed') return t('workflow.nodes.agent.toolNotInstallTooltip', { tool: name })
    if (status === 'not-authorized') return t('workflow.nodes.agent.toolNotAuthorizedTooltip', { tool: name })
    throw new Error('Unknown status')
  }, [name, notSuccess, status, t])
  const [iconFetchError, setIconFetchError] = useState(false)
  return <Tooltip
    triggerMethod='hover'
    popupContent={tooltip}
    disabled={!notSuccess}
  >
    <div
      className={classNames(
        'size-5 border-[0.5px] border-components-panel-border-subtle bg-background-default-dodge relative flex items-center justify-center rounded-[6px]',
      )}
      ref={containerRef}
    >
      {(!iconFetchError && isDataReady)
 
        ? <img
          src={icon}
          alt='tool icon'
          className={classNames(
            'w-full h-full size-3.5 object-cover',
            notSuccess && 'opacity-50',
          )}
          onError={() => setIconFetchError(true)}
        />
        : <Group className="h-3 w-3 opacity-35" />
      }
      {indicator && <Indicator color={indicator} className="absolute right-[-1px] top-[-1px]" />}
    </div>
  </Tooltip>
})
 
ToolIcon.displayName = 'ToolIcon'