'use client' import type { CSSProperties, ReactNode } from 'react' import type { IntegrationSection } from '@/app/components/integrations/routes' import type { DocPathWithoutLang } from '@/types/doc-paths' import { cn } from '@langgenius/dify-ui/cn' import { ScrollArea } from '@langgenius/dify-ui/scroll-area' import { useState } from 'react' import { useTranslation } from 'react-i18next' import UpdateSettingDialog from '@/app/components/header/account-setting/update-setting-dialog' import { buildIntegrationPath, buildMarketplaceUrlPathByIntegrationSection, toolCategoryBySection, } from '@/app/components/integrations/routes' import { useDocLink } from '@/context/i18n' import Link from '@/next/link' import { useRouter } from '@/next/navigation' import { getMarketplaceUrl } from '@/utils/var' import { getPluginCategoryBySection, useIntegrationNav } from './hooks/use-integration-nav' import { useIntegrationPermissions } from './hooks/use-integration-permissions' import { useIntegrationSection } from './hooks/use-integration-section' import IntegrationSectionRenderer from './section-renderer' import { IntegrationSidebarActions, IntegrationSidebarUtilityActions } from './sidebar-actions' import { IntegrationSidebarNavItem, } from './sidebar-nav-item' import { integrationSidebarInactiveNavItemClassName, integrationSidebarNavItemClassName, } from './sidebar-nav-item-styles' type IntegrationsPageProps = { onSectionChange?: (section: IntegrationSection) => void onSwitchToMarketplace?: (path: string) => void section?: IntegrationSection } const headerDescriptionDocPaths: Partial> = { 'provider': '/use-dify/workspace/model-providers', 'data-source': '/develop-plugin/dev-guides-and-walkthroughs/datasource-plugin#data-source-plugin-types', 'builtin': '/use-dify/workspace/tools', 'custom-tool': '/use-dify/workspace/tools#custom-tool', 'workflow-tool': '/use-dify/workspace/tools#workflow-tool', 'mcp': '/use-dify/build/mcp', 'custom-endpoint': '/use-dify/workspace/api-extension/api-extension', 'trigger': '/develop-plugin/dev-guides-and-walkthroughs/trigger-plugin', 'extension': '/develop-plugin/dev-guides-and-walkthroughs/endpoint', 'agent-strategy': '/develop-plugin/dev-guides-and-walkthroughs/agent-strategy-plugin', } type DescriptionWithLearnMoreProps = { children: ReactNode href: string label: string } const DescriptionWithLearnMore = ({ children, href, label, }: DescriptionWithLearnMoreProps) => { const title = typeof children === 'string' ? children : undefined return ( {children} {label} ) } function ToolsDisclosureIcon({ className }: { className?: string }) { return ( ) } export default function IntegrationsPage({ onSectionChange, onSwitchToMarketplace, section: routeSection, }: IntegrationsPageProps) { const { t } = useTranslation() const docLink = useDocLink() const router = useRouter() const section = useIntegrationSection(routeSection) const { canManagement, canDebugger, handlePermissionChange, isPluginCategory, permission, showPermissionQuickPanel, showPluginCategorySetting, } = useIntegrationPermissions(section) const [providerSearchText, setProviderSearchText] = useState('') const showInstallAction = canManagement const showUtilityActions = canDebugger || showPermissionQuickPanel const { activeItem, customEndpointItem, dataSourceItem, integrationHeader, providerItem, secondaryItems, toolItems, } = useIntegrationNav(section) const isToolSection = Boolean(toolCategoryBySection[section]) const [isToolsExpanded, setIsToolsExpanded] = useState(isToolSection) const useFillLayout = section === 'provider' || section === 'data-source' || section === 'custom-endpoint' || isToolSection || isPluginCategory const scrollAreaLabel = integrationHeader?.title ?? activeItem?.label const sidebarWidthStyle = { '--integrations-sidebar-width': '200px', '--model-provider-warning-left': 'calc(240px + 200px)', } as CSSProperties & Record<'--integrations-sidebar-width' | '--model-provider-warning-left', string> const pluginSettingCategory = getPluginCategoryBySection(section) const pluginSettingAction = showPluginCategorySetting && pluginSettingCategory ? ( ) : undefined const marketplaceUrlPath = buildMarketplaceUrlPathByIntegrationSection(section) const headerDescription = integrationHeader?.description ?? (section === 'provider' ? t('modelProvider.pageDesc', { ns: 'common' }) : undefined) const headerDescriptionDocPath = headerDescriptionDocPaths[section] const headerDescriptionWithLink = headerDescription && headerDescriptionDocPath ? ( {headerDescription} ) : headerDescription const handleSwitchToMarketplace = () => { if (onSwitchToMarketplace) { onSwitchToMarketplace(marketplaceUrlPath) return } window.open(getMarketplaceUrl(marketplaceUrlPath), '_blank', 'noopener,noreferrer') } const handleSelectSection = (nextSection: IntegrationSection) => { if (onSectionChange) { onSectionChange(nextSection) return } router.push(buildIntegrationPath(nextSection)) } const handleToggleTools = () => { const willExpand = !isToolsExpanded setIsToolsExpanded(willExpand) if (willExpand && section !== 'builtin') handleSelectSection('builtin') } const toolsNavItemClassName = cn( integrationSidebarNavItemClassName, integrationSidebarInactiveNavItemClassName, 'group', ) const toolsNavItemContent = ( <> {isToolsExpanded ? : } {t('menus.tools', { ns: 'common' })} ) return (
{useFillLayout ? (
) : ( )}
) }