import React, { useState } from 'react'; import { motion } from 'framer-motion'; import { X, Database, Server, User, Copy, Check, Zap, Terminal, Loader2 } from 'lucide-react'; import { useToast } from '@/contexts/ToastContext'; import { useUserStore } from '@/store/userStore'; import { api } from '@/services/api'; import { getAuthHeadersSync, getUserIdSync } from '@/utils/userId'; interface Props { source: string; // 'PostgreSQL' | 'Snowflake' | 'Kafka' onClose: () => void; onConnect: (connectionId: string) => void; } // Generate the Python script dynamically based on user inputs and connector type const generateScript = (source: string, pushUrl: string, host: string, dbName: string, tableName: string, username: string, schema: string = 'PUBLIC'): string => { const sourceLower = source.toLowerCase(); if (sourceLower === 'postgresql') { return `import json, psycopg2, requests, time from psycopg2.extras import RealDictCursor # Your unique DataVision Cloud Push URL (do NOT share this) URL = "${pushUrl}" # Connect to your local PostgreSQL database conn = psycopg2.connect( dbname="${dbName}", user="${username}", password="YOUR_PASSWORD", # <-- Enter your password here host="${host}", port="5432" ) conn.autocommit = True cursor = conn.cursor(cursor_factory=RealDictCursor) print("Connected to ${dbName}! Streaming '${tableName}' to DataVision Cloud...") previous_count = 0 while True: try: # First run imports the existing table; later polls send the table again. # DataVision de-duplicates identical records before writing its live CSV. cursor.execute("SELECT * FROM ${tableName};") records = json.loads(json.dumps([dict(row) for row in cursor.fetchall()], default=str)) total_rows = len(records) rows_per_sec = max(0, total_rows - previous_count) if previous_count else 0 previous_count = total_rows res = requests.post(URL, json={ "total_rows": total_rows, "rows_per_sec": rows_per_sec, "data": records, "cpu_usage": 0.0, "error_rate": 0.0, "status": "Streaming ${tableName} to Cloud" }) print(f"Sent: {total_rows} rows -> {res.json()}") except Exception as e: print("Error:", e) time.sleep(5) `; } if (sourceLower === 'snowflake') { return `import json, snowflake.connector, requests, time # Your unique DataVision Cloud Push URL (do NOT share this) URL = "${pushUrl}" # Connect to your Snowflake warehouse conn = snowflake.connector.connect( user="${username}", password="YOUR_PASSWORD", # <-- Enter your password here account="${host}", # e.g. xy12345.us-east-1 warehouse="COMPUTE_WH", database="${dbName}", schema="${schema || 'PUBLIC'}" ) cursor = conn.cursor() print("Connected to Snowflake! Streaming '${tableName}' from schema '${schema || 'PUBLIC'}' to DataVision Cloud...") previous_count = 0 while True: try: cursor.execute("SELECT * FROM ${schema ? `${schema}.${tableName}` : tableName}") columns = [item[0] for item in cursor.description] records = json.loads(json.dumps([dict(zip(columns, row)) for row in cursor.fetchall()], default=str)) total_rows = len(records) rows_per_sec = max(0, total_rows - previous_count) if previous_count else 0 previous_count = total_rows res = requests.post(URL, json={ "total_rows": total_rows, "rows_per_sec": rows_per_sec, "data": records, "cpu_usage": 0.0, "error_rate": 0.0, "status": "Streaming ${tableName} from Snowflake" }) print(f"Sent: {total_rows} rows -> {res.json()}") except Exception as e: print("Error:", e) time.sleep(5) `; } // Kafka return `from confluent_kafka import Consumer import json, requests # Your unique DataVision Cloud Push URL (do NOT share this) URL = "${pushUrl}" c = Consumer({ "bootstrap.servers": "${host}", "group.id": "datavision-push-group", "auto.offset.reset": "latest" }) c.subscribe(["${tableName}"]) # Kafka Topic Name print("Listening to Kafka topic '${tableName}' and streaming to DataVision Cloud...") sent_messages = 0 while True: msg = c.poll(1.0) if msg is None: continue if msg.error(): print("Consumer error:", msg.error()) continue # Send the actual event. DataVision stores it in the live CSV/Data Hub. try: event = json.loads(msg.value().decode("utf-8")) if not isinstance(event, dict): event = {"value": event} except Exception: event = {"value": msg.value().decode("utf-8", errors="replace")} try: res = requests.post(URL, json={ "data": [event], "rows_per_sec": 1, "cpu_usage": 0.0, "error_rate": 0.0, "status": "Receiving Kafka messages" }, timeout=15) res.raise_for_status() sent_messages += 1 # Count only records DataVision accepted. print(f"Pushed message #{sent_messages} -> {res.json()}") except requests.RequestException as exc: print(f"Push failed; event was not counted: {exc}") `; }; export const ConnectionSetupModal: React.FC = ({ source, onClose, onConnect }) => { const { isDark } = useUserStore(); const toast = useToast(); // Step 1: collect details. Step 2: show generated script. Step 3: launch dashboard. const [step, setStep] = useState<1 | 2 | 3>(1); const [isGenerating, setIsGenerating] = useState(false); const [copied, setCopied] = useState(false); // Form fields const [host, setHost] = useState(''); const [databaseName, setDatabaseName] = useState(''); const [targetTable, setTargetTable] = useState(''); const [username, setUsername] = useState(''); const [schema, setSchema] = useState('PUBLIC'); // Generated values const [connectionId, setConnectionId] = useState(''); const [pushUrl, setPushUrl] = useState(''); const sourceIcon = source === 'PostgreSQL' ? '🐘' : source === 'Snowflake' ? '❄️' : '⚡'; const sourceColor = source === 'PostgreSQL' ? 'indigo' : source === 'Snowflake' ? 'blue' : 'yellow'; const placeholders: Record = { PostgreSQL: { host: 'localhost', db: 'streaming_db', table: 'weather_data', user: 'postgres' }, Snowflake: { host: 'xy12345.us-east-1', db: 'PRODUCTION', table: 'SALES_DATA', user: 'admin', schema: 'PUBLIC' }, Kafka: { host: 'localhost:9092', db: '(not needed for Kafka)', table: 'my_topic', user: '(optional)' }, }; const ph = placeholders[source] || placeholders.PostgreSQL; const handleGenerate = async () => { if (!host || !targetTable) { toast.error('Host and Table/Topic are required.'); return; } setIsGenerating(true); try { const response = await fetch('/api/v1/connections', { method: 'POST', headers: { 'Content-Type': 'application/json', ...getAuthHeadersSync() }, body: JSON.stringify({ source_type: `api_push_${source.toLowerCase()}`, host, database_name: databaseName || (source === 'Snowflake' ? 'PRODUCTION' : 'push'), target_table: targetTable, credentials: 'none' }) }); const data = await response.json(); const connId = data.connection_id; setConnectionId(connId); // Persist guest connections in localStorage if (data.is_guest && data.connection) { const stored = JSON.parse(localStorage.getItem('guest_live_connections') || '[]'); stored.unshift({ ...data.connection, source_type: `api_push_${source.toLowerCase()}` }); localStorage.setItem('guest_live_connections', JSON.stringify(stored)); } const url = `${window.location.protocol}//${window.location.host}/api/v1/push/${connId}`; setPushUrl(url); setStep(2); } catch (err: any) { toast.error('Failed to generate connection: ' + (err?.message || 'Unknown error')); } finally { setIsGenerating(false); } }; const handleCopy = () => { const script = generateScript(source, pushUrl, host, databaseName, targetTable, username, schema); navigator.clipboard.writeText(script); setCopied(true); toast.success('Script copied to clipboard!'); setTimeout(() => setCopied(false), 2000); }; const handleLaunchDashboard = () => { setStep(3); setTimeout(() => { onConnect(connectionId); }, 1200); }; const inputClasses = `w-full border rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-${sourceColor}-500/50 focus:border-${sourceColor}-500 transition-all ${isDark ? 'bg-black/40 border-gray-700 text-white placeholder-gray-500' : 'bg-white border-gray-300 text-gray-900 placeholder-gray-400'}`; return (
{/* Header */}
{sourceIcon}

{step === 1 ? `Connect ${source}` : step === 2 ? 'Your Streaming Client' : 'Launching...'}

{step === 1 ? 'Enter your database details below' : step === 2 ? 'Copy this script and run it on your machine' : 'Opening live dashboard...'}

{/* Body */}
{/* ─── STEP 1: Collect Details ─── */} {step === 1 && (
setHost(e.target.value)} placeholder={`e.g. ${ph.host}`} className={inputClasses} />
{source !== 'Kafka' && (
setDatabaseName(e.target.value)} placeholder={`e.g. ${ph.db}`} className={inputClasses} />
)} {source === 'Snowflake' && (
setSchema(e.target.value)} placeholder="e.g. PUBLIC" className={inputClasses} />
)}
setTargetTable(e.target.value)} placeholder={`e.g. ${ph.table}`} className={inputClasses} />
setUsername(e.target.value)} placeholder={`e.g. ${ph.user}`} className={inputClasses} />
How it works: We generate a Python script with your details pre-filled. You run it on your machine — it reads your database locally and securely streams data to DataVision Cloud. Your credentials never leave your machine.
)} {/* ─── STEP 2: Show Generated Script ─── */} {step === 2 && (
Push URL generated successfully!
datavision_{source.toLowerCase()}_push.py
                  {generateScript(source, pushUrl, host, databaseName, targetTable, username)}
                

Step 1: Copy the script above.

Step 2: Replace YOUR_PASSWORD with your actual password.

Step 3: Run python datavision_{source.toLowerCase()}_push.py on your machine.

Step 4: Click the button below to open your Live Dashboard.

)} {/* ─── STEP 3: Launching animation ─── */} {step === 3 && (

Launching Live Dashboard

Waiting for data from your {source} streaming client...

)}
); };