diff --git a/web/app/components/workflow/block-selector/featured-tools.tsx b/web/app/components/workflow/block-selector/featured-tools.tsx index e65b99f21c..9e4ba74ba5 100644 --- a/web/app/components/workflow/block-selector/featured-tools.tsx +++ b/web/app/components/workflow/block-selector/featured-tools.tsx @@ -5,8 +5,8 @@ import { BlockEnum, type ToolWithProvider } from '../types' import type { ToolDefaultValue, ToolValue } from './types' import type { Plugin } from '@/app/components/plugins/types' import { useGetLanguage } from '@/context/i18n' -import Button from '@/app/components/base/button' import BlockIcon from '../block-icon' +import Tooltip from '@/app/components/base/tooltip' import { RiArrowDownSLine, RiArrowRightSLine, RiLoader2Line, RiMoreLine } from '@remixicon/react' import { useInstallPackageFromMarketPlace } from '@/service/use-plugins' import Loading from '@/app/components/base/loading' @@ -15,6 +15,8 @@ import { getMarketplaceUrl } from '@/utils/var' import { ToolTypeEnum } from './types' import { ViewType } from './view-type-select' import Tools from './tools' +import { formatNumber } from '@/utils/format' +import Action from '@/app/components/workflow/block-selector/market-place-plugin/action' const MAX_RECOMMENDED_COUNT = 15 const INITIAL_VISIBLE_COUNT = 5 @@ -44,11 +46,16 @@ const FeaturedTools = ({ const language = useGetLanguage() const [visibleCount, setVisibleCount] = useState(INITIAL_VISIBLE_COUNT) const [installingIdentifier, setInstallingIdentifier] = useState(null) - const [isCollapsed, setIsCollapsed] = useState(false) + const [isCollapsed, setIsCollapsed] = useState(() => { + if (typeof window === 'undefined') + return false + const stored = window.localStorage.getItem(STORAGE_KEY) + return stored === 'true' + }) const installMutation = useInstallPackageFromMarketPlace({ - onSuccess: () => { - onInstallSuccess?.() + onSuccess: async () => { + await onInstallSuccess?.() }, onSettled: () => { setInstallingIdentifier(null) @@ -99,11 +106,11 @@ const FeaturedTools = ({
{!isCollapsed && ( @@ -198,33 +205,88 @@ function FeaturedToolUninstalledItem({ }: FeaturedToolUninstalledItemProps) { const label = plugin.label?.[language] || plugin.name const description = typeof plugin.brief === 'object' ? plugin.brief[language] : plugin.brief - const installCountLabel = t('plugin.install', { num: plugin.install_count?.toLocaleString() ?? 0 }) + const installCountLabel = t('plugin.install', { num: formatNumber(plugin.install_count || 0) }) + const [actionOpen, setActionOpen] = useState(false) + const [isActionHovered, setIsActionHovered] = useState(false) + + useEffect(() => { + if (!actionOpen) + return + + const handleScroll = () => { + setActionOpen(false) + setIsActionHovered(false) + } + + window.addEventListener('scroll', handleScroll, true) + + return () => { + window.removeEventListener('scroll', handleScroll, true) + } + }, [actionOpen]) return ( -
-
- -
-
{label}
- {description && ( -
{description}
- )} + + +
{label}
+
{description}
+
+ )} + disabled={!description || isActionHovered || actionOpen} + > +
{ + if (!actionOpen) + setIsActionHovered(false) + }} + > +
+ +
+
{label}
+
+
+
+ {installCountLabel} +
setIsActionHovered(true)} + onMouseLeave={() => { + if (!actionOpen) + setIsActionHovered(false) + }} + > + +
+ { + setActionOpen(value) + setIsActionHovered(value) + }} + author={plugin.org} + name={plugin.name} + version={plugin.latest_version} + /> +
+
-
- {installCountLabel} - -
-
+ ) } diff --git a/web/app/components/workflow/block-selector/market-place-plugin/action.tsx b/web/app/components/workflow/block-selector/market-place-plugin/action.tsx index 56ee420cff..3b9a710a5c 100644 --- a/web/app/components/workflow/block-selector/market-place-plugin/action.tsx +++ b/web/app/components/workflow/block-selector/market-place-plugin/action.tsx @@ -77,7 +77,7 @@ const OperationDropdown: FC = ({ -
+
{t('common.operation.download')}
{t('common.operation.viewDetails')}