diff --git a/web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx b/web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx index 380d10e5..09a76cf1 100644 --- a/web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx +++ b/web/default/src/features/channels/components/drawers/channel-mutate-drawer.tsx @@ -29,8 +29,14 @@ import { zodResolver } from '@hookform/resolvers/zod' import { useQuery, useQueryClient } from '@tanstack/react-query' import { ArrowRight, + AlertCircle, + Boxes, + CheckCircle2, + Circle, HelpCircle, + KeyRound, Loader2, + Server, Sparkles, Trash2, Copy, @@ -47,15 +53,17 @@ import { } from 'lucide-react' import { useTranslation } from 'react-i18next' import { toast } from 'sonner' + import { - ADMIN_PERMISSION_ACTIONS, - ADMIN_PERMISSION_RESOURCES, - hasPermission, -} from '@/lib/admin-permissions' -import { getLobeIcon } from '@/lib/lobe-icon' -import { ROLE } from '@/lib/roles' -import { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard' -import { useHiddenClickUnlock } from '@/hooks/use-hidden-click-unlock' + sideDrawerContentClassName, + sideDrawerFooterClassName, + sideDrawerFormClassName, + sideDrawerHeaderClassName, + sideDrawerSectionClassName, + sideDrawerSwitchItemClassName, +} from '@/components/drawer-layout' +import { JsonEditor } from '@/components/json-editor' +import { MultiSelect } from '@/components/multi-select' import { Alert, AlertDescription } from '@/components/ui/alert' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' @@ -96,21 +104,22 @@ import { TooltipContent, TooltipTrigger, } from '@/components/ui/tooltip' -import { - sideDrawerContentClassName, - sideDrawerFooterClassName, - sideDrawerFormClassName, - sideDrawerHeaderClassName, - sideDrawerSectionClassName, - sideDrawerSwitchItemClassName, -} from '@/components/drawer-layout' -import { JsonEditor } from '@/components/json-editor' -import { MultiSelect } from '@/components/multi-select' import { SecureVerificationDialog, useSecureVerification, } from '@/features/auth/secure-verification' +import { useCopyToClipboard } from '@/hooks/use-copy-to-clipboard' +import { useHiddenClickUnlock } from '@/hooks/use-hidden-click-unlock' +import { + ADMIN_PERMISSION_ACTIONS, + ADMIN_PERMISSION_RESOURCES, + hasPermission, +} from '@/lib/admin-permissions' +import { getLobeIcon } from '@/lib/lobe-icon' +import { ROLE } from '@/lib/roles' +import { cn } from '@/lib/utils' import { useAuthStore } from '@/stores/auth-store' + import { fetchModels, getAllModels, @@ -122,6 +131,7 @@ import { } from '../../api' import { ADD_MODE_OPTIONS, + CHANNEL_STATUS_LABELS, CHANNEL_TYPE_OPTIONS, CHANNEL_TYPE_WARNINGS, ERROR_MESSAGES, @@ -187,6 +197,17 @@ type ModelMappingGuardrail = { exposedTargetModels: string[] } +type ChannelEditorSectionStatus = 'complete' | 'configured' | 'error' | 'idle' + +type ChannelEditorNavItem = { + id: string + title: string + description?: string + statusLabel: string + status: ChannelEditorSectionStatus + icon: ReactNode +} + // Helper functions const createEmptyModelMappingGuardrail = (): ModelMappingGuardrail => ({ invalidJson: false, @@ -313,6 +334,150 @@ function SubHeading({ title, icon }: { title: string; icon?: ReactNode }) { ) } +function ChannelTypeLogo(props: { + type: number + size?: number + className?: string +}) { + const isKnownType = CHANNEL_TYPE_OPTIONS.some( + (option) => option.value === props.type + ) + + if (!isKnownType) { + return ( +