feat: re arranged connectors list

This commit is contained in:
DESKTOP-RTLN3BA\$punk 2026-03-31 20:38:43 -07:00
parent ad0e77c3d6
commit d8f403efba

View file

@ -13,6 +13,24 @@ import {
} from "../constants/connector-constants"; } from "../constants/connector-constants";
import { getDocumentCountForConnector } from "../utils/connector-document-mapping"; import { getDocumentCountForConnector } from "../utils/connector-document-mapping";
type OAuthConnector = (typeof OAUTH_CONNECTORS)[number];
type ComposioConnector = (typeof COMPOSIO_CONNECTORS)[number];
type OtherConnector = (typeof OTHER_CONNECTORS)[number];
type CrawlerConnector = (typeof CRAWLERS)[number];
const DOCUMENT_FILE_CONNECTOR_TYPES = new Set<string>([
EnumConnectorName.GOOGLE_DRIVE_CONNECTOR,
EnumConnectorName.COMPOSIO_GOOGLE_DRIVE_CONNECTOR,
EnumConnectorName.ONEDRIVE_CONNECTOR,
EnumConnectorName.DROPBOX_CONNECTOR,
]);
const OTHER_DOCUMENT_CONNECTOR_TYPES = new Set<string>([
EnumConnectorName.YOUTUBE_CONNECTOR,
EnumConnectorName.NOTION_CONNECTOR,
EnumConnectorName.AIRTABLE_CONNECTOR,
]);
/** /**
* Extract the display name from a full connector name. * Extract the display name from a full connector name.
* Full names are in format "Base Name - identifier" (e.g., "Gmail - john@example.com"). * Full names are in format "Base Name - identifier" (e.g., "Gmail - john@example.com").
@ -34,9 +52,7 @@ interface AllConnectorsTabProps {
allConnectors: SearchSourceConnector[] | undefined; allConnectors: SearchSourceConnector[] | undefined;
documentTypeCounts?: Record<string, number>; documentTypeCounts?: Record<string, number>;
indexingConnectorIds?: Set<number>; indexingConnectorIds?: Set<number>;
onConnectOAuth: ( onConnectOAuth: (connector: OAuthConnector | ComposioConnector) => void;
connector: (typeof OAUTH_CONNECTORS)[number] | (typeof COMPOSIO_CONNECTORS)[number]
) => void;
onConnectNonOAuth?: (connectorType: string) => void; onConnectNonOAuth?: (connectorType: string) => void;
onCreateWebcrawler?: () => void; onCreateWebcrawler?: () => void;
onCreateYouTubeCrawler?: () => void; onCreateYouTubeCrawler?: () => void;
@ -92,22 +108,50 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
c.description.toLowerCase().includes(searchQuery.toLowerCase()) c.description.toLowerCase().includes(searchQuery.toLowerCase())
); );
return ( const nativeGoogleDriveConnectors = filteredOAuth.filter(
<div className="space-y-8"> (c) => c.connectorType === EnumConnectorName.GOOGLE_DRIVE_CONNECTOR
{/* Managed OAuth (Composio Integrations) */} );
{filteredComposio.length > 0 && ( const composioGoogleDriveConnectors = filteredComposio.filter(
<section> (c) => c.connectorType === EnumConnectorName.COMPOSIO_GOOGLE_DRIVE_CONNECTOR
<div className="flex items-center gap-2 mb-4"> );
<h3 className="text-sm font-semibold text-muted-foreground"> const fileStorageConnectors = filteredOAuth.filter(
Managed OAuth (Composio) (c) =>
</h3> c.connectorType === EnumConnectorName.ONEDRIVE_CONNECTOR ||
</div> c.connectorType === EnumConnectorName.DROPBOX_CONNECTOR
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3"> );
{filteredComposio.map((connector) => {
const otherDocumentYouTubeConnectors = filteredCrawlers.filter(
(c) => c.connectorType === EnumConnectorName.YOUTUBE_CONNECTOR
);
const otherDocumentNotionConnectors = filteredOAuth.filter(
(c) => c.connectorType === EnumConnectorName.NOTION_CONNECTOR
);
const otherDocumentAirtableConnectors = filteredOAuth.filter(
(c) => c.connectorType === EnumConnectorName.AIRTABLE_CONNECTOR
);
const moreIntegrationsComposio = filteredComposio.filter(
(c) =>
!DOCUMENT_FILE_CONNECTOR_TYPES.has(c.connectorType) &&
!OTHER_DOCUMENT_CONNECTOR_TYPES.has(c.connectorType)
);
const moreIntegrationsOAuth = filteredOAuth.filter(
(c) =>
!DOCUMENT_FILE_CONNECTOR_TYPES.has(c.connectorType) &&
!OTHER_DOCUMENT_CONNECTOR_TYPES.has(c.connectorType)
);
const moreIntegrationsOther = filteredOther;
const moreIntegrationsCrawlers = filteredCrawlers.filter(
(c) =>
!c.connectorType ||
(!DOCUMENT_FILE_CONNECTOR_TYPES.has(c.connectorType) &&
!OTHER_DOCUMENT_CONNECTOR_TYPES.has(c.connectorType))
);
const renderOAuthCard = (connector: OAuthConnector | ComposioConnector) => {
const isConnected = connectedTypes.has(connector.connectorType); const isConnected = connectedTypes.has(connector.connectorType);
const isConnecting = connectingId === connector.id; const isConnecting = connectingId === connector.id;
// Find all connectors of this type
const typeConnectors = const typeConnectors =
isConnected && allConnectors isConnected && allConnectors
? allConnectors.filter( ? allConnectors.filter(
@ -116,13 +160,10 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
: []; : [];
const accountCount = typeConnectors.length; const accountCount = typeConnectors.length;
const documentCount = getDocumentCountForConnector( const documentCount = getDocumentCountForConnector(
connector.connectorType, connector.connectorType,
documentTypeCounts documentTypeCounts
); );
// Check if any account is currently indexing
const isIndexing = typeConnectors.some((c) => indexingConnectorIds?.has(c.id)); const isIndexing = typeConnectors.some((c) => indexingConnectorIds?.has(c.id));
return ( return (
@ -145,77 +186,12 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
} }
/> />
); );
})} };
</div>
</section>
)}
{/* Quick Connect */} const renderOtherCard = (connector: OtherConnector) => {
{filteredOAuth.length > 0 && (
<section>
<div className="flex items-center gap-2 mb-4">
<h3 className="text-sm font-semibold text-muted-foreground">Quick Connect</h3>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{filteredOAuth.map((connector) => {
const isConnected = connectedTypes.has(connector.connectorType); const isConnected = connectedTypes.has(connector.connectorType);
const isConnecting = connectingId === connector.id; const isConnecting = connectingId === connector.id;
// Find all connectors of this type
const typeConnectors =
isConnected && allConnectors
? allConnectors.filter(
(c: SearchSourceConnector) => c.connector_type === connector.connectorType
)
: [];
const accountCount = typeConnectors.length;
const documentCount = getDocumentCountForConnector(
connector.connectorType,
documentTypeCounts
);
// Check if any account is currently indexing
const isIndexing = typeConnectors.some((c) => indexingConnectorIds?.has(c.id));
return (
<ConnectorCard
key={connector.id}
id={connector.id}
title={connector.title}
description={connector.description}
connectorType={connector.connectorType}
isConnected={isConnected}
isConnecting={isConnecting}
documentCount={documentCount}
accountCount={accountCount}
isIndexing={isIndexing}
onConnect={() => onConnectOAuth(connector)}
onManage={
isConnected && onViewAccountsList
? () => onViewAccountsList(connector.connectorType, connector.title)
: undefined
}
/>
);
})}
</div>
</section>
)}
{/* More Integrations */}
{filteredOther.length > 0 && (
<section>
<div className="flex items-center gap-2 mb-4">
<h3 className="text-sm font-semibold text-muted-foreground">More Integrations</h3>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{filteredOther.map((connector) => {
const isConnected = connectedTypes.has(connector.connectorType);
const isConnecting = connectingId === connector.id;
// Find the actual connector object if connected
const actualConnector = const actualConnector =
isConnected && allConnectors isConnected && allConnectors
? allConnectors.find( ? allConnectors.find(
@ -229,7 +205,6 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
); );
const isIndexing = actualConnector && indexingConnectorIds?.has(actualConnector.id); const isIndexing = actualConnector && indexingConnectorIds?.has(actualConnector.id);
// For MCP connectors, count total MCP connectors instead of document count
const isMCP = connector.connectorType === EnumConnectorName.MCP_CONNECTOR; const isMCP = connector.connectorType === EnumConnectorName.MCP_CONNECTOR;
const mcpConnectorCount = const mcpConnectorCount =
isMCP && allConnectors isMCP && allConnectors
@ -241,7 +216,7 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
const handleConnect = onConnectNonOAuth const handleConnect = onConnectNonOAuth
? () => onConnectNonOAuth(connector.connectorType) ? () => onConnectNonOAuth(connector.connectorType)
: () => {}; // Fallback - connector popup should handle all connector types : () => {};
return ( return (
<ConnectorCard <ConnectorCard
@ -261,29 +236,16 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
} }
/> />
); );
})} };
</div>
</section>
)}
{/* Content Sources */} const renderCrawlerCard = (crawler: CrawlerConnector) => {
{filteredCrawlers.length > 0 && (
<section>
<div className="flex items-center gap-2 mb-4">
<h3 className="text-sm font-semibold text-muted-foreground">Content Sources</h3>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{filteredCrawlers.map((crawler) => {
const isYouTube = crawler.id === "youtube-crawler"; const isYouTube = crawler.id === "youtube-crawler";
const isWebcrawler = crawler.id === "webcrawler-connector"; const isWebcrawler = crawler.id === "webcrawler-connector";
// For crawlers that are actual connectors, check connection status
const isConnected = crawler.connectorType const isConnected = crawler.connectorType
? connectedTypes.has(crawler.connectorType) ? connectedTypes.has(crawler.connectorType)
: false; : false;
const isConnecting = connectingId === crawler.id; const isConnecting = connectingId === crawler.id;
// Find the actual connector object if connected
const actualConnector = const actualConnector =
isConnected && crawler.connectorType && allConnectors isConnected && crawler.connectorType && allConnectors
? allConnectors.find( ? allConnectors.find(
@ -307,7 +269,7 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
onConnectNonOAuth(crawler.connectorType); onConnectNonOAuth(crawler.connectorType);
} }
} }
: () => {}; // Fallback for non-connector crawlers : () => {};
return ( return (
<ConnectorCard <ConnectorCard
@ -326,7 +288,53 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
} }
/> />
); );
})} };
const hasDocumentFileConnectors =
nativeGoogleDriveConnectors.length > 0 ||
composioGoogleDriveConnectors.length > 0 ||
fileStorageConnectors.length > 0;
const hasMoreIntegrations =
otherDocumentYouTubeConnectors.length > 0 ||
otherDocumentNotionConnectors.length > 0 ||
otherDocumentAirtableConnectors.length > 0 ||
moreIntegrationsComposio.length > 0 ||
moreIntegrationsOAuth.length > 0 ||
moreIntegrationsOther.length > 0 ||
moreIntegrationsCrawlers.length > 0;
return (
<div className="space-y-8">
{/* Document/Files Connectors */}
{hasDocumentFileConnectors && (
<section>
<div className="flex items-center gap-2 mb-4">
<h3 className="text-sm font-semibold text-muted-foreground">
Document/Files Connectors
</h3>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{nativeGoogleDriveConnectors.map(renderOAuthCard)}
{composioGoogleDriveConnectors.map(renderOAuthCard)}
{fileStorageConnectors.map(renderOAuthCard)}
</div>
</section>
)}
{/* More Integrations */}
{hasMoreIntegrations && (
<section>
<div className="flex items-center gap-2 mb-4">
<h3 className="text-sm font-semibold text-muted-foreground">More Integrations</h3>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{otherDocumentYouTubeConnectors.map(renderCrawlerCard)}
{otherDocumentNotionConnectors.map(renderOAuthCard)}
{otherDocumentAirtableConnectors.map(renderOAuthCard)}
{moreIntegrationsComposio.map(renderOAuthCard)}
{moreIntegrationsOAuth.map(renderOAuthCard)}
{moreIntegrationsOther.map(renderOtherCard)}
{moreIntegrationsCrawlers.map(renderCrawlerCard)}
</div> </div>
</section> </section>
)} )}