diff --git a/web/app/components/plugins/hooks.ts b/web/app/components/plugins/hooks.ts index 0349c46f9e..2717740272 100644 --- a/web/app/components/plugins/hooks.ts +++ b/web/app/components/plugins/hooks.ts @@ -5,7 +5,7 @@ import { tagKeys, } from './constants' -type Tag = { +export type Tag = { name: string label: string } diff --git a/web/app/components/plugins/marketplace/search-box/index.tsx b/web/app/components/plugins/marketplace/search-box/index.tsx index 277aa79843..0bc214ae1a 100644 --- a/web/app/components/plugins/marketplace/search-box/index.tsx +++ b/web/app/components/plugins/marketplace/search-box/index.tsx @@ -4,6 +4,7 @@ import TagsFilter from './tags-filter' import ActionButton from '@/app/components/base/action-button' import cn from '@/utils/classnames' import { RiAddLine } from '@remixicon/react' +import Divider from '@/app/components/base/divider' type SearchBoxProps = { search: string @@ -12,10 +13,10 @@ type SearchBoxProps = { inputClassName?: string tags: string[] onTagsChange: (tags: string[]) => void - size?: 'small' | 'large' placeholder?: string locale?: string supportAddCustomTool?: boolean + usedInMarketplace?: boolean onShowAddCustomCollectionModal?: () => void onAddedCustomTool?: () => void } @@ -26,9 +27,9 @@ const SearchBox = ({ inputClassName, tags, onTagsChange, - size = 'small', placeholder = '', locale, + usedInMarketplace = false, supportAddCustomTool, onShowAddCustomCollectionModal, }: SearchBoxProps) => { @@ -38,42 +39,82 @@ const SearchBox = ({ >
-
-
- - { - onSearchChange(e.target.value) - }} - placeholder={placeholder} - /> - { - search && ( -
- onSearchChange('')}> - - -
- ) - } -
-
-
- + { + usedInMarketplace && ( + <> + + +
+ { + onSearchChange(e.target.value) + }} + placeholder={placeholder} + /> + { + search && ( + onSearchChange('')} + className='shrink-0' + > + + + ) + } +
+ + ) + } + { + !usedInMarketplace && ( + <> +
+ + { + onSearchChange(e.target.value) + }} + placeholder={placeholder} + /> + { + search && ( + onSearchChange('')} + className='shrink-0' + > + + + ) + } +
+ + + + ) + }
{supportAddCustomTool && (
diff --git a/web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx b/web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx index 0a63361af0..e73a23f6ad 100644 --- a/web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx +++ b/web/app/components/plugins/marketplace/search-box/search-box-wrapper.tsx @@ -36,9 +36,9 @@ const SearchBoxWrapper = ({ onSearchChange={handleSearchPluginTextChange} tags={filterPluginTags} onTagsChange={handleFilterPluginTagsChange} - size='large' locale={locale} placeholder={t('plugin.searchPlugins')} + usedInMarketplace /> ) } diff --git a/web/app/components/plugins/marketplace/search-box/tags-filter.tsx b/web/app/components/plugins/marketplace/search-box/tags-filter.tsx index c0df2fe092..22c49b2280 100644 --- a/web/app/components/plugins/marketplace/search-box/tags-filter.tsx +++ b/web/app/components/plugins/marketplace/search-box/tags-filter.tsx @@ -1,40 +1,29 @@ 'use client' import { useState } from 'react' -import type { ReactElement } from 'react' -import { - RiCloseCircleFill, - RiFilter3Line, - RiPriceTag3Line, -} from '@remixicon/react' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger, } from '@/app/components/base/portal-to-follow-elem' import Checkbox from '@/app/components/base/checkbox' -import cn from '@/utils/classnames' import Input from '@/app/components/base/input' import { useTags } from '@/app/components/plugins/hooks' import { useMixedTranslation } from '@/app/components/plugins/marketplace/hooks' +import MarketplaceTrigger from './trigger/marketplace' +import ToolSelectorTrigger from './trigger/tool-selector' type TagsFilterProps = { tags: string[] onTagsChange: (tags: string[]) => void - size: 'small' | 'large' + usedInMarketplace?: boolean locale?: string - emptyTrigger?: ReactElement - className?: string - triggerClassName?: string } const TagsFilter = ({ tags, onTagsChange, - size, + usedInMarketplace = false, locale, - emptyTrigger, - className, - triggerClassName, }: TagsFilterProps) => { const { t } = useMixedTranslation(locale) const [open, setOpen] = useState(false) @@ -63,55 +52,29 @@ const TagsFilter = ({ className='shrink-0' onClick={() => setOpen(v => !v)} > -
- { - !emptyTrigger && ( -
- -
- ) - } -
- { - !selectedTagsLength && (emptyTrigger || t('pluginTags.allTags')) - } - { - !!selectedTagsLength && tags.map(tag => tagsMap[tag].label).slice(0, 2).join(',') - } - { - selectedTagsLength > 2 && ( -
- +{selectedTagsLength - 2} -
- ) - } -
- { - !!selectedTagsLength && ( - onTagsChange([])} - /> - ) - } - { - !selectedTagsLength && !emptyTrigger && ( -
- -
- ) - } -
+ { + usedInMarketplace && ( + + ) + } + { + !usedInMarketplace && ( + + ) + }
diff --git a/web/app/components/plugins/marketplace/search-box/trigger/marketplace.tsx b/web/app/components/plugins/marketplace/search-box/trigger/marketplace.tsx new file mode 100644 index 0000000000..3945e9460e --- /dev/null +++ b/web/app/components/plugins/marketplace/search-box/trigger/marketplace.tsx @@ -0,0 +1,75 @@ +import React from 'react' +import { RiArrowDownSLine, RiCloseCircleFill, RiFilter3Line } from '@remixicon/react' +import type { Tag } from '../../../hooks' +import cn from '@/utils/classnames' +import { useMixedTranslation } from '../../hooks' + +type MarketplaceTriggerProps = { + selectedTagsLength: number + open: boolean + tags: string[] + tagsMap: Record + locale?: string + onTagsChange: (tags: string[]) => void +} + +const MarketplaceTrigger = ({ + selectedTagsLength, + open, + tags, + tagsMap, + locale, + onTagsChange, +}: MarketplaceTriggerProps) => { + const { t } = useMixedTranslation(locale) + + return ( +
+
+ +
+
+ { + !selectedTagsLength && {t('pluginTags.allTags')} + } + { + !!selectedTagsLength && ( + + {tags.map(tag => tagsMap[tag].label).slice(0, 2).join(',')} + + ) + } + { + selectedTagsLength > 2 && ( +
+ +{selectedTagsLength - 2} +
+ ) + } +
+ { + !!selectedTagsLength && ( + onTagsChange([])} + /> + ) + } + { + !selectedTagsLength && ( +
+ +
+ ) + } +
+ ) +} + +export default React.memo(MarketplaceTrigger) diff --git a/web/app/components/plugins/marketplace/search-box/trigger/tool-selector.tsx b/web/app/components/plugins/marketplace/search-box/trigger/tool-selector.tsx new file mode 100644 index 0000000000..43f1a20840 --- /dev/null +++ b/web/app/components/plugins/marketplace/search-box/trigger/tool-selector.tsx @@ -0,0 +1,60 @@ +import React from 'react' +import type { Tag } from '../../../hooks' +import cn from '@/utils/classnames' +import { RiCloseCircleFill, RiPriceTag3Line } from '@remixicon/react' + +type ToolSelectorTriggerProps = { + selectedTagsLength: number + open: boolean + tags: string[] + tagsMap: Record + onTagsChange: (tags: string[]) => void +} + +const ToolSelectorTrigger = ({ + selectedTagsLength, + open, + tags, + tagsMap, + onTagsChange, +}: ToolSelectorTriggerProps) => { + return ( +
+
+ +
+ { + !!selectedTagsLength && ( +
+ + {tags.map(tag => tagsMap[tag].label).slice(0, 2).join(',')} + + { + selectedTagsLength > 2 && ( +
+ +{selectedTagsLength - 2} +
+ ) + } +
+ ) + } + { + !!selectedTagsLength && ( + onTagsChange([])} + /> + ) + } +
+ ) +} + +export default React.memo(ToolSelectorTrigger) diff --git a/web/app/components/plugins/reference-setting-modal/auto-update-setting/tool-picker.tsx b/web/app/components/plugins/reference-setting-modal/auto-update-setting/tool-picker.tsx index 02c1ecaf35..0e48a07f46 100644 --- a/web/app/components/plugins/reference-setting-modal/auto-update-setting/tool-picker.tsx +++ b/web/app/components/plugins/reference-setting-modal/auto-update-setting/tool-picker.tsx @@ -131,7 +131,6 @@ const ToolPicker: FC = ({ onSearchChange={setQuery} tags={tags} onTagsChange={setTags} - size='small' placeholder={t('plugin.searchTools')!} inputClassName='w-full' /> diff --git a/web/app/components/workflow/block-selector/main.tsx b/web/app/components/workflow/block-selector/main.tsx index 4cef6c559b..0e97cefc90 100644 --- a/web/app/components/workflow/block-selector/main.tsx +++ b/web/app/components/workflow/block-selector/main.tsx @@ -184,7 +184,6 @@ const NodeSelector: FC = ({ onSearchChange={setSearchText} tags={tags} onTagsChange={setTags} - size='small' placeholder={t('plugin.searchTools')!} inputClassName='grow' /> diff --git a/web/app/components/workflow/block-selector/tool-picker.tsx b/web/app/components/workflow/block-selector/tool-picker.tsx index d97a4f3a1b..ced6d3e88f 100644 --- a/web/app/components/workflow/block-selector/tool-picker.tsx +++ b/web/app/components/workflow/block-selector/tool-picker.tsx @@ -13,7 +13,7 @@ import type { } from '@floating-ui/react' import AllTools from '@/app/components/workflow/block-selector/all-tools' import type { ToolDefaultValue, ToolValue } from './types' -import type { BlockEnum } from '@/app/components/workflow/types' +import type { BlockEnum, OnSelectBlock } from '@/app/components/workflow/types' import SearchBox from '@/app/components/plugins/marketplace/search-box' import { useTranslation } from 'react-i18next' import { useBoolean } from 'ahooks' @@ -158,13 +158,11 @@ const ToolPicker: FC = ({ onSearchChange={setSearchText} tags={tags} onTagsChange={setTags} - size='small' placeholder={t('plugin.searchTools')!} supportAddCustomTool={supportAddCustomTool} onAddedCustomTool={handleAddedCustomTool} onShowAddCustomCollectionModal={showEditCustomCollectionModal} inputClassName='grow' - />
= ({ toolContentClassName='max-w-[100%]' tags={tags} searchText={searchText} - onSelect={handleSelect} + onSelect={handleSelect as OnSelectBlock} onSelectMultiple={handleSelectMultiple} buildInTools={builtinToolList || []} customTools={customToolList || []} diff --git a/web/app/components/workflow/block-selector/tool-search-input-tag.tsx b/web/app/components/workflow/block-selector/tool-search-input-tag.tsx deleted file mode 100644 index fbec3ca1a2..0000000000 --- a/web/app/components/workflow/block-selector/tool-search-input-tag.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { memo } from 'react' -import { RiPriceTag3Line } from '@remixicon/react' -import TagsFilter from '@/app/components/plugins/marketplace/search-box/tags-filter' -import cn from '@/utils/classnames' - -type ToolSearchInputTagProps = { - tags: string[] - onTagsChange: (tags: string[]) => void -} -const ToolSearchInputTag = ({ - tags, - onTagsChange, -}: ToolSearchInputTagProps) => { - return ( - - -
- } - /> - ) -} - -export default memo(ToolSearchInputTag)