From 20403c69b2f47b04d515a7aa7eea19992e3e79dd Mon Sep 17 00:00:00 2001 From: yangzheli <43645580+yangzheli@users.noreply.github.com> Date: Thu, 13 Nov 2025 20:21:04 +0800 Subject: [PATCH] refactor(web): remove redundant add-tool-modal components and related code (#27996) --- .../assets/vender/line/others/apps-02.svg | 5 - .../assets/vender/line/others/exchange-02.svg | 3 - .../assets/vender/line/others/file-code.svg | 3 - .../icons/src/vender/line/others/Apps02.json | 36 --- .../icons/src/vender/line/others/Apps02.tsx | 20 -- .../src/vender/line/others/Exchange02.json | 26 -- .../src/vender/line/others/Exchange02.tsx | 20 -- .../src/vender/line/others/FileCode.json | 26 -- .../icons/src/vender/line/others/FileCode.tsx | 20 -- .../icons/src/vender/line/others/index.ts | 3 - web/app/components/tools/add-tool-modal/D.png | Bin 1139 -> 0 bytes .../tools/add-tool-modal/category.tsx | 80 ------ .../components/tools/add-tool-modal/empty.png | Bin 30290 -> 0 bytes .../components/tools/add-tool-modal/index.tsx | 258 ------------------ .../components/tools/add-tool-modal/tools.tsx | 158 ----------- .../components/tools/add-tool-modal/type.tsx | 34 --- web/app/components/tools/provider-list.tsx | 2 +- .../{add-tool-modal => provider}/empty.tsx | 0 .../workflow/block-selector/tools.tsx | 2 +- web/i18n/de-DE/tools.ts | 4 - web/i18n/en-US/tools.ts | 4 - web/i18n/es-ES/tools.ts | 4 - web/i18n/fa-IR/tools.ts | 4 - web/i18n/fr-FR/tools.ts | 4 - web/i18n/hi-IN/tools.ts | 4 - web/i18n/id-ID/tools.ts | 4 - web/i18n/it-IT/tools.ts | 4 - web/i18n/ja-JP/tools.ts | 4 - web/i18n/ko-KR/tools.ts | 4 - web/i18n/pl-PL/tools.ts | 4 - web/i18n/pt-BR/tools.ts | 4 - web/i18n/ro-RO/tools.ts | 4 - web/i18n/ru-RU/tools.ts | 4 - web/i18n/sl-SI/tools.ts | 4 - web/i18n/th-TH/tools.ts | 4 - web/i18n/tr-TR/tools.ts | 4 - web/i18n/uk-UA/tools.ts | 4 - web/i18n/vi-VN/tools.ts | 4 - web/i18n/zh-Hans/tools.ts | 4 - web/i18n/zh-Hant/tools.ts | 4 - web/service/tools.ts | 22 -- 41 files changed, 2 insertions(+), 800 deletions(-) delete mode 100644 web/app/components/base/icons/assets/vender/line/others/apps-02.svg delete mode 100644 web/app/components/base/icons/assets/vender/line/others/exchange-02.svg delete mode 100644 web/app/components/base/icons/assets/vender/line/others/file-code.svg delete mode 100644 web/app/components/base/icons/src/vender/line/others/Apps02.json delete mode 100644 web/app/components/base/icons/src/vender/line/others/Apps02.tsx delete mode 100644 web/app/components/base/icons/src/vender/line/others/Exchange02.json delete mode 100644 web/app/components/base/icons/src/vender/line/others/Exchange02.tsx delete mode 100644 web/app/components/base/icons/src/vender/line/others/FileCode.json delete mode 100644 web/app/components/base/icons/src/vender/line/others/FileCode.tsx delete mode 100644 web/app/components/tools/add-tool-modal/D.png delete mode 100644 web/app/components/tools/add-tool-modal/category.tsx delete mode 100644 web/app/components/tools/add-tool-modal/empty.png delete mode 100644 web/app/components/tools/add-tool-modal/index.tsx delete mode 100644 web/app/components/tools/add-tool-modal/tools.tsx delete mode 100644 web/app/components/tools/add-tool-modal/type.tsx rename web/app/components/tools/{add-tool-modal => provider}/empty.tsx (100%) diff --git a/web/app/components/base/icons/assets/vender/line/others/apps-02.svg b/web/app/components/base/icons/assets/vender/line/others/apps-02.svg deleted file mode 100644 index 8e1fec9ecc..0000000000 --- a/web/app/components/base/icons/assets/vender/line/others/apps-02.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/web/app/components/base/icons/assets/vender/line/others/exchange-02.svg b/web/app/components/base/icons/assets/vender/line/others/exchange-02.svg deleted file mode 100644 index 45d2770277..0000000000 --- a/web/app/components/base/icons/assets/vender/line/others/exchange-02.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/app/components/base/icons/assets/vender/line/others/file-code.svg b/web/app/components/base/icons/assets/vender/line/others/file-code.svg deleted file mode 100644 index eb77033a0a..0000000000 --- a/web/app/components/base/icons/assets/vender/line/others/file-code.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/app/components/base/icons/src/vender/line/others/Apps02.json b/web/app/components/base/icons/src/vender/line/others/Apps02.json deleted file mode 100644 index 31378e175d..0000000000 --- a/web/app/components/base/icons/src/vender/line/others/Apps02.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "icon": { - "type": "element", - "isRootNode": true, - "name": "svg", - "attributes": { - "width": "16", - "height": "16", - "viewBox": "0 0 16 16", - "fill": "none", - "xmlns": "http://www.w3.org/2000/svg" - }, - "children": [ - { - "type": "element", - "name": "g", - "attributes": { - "id": "apps-2-line" - }, - "children": [ - { - "type": "element", - "name": "path", - "attributes": { - "id": "Vector", - "d": "M4.66602 7.6665C3.00916 7.6665 1.66602 6.32336 1.66602 4.6665C1.66602 3.00965 3.00916 1.6665 4.66602 1.6665C6.32287 1.6665 7.66602 3.00965 7.66602 4.6665C7.66602 6.32336 6.32287 7.6665 4.66602 7.6665ZM4.66602 14.3332C3.00916 14.3332 1.66602 12.99 1.66602 11.3332C1.66602 9.6763 3.00916 8.33317 4.66602 8.33317C6.32287 8.33317 7.66602 9.6763 7.66602 11.3332C7.66602 12.99 6.32287 14.3332 4.66602 14.3332ZM11.3327 7.6665C9.67582 7.6665 8.33268 6.32336 8.33268 4.6665C8.33268 3.00965 9.67582 1.6665 11.3327 1.6665C12.9895 1.6665 14.3327 3.00965 14.3327 4.6665C14.3327 6.32336 12.9895 7.6665 11.3327 7.6665ZM11.3327 14.3332C9.67582 14.3332 8.33268 12.99 8.33268 11.3332C8.33268 9.6763 9.67582 8.33317 11.3327 8.33317C12.9895 8.33317 14.3327 9.6763 14.3327 11.3332C14.3327 12.99 12.9895 14.3332 11.3327 14.3332ZM4.66602 6.33317C5.58649 6.33317 6.33268 5.58698 6.33268 4.6665C6.33268 3.74603 5.58649 2.99984 4.66602 2.99984C3.74554 2.99984 2.99935 3.74603 2.99935 4.6665C2.99935 5.58698 3.74554 6.33317 4.66602 6.33317ZM4.66602 12.9998C5.58649 12.9998 6.33268 12.2536 6.33268 11.3332C6.33268 10.4127 5.58649 9.6665 4.66602 9.6665C3.74554 9.6665 2.99935 10.4127 2.99935 11.3332C2.99935 12.2536 3.74554 12.9998 4.66602 12.9998ZM11.3327 6.33317C12.2531 6.33317 12.9993 5.58698 12.9993 4.6665C12.9993 3.74603 12.2531 2.99984 11.3327 2.99984C10.4122 2.99984 9.66602 3.74603 9.66602 4.6665C9.66602 5.58698 10.4122 6.33317 11.3327 6.33317ZM11.3327 12.9998C12.2531 12.9998 12.9993 12.2536 12.9993 11.3332C12.9993 10.4127 12.2531 9.6665 11.3327 9.6665C10.4122 9.6665 9.66602 10.4127 9.66602 11.3332C9.66602 12.2536 10.4122 12.9998 11.3327 12.9998Z", - "fill": "currentColor" - }, - "children": [] - } - ] - } - ] - }, - "name": "Apps02" -} diff --git a/web/app/components/base/icons/src/vender/line/others/Apps02.tsx b/web/app/components/base/icons/src/vender/line/others/Apps02.tsx deleted file mode 100644 index 3236059d8d..0000000000 --- a/web/app/components/base/icons/src/vender/line/others/Apps02.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// GENERATE BY script -// DON NOT EDIT IT MANUALLY - -import * as React from 'react' -import data from './Apps02.json' -import IconBase from '@/app/components/base/icons/IconBase' -import type { IconData } from '@/app/components/base/icons/IconBase' - -const Icon = ( - { - ref, - ...props - }: React.SVGProps & { - ref?: React.RefObject>; - }, -) => - -Icon.displayName = 'Apps02' - -export default Icon diff --git a/web/app/components/base/icons/src/vender/line/others/Exchange02.json b/web/app/components/base/icons/src/vender/line/others/Exchange02.json deleted file mode 100644 index 3672d8b88b..0000000000 --- a/web/app/components/base/icons/src/vender/line/others/Exchange02.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "icon": { - "type": "element", - "isRootNode": true, - "name": "svg", - "attributes": { - "width": "16", - "height": "16", - "viewBox": "0 0 16 16", - "fill": "none", - "xmlns": "http://www.w3.org/2000/svg" - }, - "children": [ - { - "type": "element", - "name": "path", - "attributes": { - "d": "M4.66602 14.3334C3.00916 14.3334 1.66602 12.9903 1.66602 11.3334C1.66602 9.67655 3.00916 8.33342 4.66602 8.33342C6.32287 8.33342 7.66602 9.67655 7.66602 11.3334C7.66602 12.9903 6.32287 14.3334 4.66602 14.3334ZM11.3327 7.66675C9.67582 7.66675 8.33268 6.3236 8.33268 4.66675C8.33268 3.00989 9.67582 1.66675 11.3327 1.66675C12.9895 1.66675 14.3327 3.00989 14.3327 4.66675C14.3327 6.3236 12.9895 7.66675 11.3327 7.66675ZM4.66602 13.0001C5.58649 13.0001 6.33268 12.2539 6.33268 11.3334C6.33268 10.4129 5.58649 9.66675 4.66602 9.66675C3.74554 9.66675 2.99935 10.4129 2.99935 11.3334C2.99935 12.2539 3.74554 13.0001 4.66602 13.0001ZM11.3327 6.33342C12.2531 6.33342 12.9993 5.58722 12.9993 4.66675C12.9993 3.74627 12.2531 3.00008 11.3327 3.00008C10.4122 3.00008 9.66602 3.74627 9.66602 4.66675C9.66602 5.58722 10.4122 6.33342 11.3327 6.33342ZM1.99935 5.33341C1.99935 3.49247 3.49174 2.00008 5.33268 2.00008H7.33268V3.33341H5.33268C4.22812 3.33341 3.33268 4.22885 3.33268 5.33341V7.33342H1.99935V5.33341ZM13.9993 8.66675H12.666V10.6667C12.666 11.7713 11.7706 12.6667 10.666 12.6667H8.66602V14.0001H10.666C12.5069 14.0001 13.9993 12.5077 13.9993 10.6667V8.66675Z", - "fill": "currentColor" - }, - "children": [] - } - ] - }, - "name": "Exchange02" -} diff --git a/web/app/components/base/icons/src/vender/line/others/Exchange02.tsx b/web/app/components/base/icons/src/vender/line/others/Exchange02.tsx deleted file mode 100644 index 4f58de3619..0000000000 --- a/web/app/components/base/icons/src/vender/line/others/Exchange02.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// GENERATE BY script -// DON NOT EDIT IT MANUALLY - -import * as React from 'react' -import data from './Exchange02.json' -import IconBase from '@/app/components/base/icons/IconBase' -import type { IconData } from '@/app/components/base/icons/IconBase' - -const Icon = ( - { - ref, - ...props - }: React.SVGProps & { - ref?: React.RefObject>; - }, -) => - -Icon.displayName = 'Exchange02' - -export default Icon diff --git a/web/app/components/base/icons/src/vender/line/others/FileCode.json b/web/app/components/base/icons/src/vender/line/others/FileCode.json deleted file mode 100644 index d61af3fdb3..0000000000 --- a/web/app/components/base/icons/src/vender/line/others/FileCode.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "icon": { - "type": "element", - "isRootNode": true, - "name": "svg", - "attributes": { - "width": "16", - "height": "16", - "viewBox": "0 0 16 16", - "fill": "none", - "xmlns": "http://www.w3.org/2000/svg" - }, - "children": [ - { - "type": "element", - "name": "path", - "attributes": { - "d": "M10 2.66659H3.33333V13.3333H12.6667V5.33325H10V2.66659ZM2 1.99445C2 1.62929 2.29833 1.33325 2.66567 1.33325H10.6667L13.9998 4.66658L14 13.9949C14 14.3659 13.7034 14.6666 13.3377 14.6666H2.66227C2.29651 14.6666 2 14.3631 2 14.0054V1.99445ZM11.7713 7.99992L9.4142 10.3569L8.4714 9.41412L9.8856 7.99992L8.4714 6.58571L9.4142 5.6429L11.7713 7.99992ZM4.22877 7.99992L6.58579 5.6429L7.5286 6.58571L6.11438 7.99992L7.5286 9.41412L6.58579 10.3569L4.22877 7.99992Z", - "fill": "currentColor" - }, - "children": [] - } - ] - }, - "name": "FileCode" -} diff --git a/web/app/components/base/icons/src/vender/line/others/FileCode.tsx b/web/app/components/base/icons/src/vender/line/others/FileCode.tsx deleted file mode 100644 index 3660aad794..0000000000 --- a/web/app/components/base/icons/src/vender/line/others/FileCode.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// GENERATE BY script -// DON NOT EDIT IT MANUALLY - -import * as React from 'react' -import data from './FileCode.json' -import IconBase from '@/app/components/base/icons/IconBase' -import type { IconData } from '@/app/components/base/icons/IconBase' - -const Icon = ( - { - ref, - ...props - }: React.SVGProps & { - ref?: React.RefObject>; - }, -) => - -Icon.displayName = 'FileCode' - -export default Icon diff --git a/web/app/components/base/icons/src/vender/line/others/index.ts b/web/app/components/base/icons/src/vender/line/others/index.ts index 2322e9d9f1..99db66b397 100644 --- a/web/app/components/base/icons/src/vender/line/others/index.ts +++ b/web/app/components/base/icons/src/vender/line/others/index.ts @@ -1,10 +1,7 @@ -export { default as Apps02 } from './Apps02' export { default as BubbleX } from './BubbleX' export { default as Colors } from './Colors' export { default as DragHandle } from './DragHandle' export { default as Env } from './Env' -export { default as Exchange02 } from './Exchange02' -export { default as FileCode } from './FileCode' export { default as GlobalVariable } from './GlobalVariable' export { default as Icon3Dots } from './Icon3Dots' export { default as LongArrowLeft } from './LongArrowLeft' diff --git a/web/app/components/tools/add-tool-modal/D.png b/web/app/components/tools/add-tool-modal/D.png deleted file mode 100644 index 70b829c821fe5e49cf22ca1c0b55e48d2e46ed9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1139 zcmV-(1dRKMP)ghe-o=);zf`mveCBhOfuzmxGh>&;$kjN2_KtyO0AQB`W0SU>jKuBbFLHx>gZzVcTD<-A4#`h5)OI^;1GzfBW;zKVROAnPKv<=+ zU;lWuyZ2f~g^W?rH49^C=vW0o?cmWl$HP;qfUnlWk#ni#kqIxy34 zR)_Rx{l^r>8IVeu|KGwnV}r7DlQe;8g(kD}01Q$dOh6+$RDlU(bigu&llstk*urUR zgERp;v(+zu?pG5dcRG$PZpXUjiM$w;iRVQ73m~&o)tT3_+X^Uo8@>>rEW0N`XGijJ z?MqtoP_qVB`BRSPp>Znrnb>iO=EV3~YHsW|8 zvM`->dU#PF%u606?DRpF(8#W-a8IOap($0vQi}AFrk|Y?+ez1t768W#a>s!hn+~M) znQSk?ds%W}39kMEda@DrNpgjnFT@O|CzU}EPLC6uupDJ$BD^Ic80D{4H4t08m-l;8 z$5Ffj2(9}OZqNql^B09#0lfe263$PP=BMAeIgSPhfbd$+8Y6w$5S<3AmNwV;?T+A| zzn;S9ADzSVTd=YRX#HiMqYf%;oiL#}(80uxQN-THkwI<=o;}^eF;~morR8GBeK$sr zDGD|X0TiVRe5@3HTX!A+GT#b#UlHt?$<2!q{(H8E#nO7_PPWezL2GFB0o}L~?K$D! z|5ipeJfpO$R-0@<^0yP9n*uv#MMtQ4L$#k0 z3UphP)yOv0Nq;#2M#28TI1vG5peB4_I<6vyF4y|`AHZ}z? z3MfDfaC7lCZY^}(F%fKv1BoWzOzhq!cQr>MHbAB#fQb!%`HfaxI4NZUqR{|^ortVg z-)0nSKW1tqi#i}(uMgij&kq$y9T9XuxI^@Z-*hG!t2A|{5_8Ng*7RlTqY@`- z4?<=WQOloH=8R44CJ0!5&_UUJf`lKwb&lHrN>Od??$90QaTSB^NS~f=Qp4i0XHfc52zolbh2Z5zJZeRcN) zFX0tW1FG#3;`ch&Q3VH4+j1_p9Dv_B7ni3?+`t>2{{f?Ff}eEgCd&W-002ovPDHLk FV1i2L`F;QZ diff --git a/web/app/components/tools/add-tool-modal/category.tsx b/web/app/components/tools/add-tool-modal/category.tsx deleted file mode 100644 index c1467a0ff4..0000000000 --- a/web/app/components/tools/add-tool-modal/category.tsx +++ /dev/null @@ -1,80 +0,0 @@ -'use client' -import { useRef } from 'react' -import { useTranslation } from 'react-i18next' -import { useContext } from 'use-context-selector' -import { useMount } from 'ahooks' -import cn from '@/utils/classnames' -import { Apps02 } from '@/app/components/base/icons/src/vender/line/others' -import I18n from '@/context/i18n' -import { getLanguage } from '@/i18n-config/language' -import { useStore as useLabelStore } from '@/app/components/tools/labels/store' -import { fetchLabelList } from '@/service/tools' -import { renderI18nObject } from '@/i18n-config' - -type Props = { - value: string - onSelect: (type: string) => void -} - -const Icon = ({ svgString, active }: { svgString: string; active: boolean }) => { - const svgRef = useRef(null) - const SVGParser = (svg: string) => { - if (!svg) - return null - const parser = new DOMParser() - const doc = parser.parseFromString(svg, 'image/svg+xml') - return doc.documentElement - } - useMount(() => { - const svgElement = SVGParser(svgString) - if (svgRef.current && svgElement) - svgRef.current.appendChild(svgElement) - }) - return -} - -const Category = ({ - value, - onSelect, -}: Props) => { - const { t } = useTranslation() - const { locale } = useContext(I18n) - const language = getLanguage(locale) - const labelList = useLabelStore(s => s.labelList) - const setLabelList = useLabelStore(s => s.setLabelList) - - useMount(() => { - fetchLabelList().then((res) => { - setLabelList(res) - }) - }) - - return ( -
-
{t('tools.addToolModal.category').toLocaleUpperCase()}
-
onSelect('')}> - - {t('tools.type.all')} -
- {labelList.map((label) => { - const labelText = typeof label.label === 'string' - ? label.label - : (label.label ? renderI18nObject(label.label, language) : '') - return ( -
onSelect(label.name)} - > -
- -
- {labelText} -
- ) - })} -
- ) -} -export default Category diff --git a/web/app/components/tools/add-tool-modal/empty.png b/web/app/components/tools/add-tool-modal/empty.png deleted file mode 100644 index da4007e45acab1ae84864f5e7187cab966d6286d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30290 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
)^_xjGZJnY^#>{Na zc8k{vA)lzLKV)@Ilf5)n!i=OMm-3A#-u>DYa~{9K?Aahd-jv^vs9N&S^dH_cNebpooQvxCrWJ^x_7-;r$kCkmbd`+YTzZxihTxt-Cux>46^1`V@oqnDE!HeLN6k9)uj-Gay`R zo0LZOme={zC=BXDYp7|QH=5>z5iB#e!28k39S!Re-s7Vm*K=PXwarf!G@r?qnQuzF z^s>PYB2jF6gT~T`psklJJSV9R5@&Xup77sNkjifM-=J+POU7;f)>614;o;AFe*HwV zkK1Cmm`jdva`bEcrzaBGL8yNJ`nrdc^63B0_X}z|gbgCFEBe8=z8geDPVWa3Quj+b zkqL0Z*YHe+XS>bR4?QxtIPWV+qL1y3CXzxA>R1bmN$r`a>DpB5^8K*H^ugEWNNCx! zE#F7D>C5W)I%WFATT?FXdR}LOQD*5X*5cYhb#B<;8?EBtwXw16yj`#%NFy#n-Yb7) zPzqA$q8D?-BmmuHIh|>~b;OqPE}pp|JN))VQE&OwbRn%j`rv1DRBHt5lY@Lvs8;FU zy1i>09ZN3QOFpGN130yvLhotM%x%ftAIU*PQcH9A%5Gs>;6T&wU2%8aiC3oh=a4RK zJ?zrkMEMPp(S?SHL5%VTIrYyx4*R0Mj^4z`y;<;BvU)iYs)rf`aVjPiX|Iige*8}T zPo_^emt?eNcJgVzF-Fx-=?zwZes?QjbHIAs^vGy8S9gf(6Zz9kii)$27g(#EP3l0< zysjK`Yo%AOIyx<-Hf^(YzT4N1-e>WR0;xMqeR3m+z&Jq}*2Y2Jk2n4hZ23{@BTBq1 z1`S_(oI9Y~`7`%k7+KBjb#2LQbRgZTXTwAMpmkFvHo%+iDA_fldA-u72jzna|L(BH zn39jsRiHV89&Y~K4C|^E9dNsPsE1($3K-k&1v-T^bX{hPf+#D!Dg&sO&mMxf*VPEO}Z?EO~3 zFvFYr|9jYD#`(mX68~lHFjRhU^C=NRL-|;Q2GLqKG8$1Xg~&!qHddbB$B@`n>s7U| z=mlvf9gY3W{lax~Ej)SrJxOPKT&kECF6pRf{V*Lj9CylSe;eNYiLpOwJ4a~8$s43f4$>y35+>`KHR^n_2DGqSTt}+n6!GL^q8n&LrXr< z-sRqg20@jIdykKtCr`dFE7xuFDOtd7}R6tB2ogDuldfuApWMp3+oJ3=kjKp<*M|M zwJgI+3tz09+FC3(@1}?545baeIoVPU;Msd*T7{#zcoLSIJ9iXh={Lw@4o6GxW--XvIHv}~_J|F%(ar|i*b?pV)SHo0 zfp&GX@&379EWRV+^vwJ;qwjj`O+H(QMYOxI6`xMC~~ zc4YmNp?sRm!DPoP)=H{6ZRyFsY`WIQP_7ZDw)+#St4jQ1?Jy#balIXQJXgBgsPI=G z&!#iw-cOD>M${X9y@3_IjGgK>Av2%PtyJORj;~9oqG%t g7XR;CU+KsUSxb`z3Z3sC{QHHGf$8 void -} -// Add and Edit -const AddToolModal: FC = ({ - onHide, -}) => { - const { t } = useTranslation() - const { locale } = useContext(I18n) - const [currentType, setCurrentType] = useState('builtin') - const [currentCategory, setCurrentCategory] = useState('') - const [keywords, setKeywords] = useState('') - const handleKeywordsChange = (value: string) => { - setKeywords(value) - } - const isMatchingKeywords = (text: string, keywords: string) => { - return text.toLowerCase().includes(keywords.toLowerCase()) - } - const [toolList, setToolList] = useState([]) - const [listLoading, setListLoading] = useState(true) - const getAllTools = async () => { - setListLoading(true) - const buildInTools = await fetchAllBuiltInTools() - if (basePath) { - buildInTools.forEach((item) => { - if (typeof item.icon == 'string' && !item.icon.includes(basePath)) - item.icon = `${basePath}${item.icon}` - }) - } - const customTools = await fetchAllCustomTools() - const workflowTools = await fetchAllWorkflowTools() - const mergedToolList = [ - ...buildInTools, - ...customTools, - ...workflowTools.filter((toolWithProvider) => { - return !toolWithProvider.tools.some((tool) => { - return !!tool.parameters.find(item => item.name === '__image') - }) - }), - ] - setToolList(mergedToolList) - setListLoading(false) - } - const filteredList = useMemo(() => { - return toolList.filter((toolWithProvider) => { - if (currentType === 'all') - return true - else - return toolWithProvider.type === currentType - }).filter((toolWithProvider) => { - if (!currentCategory) - return true - else - return toolWithProvider.labels.includes(currentCategory) - }).filter((toolWithProvider) => { - return ( - isMatchingKeywords(toolWithProvider.name, keywords) - || toolWithProvider.tools.some((tool) => { - return Object.values(tool.label).some((label) => { - return isMatchingKeywords(label, keywords) - }) - }) - ) - }) - }, [currentType, currentCategory, toolList, keywords]) - - const { - modelConfig, - setModelConfig, - } = useContext(ConfigContext) - - const [isShowEditCollectionToolModal, setIsShowEditCustomCollectionModal] = useState(false) - const doCreateCustomToolCollection = async (data: CustomCollectionBackend) => { - await createCustomCollection(data) - Toast.notify({ - type: 'success', - message: t('common.api.actionSuccess'), - }) - setIsShowEditCustomCollectionModal(false) - getAllTools() - } - const [showSettingAuth, setShowSettingAuth] = useState(false) - const [collection, setCollection] = useState() - const toolSelectHandle = (collection: Collection, tool: Tool) => { - const parameters: Record = {} - if (tool.parameters) { - tool.parameters.forEach((item) => { - parameters[item.name] = '' - }) - } - - const nexModelConfig = produce(modelConfig, (draft: ModelConfig) => { - draft.agentConfig.tools.push({ - provider_id: collection.id || collection.name, - provider_type: collection.type as CollectionType, - provider_name: collection.name, - tool_name: tool.name, - tool_label: tool.label[locale] || tool.label[locale.replaceAll('-', '_')], - tool_parameters: parameters, - enabled: true, - }) - }) - setModelConfig(nexModelConfig) - } - const authSelectHandle = (provider: Collection) => { - setCollection(provider) - setShowSettingAuth(true) - } - const updateBuiltinAuth = async (value: Record) => { - if (!collection) - return - await updateBuiltInToolCredential(collection.name, value) - Toast.notify({ - type: 'success', - message: t('common.api.actionSuccess'), - }) - await getAllTools() - setShowSettingAuth(false) - } - const removeBuiltinAuth = async () => { - if (!collection) - return - await removeBuiltInToolCredential(collection.name) - Toast.notify({ - type: 'success', - message: t('common.api.actionSuccess'), - }) - await getAllTools() - setShowSettingAuth(false) - } - - useMount(() => { - getAllTools() - }) - - return ( - <> - -
-
-
-
{t('tools.addTool')}
-
- -
-
-
- - -
-
-
-
-
- handleKeywordsChange(e.target.value)} - onClear={() => handleKeywordsChange('')} - /> -
-
-
- -
-
- {listLoading && ( -
- -
- )} - {!listLoading && ( - - )} -
-
-
- {isShowEditCollectionToolModal && ( - setIsShowEditCustomCollectionModal(false)} - onAdd={doCreateCustomToolCollection} - /> - )} - {showSettingAuth && collection && ( - setShowSettingAuth(false)} - onSaved={updateBuiltinAuth} - onRemove={removeBuiltinAuth} - /> - )} - - - ) -} -export default React.memo(AddToolModal) diff --git a/web/app/components/tools/add-tool-modal/tools.tsx b/web/app/components/tools/add-tool-modal/tools.tsx deleted file mode 100644 index 20f7e6b0da..0000000000 --- a/web/app/components/tools/add-tool-modal/tools.tsx +++ /dev/null @@ -1,158 +0,0 @@ -import { - memo, - useCallback, -} from 'react' -import { basePath } from '@/utils/var' -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' -import type { TypeWithI18N } from '@/app/components/header/account-setting/model-provider-page/declarations' -import { renderI18nObject } from '@/i18n-config' - -const resolveI18nText = (value: TypeWithI18N | string | undefined, language: string): string => { - if (!value) - return '' - return typeof value === 'string' ? value : renderI18nObject(value, language) -} - -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 ( -
-
- {resolveI18nText(toolWithProvider.label, language)} - {t('tools.addToolModal.manageInTools')} -
- {list.map((tool) => { - const labelContent = (() => { - if (!tool.labels) - return '' - return tool.labels.map((name) => { - const label = labelList.find(item => item.name === name) - return resolveI18nText(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 ( - - -
{resolveI18nText(tool.label, language)}
-
{resolveI18nText(tool.description, language)}
- {tool.labels?.length > 0 && ( -
-
- -
{labelContent}
-
-
- )} -
- )} - > -
- -
{resolveI18nText(tool.label, language)}
- {!needAuth && added && ( -
- - {t('tools.addToolModal.added').toLocaleUpperCase()} -
- )} - {!needAuth && !added && addable && ( - - )} - {needAuth && ( - - )} -
- - ) - })} - - ) - }, [addable, language, t, labelList, addedTools, onAuthSetup, onSelect]) - - return ( -
- {!tools.length && !showWorkflowEmpty && ( -
{t('workflow.tabs.noResult')}
- )} - {!tools.length && showWorkflowEmpty && ( -
- -
- )} - {!!tools.length && tools.map(renderGroup)} -
- ) -} - -export default memo(Blocks) diff --git a/web/app/components/tools/add-tool-modal/type.tsx b/web/app/components/tools/add-tool-modal/type.tsx deleted file mode 100644 index 26e78a7525..0000000000 --- a/web/app/components/tools/add-tool-modal/type.tsx +++ /dev/null @@ -1,34 +0,0 @@ -'use client' -import { useTranslation } from 'react-i18next' -import cn from '@/utils/classnames' -import { Exchange02, FileCode } from '@/app/components/base/icons/src/vender/line/others' - -type Props = { - value: string - onSelect: (type: string) => void -} - -const Types = ({ - value, - onSelect, -}: Props) => { - const { t } = useTranslation() - - return ( -
-
onSelect('builtin')}> -
- {t('tools.type.builtIn')} -
-
onSelect('api')}> - - {t('tools.type.custom')} -
-
onSelect('workflow')}> - - {t('tools.type.workflow')} -
-
- ) -} -export default Types diff --git a/web/app/components/tools/provider-list.tsx b/web/app/components/tools/provider-list.tsx index 1679b4469b..01f9f09127 100644 --- a/web/app/components/tools/provider-list.tsx +++ b/web/app/components/tools/provider-list.tsx @@ -11,7 +11,7 @@ import Input from '@/app/components/base/input' import ProviderDetail from '@/app/components/tools/provider/detail' import Empty from '@/app/components/plugins/marketplace/empty' import CustomCreateCard from '@/app/components/tools/provider/custom-create-card' -import WorkflowToolEmpty from '@/app/components/tools/add-tool-modal/empty' +import WorkflowToolEmpty from '@/app/components/tools/provider/empty' import Card from '@/app/components/plugins/card' import CardMoreInfo from '@/app/components/plugins/card/card-more-info' import PluginDetailPanel from '@/app/components/plugins/plugin-detail-panel' diff --git a/web/app/components/tools/add-tool-modal/empty.tsx b/web/app/components/tools/provider/empty.tsx similarity index 100% rename from web/app/components/tools/add-tool-modal/empty.tsx rename to web/app/components/tools/provider/empty.tsx diff --git a/web/app/components/workflow/block-selector/tools.tsx b/web/app/components/workflow/block-selector/tools.tsx index c62f6a67f9..66d880d994 100644 --- a/web/app/components/workflow/block-selector/tools.tsx +++ b/web/app/components/workflow/block-selector/tools.tsx @@ -4,7 +4,7 @@ import IndexBar, { groupItems } from './index-bar' import type { ToolDefaultValue, ToolValue } from './types' import type { ToolTypeEnum } from './types' import { ViewType } from './view-type-select' -import Empty from '@/app/components/tools/add-tool-modal/empty' +import Empty from '@/app/components/tools/provider/empty' import { useGetLanguage } from '@/context/i18n' import ToolListTreeView from './tool/tool-list-tree-view/list' import ToolListFlatView from './tool/tool-list-flat-view/list' diff --git a/web/i18n/de-DE/tools.ts b/web/i18n/de-DE/tools.ts index 8aef8e87f9..4e93b4b71e 100644 --- a/web/i18n/de-DE/tools.ts +++ b/web/i18n/de-DE/tools.ts @@ -2,7 +2,6 @@ const translation = { title: 'Werkzeuge', createCustomTool: 'Eigenes Werkzeug erstellen', type: { - all: 'Alle', builtIn: 'Integriert', custom: 'Benutzerdefiniert', workflow: 'Arbeitsablauf', @@ -20,7 +19,6 @@ const translation = { setupModalTitleDescription: 'Nach der Konfiguration der Anmeldeinformationen können alle Mitglieder im Arbeitsbereich dieses Werkzeug beim Orchestrieren von Anwendungen nutzen.', }, includeToolNum: '{{num}} Werkzeuge inkludiert', - addTool: 'Werkzeug hinzufügen', createTool: { title: 'Eigenes Werkzeug erstellen', editAction: 'Konfigurieren', @@ -143,9 +141,7 @@ const translation = { addToolModal: { type: 'Art', category: 'Kategorie', - add: 'hinzufügen', added: 'zugefügt', - manageInTools: 'Verwalten in Tools', custom: { title: 'Kein benutzerdefiniertes Werkzeug verfügbar', tip: 'Benutzerdefiniertes Werkzeug erstellen', diff --git a/web/i18n/en-US/tools.ts b/web/i18n/en-US/tools.ts index ec78aa2084..308d4b2b05 100644 --- a/web/i18n/en-US/tools.ts +++ b/web/i18n/en-US/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'Create Custom Tool', customToolTip: 'Learn more about Dify custom tools', type: { - all: 'All', builtIn: 'Tools', custom: 'Custom', workflow: 'Workflow', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: 'After configuring credentials, all members within the workspace can use this tool when orchestrating applications.', }, includeToolNum: '{{num}} {{action}} included', - addTool: 'Add Tool', addToolModal: { type: 'type', category: 'category', - add: 'add', added: 'added', - manageInTools: 'Manage in Tools', custom: { title: 'No custom tool available', tip: 'Create a custom tool', diff --git a/web/i18n/es-ES/tools.ts b/web/i18n/es-ES/tools.ts index 304247aee9..f85a44882e 100644 --- a/web/i18n/es-ES/tools.ts +++ b/web/i18n/es-ES/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'Crear Herramienta Personalizada', customToolTip: 'Aprende más sobre las herramientas personalizadas de Dify', type: { - all: 'Todas', builtIn: 'Incorporadas', custom: 'Personalizadas', workflow: 'Flujo de Trabajo', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: 'Después de configurar las credenciales, todos los miembros dentro del espacio de trabajo pueden usar esta herramienta al orquestar aplicaciones.', }, includeToolNum: '{{num}} herramientas incluidas', - addTool: 'Agregar Herramienta', addToolModal: { type: 'tipo', category: 'categoría', - add: 'agregar', added: 'agregada', - manageInTools: 'Administrar en Herramientas', custom: { title: 'No hay herramienta personalizada disponible', tip: 'Crear una herramienta personalizada', diff --git a/web/i18n/fa-IR/tools.ts b/web/i18n/fa-IR/tools.ts index a6be1d0d42..bc0510341b 100644 --- a/web/i18n/fa-IR/tools.ts +++ b/web/i18n/fa-IR/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'ایجاد ابزار سفارشی', customToolTip: 'بیشتر در مورد ابزارهای سفارشی Dify بیاموزید', type: { - all: 'همه', builtIn: 'سفارشی شده', custom: 'سفارشی', workflow: 'جریان کار', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: 'پس از پیکربندی اعتبارنامه‌ها، همه اعضای موجود در فضای کاری می‌توانند از این ابزار هنگام هماهنگی برنامه‌ها استفاده کنند.', }, includeToolNum: '{{num}} ابزار شامل شد', - addTool: 'افزودن ابزار', addToolModal: { type: 'نوع', category: 'دسته‌بندی', - add: 'افزودن', added: 'افزوده شد', - manageInTools: 'مدیریت در ابزارها', custom: { title: 'هیچ ابزار سفارشی موجود نیست', tip: 'یک ابزار سفارشی ایجاد کنید', diff --git a/web/i18n/fr-FR/tools.ts b/web/i18n/fr-FR/tools.ts index 7c0e4db020..9f296773f2 100644 --- a/web/i18n/fr-FR/tools.ts +++ b/web/i18n/fr-FR/tools.ts @@ -2,7 +2,6 @@ const translation = { title: 'Outils', createCustomTool: 'Créer un Outil Personnalisé', type: { - all: 'Tout', builtIn: 'Intégré', custom: 'Personnalisé', workflow: 'Flux de travail', @@ -20,7 +19,6 @@ const translation = { setupModalTitleDescription: 'Après avoir configuré les identifiants, tous les membres de l\'espace de travail peuvent utiliser cet outil lors de l\'orchestration des applications.', }, includeToolNum: '{{num}} outils inclus', - addTool: 'Ajouter un outil', createTool: { title: 'Créer un Outil Personnalisé', editAction: 'Configurer', @@ -143,9 +141,7 @@ const translation = { addToolModal: { type: 'type', added: 'supplémentaire', - add: 'ajouter', category: 'catégorie', - manageInTools: 'Gérer dans Outils', custom: { title: 'Aucun outil personnalisé disponible', tip: 'Créer un outil personnalisé', diff --git a/web/i18n/hi-IN/tools.ts b/web/i18n/hi-IN/tools.ts index 6e6dcf0ff6..c606f5f0b3 100644 --- a/web/i18n/hi-IN/tools.ts +++ b/web/i18n/hi-IN/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'कस्टम उपकरण बनाएं', customToolTip: 'Dify कस्टम उपकरणों के बारे में और जानें', type: { - all: 'सभी', builtIn: 'निर्मित', custom: 'कस्टम', workflow: 'कार्यप्रवाह', @@ -22,13 +21,10 @@ const translation = { 'प्रमाणिकरण कॉन्फ़िगर करने के बाद, कार्यस्थान के सभी सदस्य इस उपकरण का उपयोग कर सकेंगे।', }, includeToolNum: '{{num}} उपकरण शामिल हैं', - addTool: 'उपकरण जोड़ें', addToolModal: { type: 'प्रकार', category: 'श्रेणी', - add: 'जोड़ें', added: 'जोड़ा गया', - manageInTools: 'उपकरणों में प्रबंधित करें', custom: { title: 'कोई कस्टम टूल उपलब्ध नहीं है', tip: 'एक कस्टम टूल बनाएं', diff --git a/web/i18n/id-ID/tools.ts b/web/i18n/id-ID/tools.ts index 707594446d..d9866dfb58 100644 --- a/web/i18n/id-ID/tools.ts +++ b/web/i18n/id-ID/tools.ts @@ -1,6 +1,5 @@ const translation = { type: { - all: 'Semua', workflow: 'Alur Kerja', builtIn: 'Perkakas', custom: 'Adat', @@ -35,8 +34,6 @@ const translation = { category: 'golongan', type: 'jenis', added: 'Ditambahkan', - add: 'tambah', - manageInTools: 'Kelola di Alat', }, createTool: { exampleOptions: { @@ -240,7 +237,6 @@ const translation = { title: 'Perkakas', createCustomTool: 'Buat Alat Kustom', customToolTip: 'Pelajari alat kustom Dify lebih lanjut', - addTool: 'Tambahkan Alat', author: 'Oleh', copyToolName: 'Salin Nama', howToGet: 'Cara mendapatkan', diff --git a/web/i18n/it-IT/tools.ts b/web/i18n/it-IT/tools.ts index 0b8b122518..a81898eff2 100644 --- a/web/i18n/it-IT/tools.ts +++ b/web/i18n/it-IT/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'Crea Strumento Personalizzato', customToolTip: 'Scopri di più sugli strumenti personalizzati di Dify', type: { - all: 'Tutti', builtIn: 'Integrato', custom: 'Personalizzato', workflow: 'Flusso di lavoro', @@ -22,13 +21,10 @@ const translation = { 'Dopo aver configurato le credenziali, tutti i membri all\'interno del workspace possono utilizzare questo strumento durante l\'orchestrazione delle applicazioni.', }, includeToolNum: '{{num}} strumenti inclusi', - addTool: 'Aggiungi Strumento', addToolModal: { type: 'tipo', category: 'categoria', - add: 'aggiungi', added: 'aggiunto', - manageInTools: 'Gestisci in Strumenti', custom: { title: 'Nessuno strumento personalizzato disponibile', tip: 'Crea uno strumento personalizzato', diff --git a/web/i18n/ja-JP/tools.ts b/web/i18n/ja-JP/tools.ts index 812b5f3c92..8df59af218 100644 --- a/web/i18n/ja-JP/tools.ts +++ b/web/i18n/ja-JP/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'カスタムツールを作成する', customToolTip: 'Dify カスタムツールの詳細', type: { - all: 'すべて', builtIn: 'ツール', custom: 'カスタム', workflow: 'ワークフロー', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: '資格情報を構成した後、ワークスペース内のすべてのメンバーがアプリケーションのオーケストレーション時にこのツールを使用できます。', }, includeToolNum: '{{num}}個のツールが含まれています', - addTool: 'ツールを追加する', addToolModal: { type: 'タイプ', category: 'カテゴリー', - add: '追加', added: '追加済', - manageInTools: 'ツールリストに移動して管理する', custom: { title: 'カスタムツールはありません', tip: 'カスタムツールを作成する', diff --git a/web/i18n/ko-KR/tools.ts b/web/i18n/ko-KR/tools.ts index ddcefe4bd4..6bfed4e859 100644 --- a/web/i18n/ko-KR/tools.ts +++ b/web/i18n/ko-KR/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: '커스텀 도구 만들기', customToolTip: 'Dify 커스텀 도구에 대해 더 알아보기', type: { - all: '모두', builtIn: '내장', custom: '커스텀', workflow: '워크플로우', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: '자격 증명을 구성한 후에 워크스페이스의 모든 멤버가 이 도구를 사용하여 애플리케이션을 조작할 수 있습니다.', }, includeToolNum: '{{num}}개의 도구가 포함되어 있습니다', - addTool: '도구 추가', addToolModal: { type: '타입', category: '카테고리', - add: '추가', added: '추가됨', - manageInTools: '도구에서 관리', custom: { title: '사용자 정의 도구 없음', tip: '사용자 정의 도구 생성', diff --git a/web/i18n/pl-PL/tools.ts b/web/i18n/pl-PL/tools.ts index 16fe5037df..fa6c5931e7 100644 --- a/web/i18n/pl-PL/tools.ts +++ b/web/i18n/pl-PL/tools.ts @@ -2,7 +2,6 @@ const translation = { title: 'Narzędzia', createCustomTool: 'Utwórz niestandardowe narzędzie', type: { - all: 'Wszystkie', builtIn: 'Wbudowane', custom: 'Niestandardowe', workflow: 'Przepływ pracy', @@ -21,7 +20,6 @@ const translation = { 'Po skonfigurowaniu poświadczeń wszyscy członkowie w przestrzeni roboczej mogą używać tego narzędzia podczas projektowania aplikacji.', }, includeToolNum: '{{num}} narzędzi zawarte', - addTool: 'Dodaj narzędzie', createTool: { title: 'Utwórz niestandardowe narzędzie', editAction: 'Konfiguruj', @@ -145,11 +143,9 @@ const translation = { notAuthorized: 'Narzędzie nieautoryzowane', howToGet: 'Jak uzyskać', addToolModal: { - manageInTools: 'Zarządzanie w Narzędziach', added: 'Dodane', type: 'typ', category: 'kategoria', - add: 'dodawać', custom: { title: 'Brak dostępnego narzędzia niestandardowego', tip: 'Utwórz narzędzie niestandardowe', diff --git a/web/i18n/pt-BR/tools.ts b/web/i18n/pt-BR/tools.ts index 66b040275d..6d5344b11b 100644 --- a/web/i18n/pt-BR/tools.ts +++ b/web/i18n/pt-BR/tools.ts @@ -2,7 +2,6 @@ const translation = { title: 'Ferramentas', createCustomTool: 'Criar Ferramenta Personalizada', type: { - all: 'Todas', builtIn: 'Integradas', custom: 'Personalizadas', workflow: 'Fluxo de trabalho', @@ -20,7 +19,6 @@ const translation = { setupModalTitleDescription: 'Após configurar as credenciais, todos os membros do espaço de trabalho podem usar essa ferramenta ao orquestrar aplicativos.', }, includeToolNum: '{{num}} ferramentas incluídas', - addTool: 'Adicionar Ferramenta', createTool: { title: 'Criar Ferramenta Personalizada', editAction: 'Configurar', @@ -143,9 +141,7 @@ const translation = { addToolModal: { category: 'categoria', type: 'tipo', - add: 'adicionar', added: 'Adicionado', - manageInTools: 'Gerenciar em Ferramentas', custom: { title: 'Nenhuma ferramenta personalizada disponível', tip: 'Crie uma ferramenta personalizada', diff --git a/web/i18n/ro-RO/tools.ts b/web/i18n/ro-RO/tools.ts index 72c3954c97..c9eeb29d97 100644 --- a/web/i18n/ro-RO/tools.ts +++ b/web/i18n/ro-RO/tools.ts @@ -2,7 +2,6 @@ const translation = { title: 'Instrumente', createCustomTool: 'Creează Instrument Personalizat', type: { - all: 'Toate', builtIn: 'Incorporat', custom: 'Personalizat', workflow: 'Flux de lucru', @@ -20,7 +19,6 @@ const translation = { setupModalTitleDescription: 'După configurarea credențialelor, toți membrii din spațiul de lucru pot utiliza acest instrument la orchestrarea aplicațiilor.', }, includeToolNum: '{{num}} instrumente incluse', - addTool: 'Adaugă Instrument', createTool: { title: 'Creează Instrument Personalizat', editAction: 'Configurează', @@ -143,8 +141,6 @@ const translation = { addToolModal: { added: 'adăugat', category: 'categorie', - manageInTools: 'Gestionați în Instrumente', - add: 'adăuga', type: 'tip', custom: { title: 'Niciun instrument personalizat disponibil', diff --git a/web/i18n/ru-RU/tools.ts b/web/i18n/ru-RU/tools.ts index 7ee263657d..48de76e383 100644 --- a/web/i18n/ru-RU/tools.ts +++ b/web/i18n/ru-RU/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'Создать пользовательский инструмент', customToolTip: 'Узнать больше о пользовательских инструментах Dify', type: { - all: 'Все', builtIn: 'Встроенные', custom: 'Пользовательские', workflow: 'Рабочий процесс', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: 'После настройки учетных данных все участники рабочего пространства смогут использовать этот инструмент при оркестровке приложений.', }, includeToolNum: 'Включено {{num}} инструментов', - addTool: 'Добавить инструмент', addToolModal: { type: 'тип', category: 'категория', - add: 'добавить', added: 'добавлено', - manageInTools: 'Управлять в инструментах', custom: { title: 'Нет доступного пользовательского инструмента', tip: 'Создать пользовательский инструмент', diff --git a/web/i18n/sl-SI/tools.ts b/web/i18n/sl-SI/tools.ts index cae126d99d..f8dd1dc831 100644 --- a/web/i18n/sl-SI/tools.ts +++ b/web/i18n/sl-SI/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'Ustvari prilagojeno orodje', customToolTip: 'Izvedite več o prilagojenih orodjih Dify', type: { - all: 'Vsa', builtIn: 'Vgrajena', custom: 'Prilagojena', workflow: 'Potek dela', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: 'Po konfiguraciji poverilnic bodo vsi člani znotraj delovnega prostora lahko uporabljali to orodje pri orkestraciji aplikacij.', }, includeToolNum: 'Vključeno {{num}} orodij', - addTool: 'Dodaj orodje', addToolModal: { type: 'tip', category: 'kategorija', - add: 'dodaj', added: 'dodano', - manageInTools: 'Upravljaj v Orodjih', custom: { title: 'Žiadne prispôsobené nástroje nie sú k dispozícii', tip: 'Vytvorte prispôsobený nástroj', diff --git a/web/i18n/th-TH/tools.ts b/web/i18n/th-TH/tools.ts index 848a3f51b6..47e160c9e9 100644 --- a/web/i18n/th-TH/tools.ts +++ b/web/i18n/th-TH/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'สร้างเครื่องมือที่กําหนดเอง', customToolTip: 'เรียนรู้เพิ่มเติมเกี่ยวกับเครื่องมือแบบกําหนดเองของ Dify', type: { - all: 'ทั้งหมด', builtIn: 'ในตัว', custom: 'ธรรมเนียม', workflow: 'เวิร์กโฟลว์', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: 'หลังจากกําหนดค่าข้อมูลประจําตัวแล้ว สมาชิกทั้งหมดภายในพื้นที่ทํางานสามารถใช้เครื่องมือนี้เมื่อประสานงานแอปพลิเคชันได้', }, includeToolNum: '{{num}} รวมเครื่องมือ', - addTool: 'เพิ่มเครื่องมือ', addToolModal: { type: 'ประเภท', category: 'ประเภท', - add: 'เพิ่ม', added: 'เพิ่ม', - manageInTools: 'จัดการในเครื่องมือ', custom: { title: 'ไม่มีเครื่องมือกำหนดเอง', tip: 'สร้างเครื่องมือกำหนดเอง', diff --git a/web/i18n/tr-TR/tools.ts b/web/i18n/tr-TR/tools.ts index ccc97fef10..12849b1879 100644 --- a/web/i18n/tr-TR/tools.ts +++ b/web/i18n/tr-TR/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: 'Özel Araç Oluştur', customToolTip: 'Dify özel araçları hakkında daha fazla bilgi edinin', type: { - all: 'Hepsi', builtIn: 'Yerleşik', custom: 'Özel', workflow: 'Workflow', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: 'Kimlik bilgilerini yapılandırdıktan sonra, çalışma alanındaki tüm üyeler uygulamaları düzenlerken bu aracı kullanabilir.', }, includeToolNum: '{{num}} araç dahil', - addTool: 'Araç Ekle', addToolModal: { type: 'Tür', category: 'Kategori', - add: 'Ekle', added: 'Eklendi', - manageInTools: 'Araçlarda Yönet', custom: { title: 'Mevcut özel araç yok', tip: 'Özel bir araç oluşturun', diff --git a/web/i18n/uk-UA/tools.ts b/web/i18n/uk-UA/tools.ts index 40e35a1236..3a3f72b5ba 100644 --- a/web/i18n/uk-UA/tools.ts +++ b/web/i18n/uk-UA/tools.ts @@ -2,7 +2,6 @@ const translation = { title: 'Інструменти', createCustomTool: 'Створити власний інструмент', type: { - all: 'Усі', builtIn: 'Вбудовані', custom: 'Користувацькі', workflow: 'Робочий процес', @@ -20,7 +19,6 @@ const translation = { setupModalTitleDescription: 'Після налаштування облікових даних усі члени робочого простору можуть використовувати цей інструмент під час оркестрування програм.', }, includeToolNum: '{{num}} інструмент(ів) включено', - addTool: 'Додати інструмент ', createTool: { title: 'Створити власний інструмент', editAction: 'Налаштування', @@ -142,10 +140,8 @@ const translation = { howToGet: 'Як отримати', addToolModal: { category: 'категорія', - add: 'Додати', added: 'Додано', type: 'тип', - manageInTools: 'Керування в інструментах', custom: { title: 'Немає доступного користувацького інструмента', tip: 'Створити користувацький інструмент', diff --git a/web/i18n/vi-VN/tools.ts b/web/i18n/vi-VN/tools.ts index 08041ce400..a499a451a3 100644 --- a/web/i18n/vi-VN/tools.ts +++ b/web/i18n/vi-VN/tools.ts @@ -2,7 +2,6 @@ const translation = { title: 'Công cụ', createCustomTool: 'Tạo công cụ tùy chỉnh', type: { - all: 'Tất cả', builtIn: 'Tích hợp sẵn', custom: 'Tùy chỉnh', workflow: 'Quy trình làm việc', @@ -20,7 +19,6 @@ const translation = { setupModalTitleDescription: 'Sau khi cấu hình thông tin đăng nhập, tất cả thành viên trong không gian làm việc có thể sử dụng công cụ này khi triển khai ứng dụng.', }, includeToolNum: 'Bao gồm {{num}} công cụ', - addTool: 'Thêm công cụ', createTool: { title: 'Tạo công cụ tùy chỉnh', editAction: 'Cấu hình', @@ -142,9 +140,7 @@ const translation = { howToGet: 'Cách nhận', addToolModal: { category: 'loại', - manageInTools: 'Quản lý trong Công cụ', type: 'kiểu', - add: 'thêm', added: 'Thêm', custom: { title: 'Không có công cụ tùy chỉnh nào', diff --git a/web/i18n/zh-Hans/tools.ts b/web/i18n/zh-Hans/tools.ts index ce203a0592..cab4b22164 100644 --- a/web/i18n/zh-Hans/tools.ts +++ b/web/i18n/zh-Hans/tools.ts @@ -3,7 +3,6 @@ const translation = { createCustomTool: '创建自定义工具', customToolTip: '了解更多关于 Dify 自定义工具的信息', type: { - all: '全部', builtIn: '工具', custom: '自定义', workflow: '工作流', @@ -21,13 +20,10 @@ const translation = { setupModalTitleDescription: '配置凭据后,工作区中的所有成员都可以在编排应用程序时使用此工具。', }, includeToolNum: '包含 {{num}} 个 {{action}}', - addTool: '添加工具', addToolModal: { type: '类型', category: '类别', - add: '添加', added: '已添加', - manageInTools: '去工具列表管理', custom: { title: '没有可用的自定义工具', tip: '创建自定义工具', diff --git a/web/i18n/zh-Hant/tools.ts b/web/i18n/zh-Hant/tools.ts index d9aa901278..246d2d9dd5 100644 --- a/web/i18n/zh-Hant/tools.ts +++ b/web/i18n/zh-Hant/tools.ts @@ -2,7 +2,6 @@ const translation = { title: '工具', createCustomTool: '建立自定義工具', type: { - all: '全部', builtIn: '內建', custom: '自定義', workflow: '工作流', @@ -20,7 +19,6 @@ const translation = { setupModalTitleDescription: '配置憑據後,工作區中的所有成員都可以在編排應用程式時使用此工具。', }, includeToolNum: '包含 {{num}} 個工具', - addTool: '新增工具', createTool: { title: '建立自定義工具', editAction: '編輯', @@ -141,10 +139,8 @@ const translation = { notAuthorized: '工具未授權', howToGet: '如何獲取', addToolModal: { - add: '加', type: '類型', added: '新增', - manageInTools: '在工具中管理', category: '類別', custom: { title: '沒有可用的自訂工具', diff --git a/web/service/tools.ts b/web/service/tools.ts index 6a88d8d567..2897ccac12 100644 --- a/web/service/tools.ts +++ b/web/service/tools.ts @@ -8,8 +8,6 @@ import type { WorkflowToolProviderRequest, WorkflowToolProviderResponse, } from '@/app/components/tools/types' -import type { ToolWithProvider } from '@/app/components/workflow/types' -import type { Label } from '@/app/components/tools/labels/constant' import { buildProviderQuery } from './_tools_util' export const fetchCollectionList = () => { @@ -112,26 +110,6 @@ export const testAPIAvailable = (payload: any) => { }) } -export const fetchAllBuiltInTools = () => { - return get('/workspaces/current/tools/builtin') -} - -export const fetchAllCustomTools = () => { - return get('/workspaces/current/tools/api') -} - -export const fetchAllWorkflowTools = () => { - return get('/workspaces/current/tools/workflow') -} - -export const fetchAllMCPTools = () => { - return get('/workspaces/current/tools/mcp') -} - -export const fetchLabelList = () => { - return get('/workspaces/current/tool-labels') -} - export const createWorkflowToolProvider = (payload: WorkflowToolProviderRequest & { workflow_app_id: string }) => { return post('/workspaces/current/tool-provider/workflow/create', { body: { ...payload },