import { Boxes, ChevronLeft, ChevronRight, EllipsisVertical, ExternalLink, FileText, Gauge, Lock, Plus, Power, Square, Trash2 } from 'lucide-react'; import type { RefObject } from 'react'; import { ProtectedSearchInput } from '../../../components/ProtectedSearchInput'; import { LucentIconButton } from '../../../components/lucent/LucentIconButton'; import type { CompactPanelTab } from '../types'; import './DashboardMenus.css'; import './BotListPanel.css'; interface BotListLabels { batchStart: string; batchStop: string; botSearchNoResult: string; botSearchPlaceholder: string; clearSearch: string; delete: string; disable: string; disabled: string; enable: string; extensions: string; image: string; manageImages: string; newBot: string; paginationNext: string; paginationPage: (page: number, totalPages: number) => string; paginationPrev: string; searchAction: string; start: string; stop: string; syncingPageSize: string; templateManager: string; titleBots: string; } interface BotListPanelProps { bots: any[]; filteredBots: any[]; pagedBots: any[]; selectedBotId: string; normalizedBotListQuery: string; botListQuery: string; botListPageSizeReady: boolean; botListPage: number; botListTotalPages: number; botListMenuOpen: boolean; controlStateByBot: Record; operatingBotId: string | null; compactMode: boolean; isZh: boolean; isLoadingTemplates: boolean; isBatchOperating: boolean; labels: BotListLabels; botSearchInputName: string; botListMenuRef: RefObject; onOpenCreateWizard?: () => void; onOpenImageFactory?: () => void; onToggleMenu?: () => void; onCloseMenu: () => void; onOpenTemplateManager: () => Promise | void; onBatchStartBots: () => Promise | void; onBatchStopBots: () => Promise | void; onBotListQueryChange: (value: string) => void; onBotListPageChange: (value: number | ((prev: number) => number)) => void; onSelectBot: (botId: string) => void; onSetCompactPanelTab: (tab: CompactPanelTab) => void; onSetBotEnabled: (botId: string, enabled: boolean) => Promise | void; onStartBot: (botId: string, dockerStatus: string) => Promise | void; onStopBot: (botId: string, dockerStatus: string) => Promise | void; onOpenResourceMonitor: (botId: string) => void; onRemoveBot: (botId: string) => Promise | void; } export function BotListPanel({ bots, filteredBots, pagedBots, selectedBotId, normalizedBotListQuery, botListQuery, botListPageSizeReady, botListPage, botListTotalPages, botListMenuOpen, controlStateByBot, operatingBotId, compactMode, isZh, isLoadingTemplates, isBatchOperating, labels, botSearchInputName, botListMenuRef, onOpenCreateWizard, onOpenImageFactory, onToggleMenu, onCloseMenu, onOpenTemplateManager, onBatchStartBots, onBatchStopBots, onBotListQueryChange, onBotListPageChange, onSelectBot, onSetCompactPanelTab, onSetBotEnabled, onStartBot, onStopBot, onOpenResourceMonitor, onRemoveBot, }: BotListPanelProps) { return (

{normalizedBotListQuery ? `${labels.titleBots} (${filteredBots.length}/${bots.length})` : `${labels.titleBots} (${bots.length})`}

{botListMenuOpen ? (
) : null}
{ onBotListQueryChange(''); onBotListPageChange(1); }} onSearchAction={() => onBotListPageChange(1)} debounceMs={120} placeholder={labels.botSearchPlaceholder} ariaLabel={labels.botSearchPlaceholder} clearTitle={labels.clearSearch} searchTitle={labels.searchAction} name={botSearchInputName} id={botSearchInputName} />
{!botListPageSizeReady ? (
{labels.syncingPageSize}
) : null} {botListPageSizeReady ? pagedBots.map((bot) => { const selected = selectedBotId === bot.id; const controlState = controlStateByBot[bot.id]; const isOperating = operatingBotId === bot.id; const isEnabled = bot.enabled !== false; const isEnabling = controlState === 'enabling'; const isDisabling = controlState === 'disabling'; const isRunning = String(bot.docker_status || '').toUpperCase() === 'RUNNING'; const showActionPending = isOperating && !isEnabling && !isDisabling; return (
{ onSelectBot(bot.id); if (compactMode) onSetCompactPanelTab('chat'); }} >
); }) : null} {botListPageSizeReady && filteredBots.length === 0 ? (
{labels.botSearchNoResult}
) : null}
{botListPageSizeReady ? (
onBotListPageChange((p) => Math.max(1, p - 1))} disabled={botListPage <= 1} tooltip={labels.paginationPrev} aria-label={labels.paginationPrev} >
{labels.paginationPage(botListPage, botListTotalPages)}
onBotListPageChange((p) => Math.min(botListTotalPages, p + 1))} disabled={botListPage >= botListTotalPages} tooltip={labels.paginationNext} aria-label={labels.paginationNext} >
) : null}
); }