import { useState, useEffect } from "react"; import { api } from "@/lib/api"; import { DataSourceForm, type DataSourceConfig } from "@/components/DataSourceForm"; import { Button } from "@/components/ui/button"; import { Plus, Database, Pencil, Trash2, Loader2, FolderOpen, Info, ChevronLeft, FileText, Search, Network } from "lucide-react"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { useAuthStore } from "@/store/authStore"; import { useProjectStore } from "@/store/projectStore"; import { useNavigate } from "react-router-dom"; const SOURCE_TYPES = [ { id: "csv", name: "CSV Upload", icon: }, { id: "bigquery", name: "BigQuery", icon: }, { id: "postgres", name: "PostgreSQL", icon: }, { id: "supabase", name: "Supabase", icon: }, { id: "mysql", name: "MySQL", icon: }, { id: "oracle", name: "Oracle", icon: }, { id: "sqlserver", name: "SQL Server", icon: }, { id: "clickhouse", name: "ClickHouse", icon: }, { id: "trino", name: "Trino", icon: }, { id: "snowflake", name: "Snowflake", icon: }, { id: "athena-trino", name: "Athena (Trino)", icon: }, { id: "redshift", name: "Redshift", icon: }, { id: "databricks", name: "Databricks", icon: }, { id: "emr-spark", name: "EMR (Spark)", icon: }, { id: "athena-spark", name: "Athena (Spark)", icon: }, { id: "spark", name: "Spark", icon: }, { id: "sqlite", name: "SQLite", icon: }, { id: "parquet", name: "Parquet", icon: }, ]; export function DataSources() { const [datasources, setDatasources] = useState([]); const [isLoading, setIsLoading] = useState(false); const [view, setView] = useState<"list" | "select-type">("list"); const [isOpen, setIsOpen] = useState(false); const [editingDs, setEditingDs] = useState(null); const [selectedType, setSelectedType] = useState(null); const { user } = useAuthStore(); const { currentProject } = useProjectStore(); const navigate = useNavigate(); useEffect(() => { if (currentProject) { fetchDataSources(); } }, [currentProject]); const fetchDataSources = async () => { if (!currentProject) return; setIsLoading(true); try { const data = await api.get(`/api/v1/datasources?project_id=${currentProject.id}`); setDatasources(data); } catch (e) { console.error("Failed to fetch data sources", e); } finally { setIsLoading(false); } } const handleCreate = () => { setEditingDs(null); setSelectedType(null); setView("select-type"); }; const handleSelectType = (typeId: string) => { setSelectedType(typeId); setIsOpen(true); }; const handleEdit = (ds: DataSourceConfig) => { setEditingDs(ds); setSelectedType(ds.type); setIsOpen(true); }; const handleDelete = async (id: number) => { if (!window.confirm("确定要删除这个数据源吗?")) return; try { await api.delete(`/api/v1/datasources/${id}`); fetchDataSources(); } catch (e) { console.error("Failed to delete data source", e); } }; const handleSubmit = async (data: Omit) => { if (!currentProject) return; try { if (editingDs?.id) { await api.put(`/api/v1/datasources/${editingDs.id}`, { ...data, project_id: currentProject.id }); } else { await api.post("/api/v1/datasources", { ...data, project_id: currentProject.id }); } setIsOpen(false); fetchDataSources(); } catch (e) { console.error("Failed to save data source", e); alert("保存失败: " + (e as any).message); } }; const handleTest = async (type: string, config: Record) => { try { const res = await api.post<{ success: boolean; message: string }>("/api/v1/datasources/test", { type, config }); return res.success; } catch (e) { console.error("Test connection failed", e); throw e; } }; if (view === "select-type") { return ( setView("list")} className="flex items-center text-zinc-500 hover:text-zinc-800 transition-colors mb-6 group" > 返回列表 Connect an external data source dbt integration is available for PostgreSQL, MySQL, BigQuery, Redshift, and Snowflake (For Essential Plan and above). Contact Us to suggest new data sources. {SOURCE_TYPES.map((type) => ( handleSelectType(type.id)} className="flex items-center gap-4 bg-white p-4 rounded-lg border border-zinc-200 hover:border-blue-500 hover:shadow-sm transition-all text-left group" > {type.icon} {type.name} ))} { setIsOpen(open); if (!open && !editingDs) setSelectedType(null); }}> {editingDs ? "编辑数据源" : `新建 ${SOURCE_TYPES.find(t => t.id === selectedType)?.name || ""} 数据源`} setIsOpen(false)} /> ); } return ( 数据源配置 管理可用于问答的数据源连接 新建数据源 {isLoading ? ( ) : datasources.length === 0 ? ( 暂无数据源 点击右上角按钮添加第一个数据源 ) : ( {datasources.map((ds) => ( {ds.name} {ds.type} navigate(`/modeling/${ds.id}`)} title="Data Modeling"> handleEdit(ds)}> handleDelete(ds.id!)}> Host {ds.config.host || "Local / File"} Database {ds.config.database || ds.config.file_path ? (ds.config.file_path?.split('/').pop()) : "-"} ))} )} { setIsOpen(open); if (!open && !editingDs) setSelectedType(null); }}> {editingDs ? `编辑 ${SOURCE_TYPES.find(t => t.id === editingDs.type)?.name || editingDs.type} 数据源` : `新建 ${SOURCE_TYPES.find(t => t.id === selectedType)?.name || ""} 数据源`} setIsOpen(false)} /> ); }
dbt integration is available for PostgreSQL, MySQL, BigQuery, Redshift, and Snowflake (For Essential Plan and above). Contact Us to suggest new data sources.
管理可用于问答的数据源连接
暂无数据源
点击右上角按钮添加第一个数据源
{ds.type}