"use client" import { useState, useEffect, useCallback } from "react" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { GoogleDrivePicker } from "@/components/google-drive-picker" import { OneDrivePicker } from "@/components/onedrive-picker" import { Loader2 } from "lucide-react" interface GoogleDriveFile { id: string name: string mimeType: string webViewLink?: string iconLink?: string } interface OneDriveFile { id: string name: string mimeType?: string webUrl?: string driveItem?: { file?: { mimeType: string } folder?: unknown } } interface CloudConnector { id: string name: string description: string icon: React.ReactNode status: "not_connected" | "connecting" | "connected" | "error" type: string connectionId?: string hasAccessToken: boolean accessTokenError?: string } interface CloudConnectorsDialogProps { isOpen: boolean onOpenChange: (open: boolean) => void onFileSelected?: (files: GoogleDriveFile[] | OneDriveFile[], connectorType: string) => void } export function CloudConnectorsDialog({ isOpen, onOpenChange, onFileSelected }: CloudConnectorsDialogProps) { const [connectors, setConnectors] = useState([]) const [isLoading, setIsLoading] = useState(true) const [selectedFiles, setSelectedFiles] = useState<{[connectorId: string]: GoogleDriveFile[] | OneDriveFile[]}>({}) const [connectorAccessTokens, setConnectorAccessTokens] = useState<{[connectorType: string]: string}>({}) const [activePickerType, setActivePickerType] = useState(null) const getConnectorIcon = (iconName: string) => { const iconMap: { [key: string]: React.ReactElement } = { 'google-drive': (
G
), 'sharepoint': (
SP
), 'onedrive': (
OD
), } return iconMap[iconName] || (
?
) } const fetchConnectorStatuses = useCallback(async () => { if (!isOpen) return setIsLoading(true) try { // Fetch available connectors from backend const connectorsResponse = await fetch('/api/connectors') if (!connectorsResponse.ok) { throw new Error('Failed to load connectors') } const connectorsResult = await connectorsResponse.json() const connectorTypes = Object.keys(connectorsResult.connectors) // Filter to only cloud connectors const cloudConnectorTypes = connectorTypes.filter(type => ['google_drive', 'onedrive', 'sharepoint'].includes(type) && connectorsResult.connectors[type].available ) // Initialize connectors list const initialConnectors = cloudConnectorTypes.map(type => ({ id: type, name: connectorsResult.connectors[type].name, description: connectorsResult.connectors[type].description, icon: getConnectorIcon(connectorsResult.connectors[type].icon), status: "not_connected" as const, type: type, hasAccessToken: false, accessTokenError: undefined })) setConnectors(initialConnectors) // Check status for each cloud connector type for (const connectorType of cloudConnectorTypes) { try { const response = await fetch(`/api/connectors/${connectorType}/status`) if (response.ok) { const data = await response.json() const connections = data.connections || [] const activeConnection = connections.find((conn: { connection_id: string; is_active: boolean }) => conn.is_active) const isConnected = activeConnection !== undefined let hasAccessToken = false let accessTokenError: string | undefined = undefined // Try to get access token for connected connectors if (isConnected && activeConnection) { try { const tokenResponse = await fetch(`/api/connectors/${connectorType}/token?connection_id=${activeConnection.connection_id}`) if (tokenResponse.ok) { const tokenData = await tokenResponse.json() if (tokenData.access_token) { hasAccessToken = true setConnectorAccessTokens(prev => ({ ...prev, [connectorType]: tokenData.access_token })) } } else { const errorData = await tokenResponse.json().catch(() => ({ error: 'Token unavailable' })) accessTokenError = errorData.error || 'Access token unavailable' } } catch { accessTokenError = 'Failed to fetch access token' } } setConnectors(prev => prev.map(c => c.type === connectorType ? { ...c, status: isConnected ? "connected" : "not_connected", connectionId: activeConnection?.connection_id, hasAccessToken, accessTokenError } : c )) } } catch (error) { console.error(`Failed to check status for ${connectorType}:`, error) } } } catch (error) { console.error('Failed to load cloud connectors:', error) } finally { setIsLoading(false) } }, [isOpen]) const handleFileSelection = (connectorId: string, files: GoogleDriveFile[] | OneDriveFile[]) => { setSelectedFiles(prev => ({ ...prev, [connectorId]: files })) onFileSelected?.(files, connectorId) } useEffect(() => { fetchConnectorStatuses() }, [fetchConnectorStatuses]) return ( Cloud File Connectors Select files from your connected cloud storage providers
{isLoading ? (
Loading connectors...
) : connectors.length === 0 ? (
No cloud connectors available. Configure them in Settings first.
) : (
{/* Service Buttons Row */}
{connectors .filter(connector => connector.status === "connected") .map((connector) => ( ))}
{connectors.every(c => c.status !== "connected") && (

No connected cloud providers found.

Go to Settings to connect your cloud storage accounts.

)} {/* Render pickers inside dialog */} {activePickerType && connectors.find(c => c.id === activePickerType) && (() => { const connector = connectors.find(c => c.id === activePickerType)! if (connector.type === "google_drive") { return (
{ handleFileSelection(connector.id, files) setActivePickerType(null) }} selectedFiles={selectedFiles[connector.id] as GoogleDriveFile[] || []} isAuthenticated={connector.status === "connected"} accessToken={connectorAccessTokens[connector.type]} onPickerStateChange={() => {}} />
) } if (connector.type === "onedrive" || connector.type === "sharepoint") { return (
{ handleFileSelection(connector.id, files) setActivePickerType(null) }} selectedFiles={selectedFiles[connector.id] as OneDriveFile[] || []} isAuthenticated={connector.status === "connected"} accessToken={connectorAccessTokens[connector.type]} connectorType={connector.type as "onedrive" | "sharepoint"} />
) } return null })()}
)}
) }