diff --git a/surfsense_web/components/assistant-ui/connector-popup/connectors-panel.tsx b/surfsense_web/components/assistant-ui/connector-popup/connectors-panel.tsx index 4e0e8b4b1..1745e15ed 100644 --- a/surfsense_web/components/assistant-ui/connector-popup/connectors-panel.tsx +++ b/surfsense_web/components/assistant-ui/connector-popup/connectors-panel.tsx @@ -13,6 +13,7 @@ import { DrawerTitle, DrawerTrigger, } from "@/components/ui/drawer"; +import { Input } from "@/components/ui/input"; import { Separator } from "@/components/ui/separator"; import { Spinner } from "@/components/ui/spinner"; import { EnumConnectorName } from "@/contracts/enums/connector"; @@ -25,7 +26,13 @@ import { cn } from "@/lib/utils"; import { ConnectorConnectView } from "./connector-configs/views/connector-connect-view"; import { ConnectorEditView } from "./connector-configs/views/connector-edit-view"; import { IndexingConfigurationView } from "./connector-configs/views/indexing-configuration-view"; -import { COMPOSIO_CONNECTORS, getConnectorTitle, OAUTH_CONNECTORS } from "./constants/connector-constants"; +import { + COMPOSIO_CONNECTORS, + type ConnectorTypeRow, + getConnectorTitle, + groupConnectorsByType, + OAUTH_CONNECTORS, +} from "./constants/connector-constants"; import { useConnectorDialog } from "./hooks/use-connector-dialog"; import { useIndexingConnectors } from "./hooks/use-indexing-connectors"; import { AllConnectorsTab } from "./tabs/all-connectors-tab"; @@ -35,11 +42,7 @@ import { YouTubeCrawlerView } from "./views/youtube-crawler-view"; /** Health of a connected connector type, derived from indexing + inbox state. */ type ConnectorHealth = "syncing" | "failed" | "ok"; -interface ConnectedRow { - type: string; - title: string; - connectors: SearchSourceConnector[]; - accountCount: number; +interface ConnectedRow extends ConnectorTypeRow { health: ConnectorHealth; errorMessage?: string; } @@ -171,32 +174,20 @@ export function ConnectorsSection() { // Flat "Your connectors" rows: one per connected type, alphabetized, with a // derived health (syncing > failed > ok) and account count. const connectedRows = useMemo(() => { - const byType = new Map(); - for (const c of connectors) { - const arr = byType.get(c.connector_type) ?? []; - arr.push(c); - byType.set(c.connector_type, arr); - } - return [...byType.entries()] - .map(([type, list]) => { - const ids = list.map((c) => c.id); - const syncing = ids.some( - (id) => indexingConnectorIds.has(id) || statusByConnectorId.get(id)?.status === "in_progress" - ); - const failedEntry = syncing - ? undefined - : ids.map((id) => statusByConnectorId.get(id)).find((s) => s?.status === "failed"); - return { - type, - title: - type === EnumConnectorName.MCP_CONNECTOR ? "MCP Servers" : getConnectorTitle(type), - connectors: list, - accountCount: list.length, - health: syncing ? "syncing" : failedEntry ? "failed" : "ok", - errorMessage: failedEntry?.error, - } satisfies ConnectedRow; - }) - .sort((a, b) => a.title.localeCompare(b.title)); + return groupConnectorsByType(connectors).map((row) => { + const ids = row.connectors.map((c) => c.id); + const syncing = ids.some( + (id) => indexingConnectorIds.has(id) || statusByConnectorId.get(id)?.status === "in_progress" + ); + const failedEntry = syncing + ? undefined + : ids.map((id) => statusByConnectorId.get(id)).find((s) => s?.status === "failed"); + return { + ...row, + health: syncing ? "syncing" : failedEntry ? "failed" : "ok", + errorMessage: failedEntry?.error, + } satisfies ConnectedRow; + }); }, [connectors, indexingConnectorIds, statusByConnectorId]); if (!workspaceId) return null; @@ -461,17 +452,14 @@ export function ConnectorsSection() { const catalog = (
-
+
- - + setSearchQuery(e.target.value)} /> @@ -481,10 +469,10 @@ export function ConnectorsSection() { size="icon" type="button" onClick={() => setSearchQuery("")} - className="absolute right-1.5 top-1/2 size-7 -translate-y-1/2 text-muted-foreground transition-colors hover:bg-transparent hover:text-accent-foreground" + className="absolute right-2 top-1/2 h-7 w-7 -translate-y-1/2 rounded-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground" aria-label="Clear search" > - + )}