'use client' import { useCallback, useEffect, useMemo, useRef, useState, } from 'react' import type { RefObject, } from 'react' import { useTranslation } from 'react-i18next' import type { BlockEnum, OnSelectBlock } from '../types' import type { TriggerDefaultValue, TriggerWithProvider } from './types' import StartBlocks from './start-blocks' import TriggerPluginList from './trigger-plugin/list' import { ENTRY_NODE_TYPES } from './constants' import cn from '@/utils/classnames' import Link from 'next/link' import { RiArrowRightUpLine } from '@remixicon/react' import { getMarketplaceUrl } from '@/utils/var' import Button from '@/app/components/base/button' import { SearchMenu } from '@/app/components/base/icons/src/vender/line/general' import { BlockEnum as BlockEnumValue } from '../types' import FeaturedTriggers from './featured-triggers' import Divider from '@/app/components/base/divider' import { useGlobalPublicStore } from '@/context/global-public-context' import { useAllTriggerPlugins, useInvalidateAllTriggerPlugins } from '@/service/use-triggers' import { useFeaturedTriggersRecommendations } from '@/service/use-plugins' import { PluginCategoryEnum } from '../../plugins/types' import { useMarketplacePlugins } from '../../plugins/marketplace/hooks' import PluginList, { type ListRef } from './market-place-plugin/list' const marketplaceFooterClassName = 'system-sm-medium z-10 flex h-8 flex-none cursor-pointer items-center rounded-b-lg border-[0.5px] border-t border-components-panel-border bg-components-panel-bg-blur px-4 py-1 text-text-accent-light-mode-only shadow-lg' type AllStartBlocksProps = { className?: string searchText: string onSelect: (type: BlockEnum, trigger?: TriggerDefaultValue) => void availableBlocksTypes?: BlockEnum[] tags?: string[] allowUserInputSelection?: boolean // Allow user input option even when trigger node already exists (e.g. when no Start node yet or changing node type). } const AllStartBlocks = ({ className, searchText, onSelect, availableBlocksTypes, tags = [], allowUserInputSelection = false, }: AllStartBlocksProps) => { const { t } = useTranslation() const [hasStartBlocksContent, setHasStartBlocksContent] = useState(false) const [hasPluginContent, setHasPluginContent] = useState(false) const { enable_marketplace } = useGlobalPublicStore(s => s.systemFeatures) const pluginRef = useRef(null) const wrapElemRef = useRef(null) const entryNodeTypes = availableBlocksTypes?.length ? availableBlocksTypes : ENTRY_NODE_TYPES const enableTriggerPlugin = entryNodeTypes.includes(BlockEnumValue.TriggerPlugin) const { data: triggerProviders = [] } = useAllTriggerPlugins(enableTriggerPlugin) const providerMap = useMemo(() => { const map = new Map() triggerProviders.forEach((provider) => { const keys = [ provider.plugin_id, provider.plugin_unique_identifier, provider.id, ].filter(Boolean) as string[] keys.forEach((key) => { if (!map.has(key)) map.set(key, provider) }) }) return map }, [triggerProviders]) const invalidateTriggers = useInvalidateAllTriggerPlugins() const trimmedSearchText = searchText.trim() const hasSearchText = trimmedSearchText.length > 0 const hasFilter = hasSearchText || tags.length > 0 const { plugins: featuredPlugins = [], isLoading: featuredLoading, } = useFeaturedTriggersRecommendations(enableTriggerPlugin && enable_marketplace && !hasFilter) const { queryPluginsWithDebounced: fetchPlugins, plugins: marketplacePlugins = [], } = useMarketplacePlugins() const shouldShowFeatured = enableTriggerPlugin && enable_marketplace && !hasFilter const shouldShowTriggerListTitle = hasStartBlocksContent || hasPluginContent const shouldShowMarketplaceFooter = enable_marketplace && !hasFilter const handleStartBlocksContentChange = useCallback((hasContent: boolean) => { setHasStartBlocksContent(hasContent) }, []) const handlePluginContentChange = useCallback((hasContent: boolean) => { setHasPluginContent(hasContent) }, []) const hasMarketplaceContent = enableTriggerPlugin && enable_marketplace && marketplacePlugins.length > 0 const hasAnyContent = hasStartBlocksContent || hasPluginContent || shouldShowFeatured || hasMarketplaceContent const shouldShowEmptyState = hasFilter && !hasAnyContent useEffect(() => { if (!enableTriggerPlugin && hasPluginContent) setHasPluginContent(false) }, [enableTriggerPlugin, hasPluginContent]) useEffect(() => { if (!enableTriggerPlugin || !enable_marketplace) return if (hasFilter) { fetchPlugins({ query: searchText, tags, category: PluginCategoryEnum.trigger, }) } }, [enableTriggerPlugin, enable_marketplace, hasFilter, fetchPlugins, searchText, tags]) return (
pluginRef.current?.handleScroll()} >
{shouldShowFeatured && ( <> { invalidateTriggers() }} />
)} {shouldShowTriggerListTitle && (
{t('workflow.tabs.allTriggers')}
)} {enableTriggerPlugin && ( )} {enableTriggerPlugin && enable_marketplace && ( } list={marketplacePlugins} searchText={trimmedSearchText} tags={tags} hideFindMoreFooter /> )}
{shouldShowEmptyState && (
{t('workflow.tabs.noPluginsFound')}
)}
{shouldShowMarketplaceFooter && !shouldShowEmptyState && ( // Footer - Same as Tools tab marketplace footer {t('plugin.findMoreInMarketplace')} )}
) } export default AllStartBlocks