'use client' import type { ComponentProps, PropsWithoutRef } from 'react' import type { InstanceDetailTabKey } from './tabs' import type { NavIcon } from '@/app/components/app-sidebar/nav-link' import { cn } from '@langgenius/dify-ui/cn' import { Kbd, KbdGroup } from '@langgenius/dify-ui/kbd' import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip' import { formatForDisplay } from '@tanstack/react-hotkeys' import { useAtomValue } from 'jotai' import { useTranslation } from 'react-i18next' import NavLink from '@/app/components/app-sidebar/nav-link' import ToggleButton from '@/app/components/app-sidebar/toggle-button' import Divider from '@/app/components/base/divider' import SidebarLeftArrowIcon from '@/app/components/base/icons/src/vender/SidebarLeftArrowIcon' import { SkeletonContainer, SkeletonRectangle } from '@/app/components/base/skeleton' import { useSetGotoAnythingOpen } from '@/app/components/goto-anything/atoms' import Link from '@/next/link' import { usePathname } from '@/next/navigation' import { DeploymentActionsMenu } from '../deployment-actions' import { deploymentRouteAppInstanceIdAtom } from '../route-state' import { TitleTooltip } from '../shared/components/title-tooltip' import { deploymentDetailAppInstanceAtom, deploymentDetailAppInstanceIsErrorAtom, deploymentDetailAppInstanceIsLoadingAtom, } from './state' type TabDef = { key: InstanceDetailTabKey icon: NavIcon selectedIcon: NavIcon hidden?: boolean } type TailwindNavIconProps = PropsWithoutRef> & { title?: string titleId?: string } function OverviewIcon({ className }: TailwindNavIconProps) { return } function OverviewSelectedIcon({ className }: TailwindNavIconProps) { return } function DeployIcon({ className }: TailwindNavIconProps) { return } function DeploySelectedIcon({ className }: TailwindNavIconProps) { return } function VersionsIcon({ className }: TailwindNavIconProps) { return } function VersionsSelectedIcon({ className }: TailwindNavIconProps) { return } function AccessIcon({ className }: TailwindNavIconProps) { return } function AccessSelectedIcon({ className }: TailwindNavIconProps) { return } function ApiIcon({ className }: TailwindNavIconProps) { return } function ApiSelectedIcon({ className }: TailwindNavIconProps) { return } const DEPLOYMENT_TABS: TabDef[] = [ { key: 'overview', icon: OverviewIcon, selectedIcon: OverviewSelectedIcon }, { key: 'instances', icon: DeployIcon, selectedIcon: DeploySelectedIcon }, { key: 'releases', icon: VersionsIcon, selectedIcon: VersionsSelectedIcon }, { key: 'access', icon: AccessIcon, selectedIcon: AccessSelectedIcon, hidden: true }, { key: 'api-tokens', icon: ApiIcon, selectedIcon: ApiSelectedIcon }, ] const SEARCH_SHORTCUT = ['Mod', 'K'] function DeploymentIcon({ expand }: { expand: boolean }) { return (
) } function DeploymentDetailInstanceInfo({ appInstanceId, expand }: { appInstanceId: string expand: boolean }) { const { t } = useTranslation('deployments') const overview = useAtomValue(deploymentDetailAppInstanceAtom) const isOverviewLoading = useAtomValue(deploymentDetailAppInstanceIsLoadingAtom) const isOverviewError = useAtomValue(deploymentDetailAppInstanceIsErrorAtom) const app = overview?.appInstance const isLoading = !app && isOverviewLoading const isUnavailable = !app || isOverviewError const instanceName = app ? app.displayName : appInstanceId return (
{isLoading ? ( <> {expand && ( )} ) : isUnavailable ? ( <>
{expand && (
{t('detail.notFound')}
{appInstanceId}
)} ) : ( <> {expand && ( <>
{instanceName}
{app.description && (
{app.description}
)}
)} )}
) } export function DeploymentDetailTop({ expand = true, onToggle, }: { expand?: boolean onToggle?: () => void }) { const { t } = useTranslation() const setGotoAnythingOpen = useSetGotoAnythingOpen() if (!expand) { return (
{onToggle && ( } className="size-8 rounded-[10px] border-0 bg-transparent px-0 text-text-tertiary shadow-none hover:border-0 hover:bg-state-base-hover hover:text-text-secondary" /> )}
) } return (
/ {t('menus.deployments', { ns: 'common' })}
setGotoAnythingOpen(true)} > )} /> {t('gotoAnything.quickAction', { ns: 'app' })} {SEARCH_SHORTCUT.map(key => ( {formatForDisplay(key)} ))} {onToggle && ( } className="size-8 rounded-[10px] border-0 bg-transparent px-0 text-text-tertiary shadow-none hover:border-0 hover:bg-state-base-hover hover:text-text-secondary" /> )}
) } export function DeploymentDetailSection({ expand = true, }: { expand?: boolean }) { const { t } = useTranslation('deployments') const pathname = usePathname() const appInstanceId = useAtomValue(deploymentRouteAppInstanceIdAtom) if (!appInstanceId) return null return (
{!expand && (
)}
) }