import { useMemo, useState, useEffect } from 'react'; import RefreshIcon from '@/assets/icons/refresh.svg?react'; import { Button, ConvertedValue, DataGrid, type DataGridColumn, type DataGridRowType, EmptyState, SearchInput, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from '@/components'; import { useFullMetadata } from '../hooks/useFullMetadata'; import type { ExportDatabaseResponse, ExportDatabaseJsonData } from '@insforge/shared-schemas'; import { isSystemTable } from '../constants'; import { DataUpdatePayload, DataUpdateResourceType, ServerEvents, SocketMessage, useSocket, } from '@/lib/contexts/SocketContext'; interface IndexRow extends DataGridRowType { id: string; tableName: string; indexName: string; indexDef: string; isUnique: boolean | null; isPrimary: boolean | null; [key: string]: ConvertedValue | { [key: string]: string }[]; } function parseIndexesFromMetadata(metadata: ExportDatabaseResponse | undefined): IndexRow[] { if (!metadata || metadata.format !== 'json' || typeof metadata.data === 'string') { return []; } const data = metadata.data as ExportDatabaseJsonData; const indexes: IndexRow[] = []; Object.entries(data.tables).forEach(([tableName, tableData]) => { if (isSystemTable(tableName)) { return; } tableData.indexes.forEach((index) => { indexes.push({ id: `${tableName}_${index.indexname}`, tableName, indexName: index.indexname, indexDef: index.indexdef, isUnique: index.isUnique, isPrimary: index.isPrimary, }); }); }); return indexes; } export default function IndexesPage() { const [searchQuery, setSearchQuery] = useState(''); const [isRefreshing, setIsRefreshing] = useState(false); const { data: metadata, isLoading, error, refetch } = useFullMetadata(true); const { socket, isConnected } = useSocket(); const allIndexes = useMemo(() => parseIndexesFromMetadata(metadata), [metadata]); useEffect(() => { if (!socket || !isConnected) { return; } const handleDataUpdate = (message: SocketMessage) => { if (message.payload?.resource === DataUpdateResourceType.DATABASE) { void refetch(); } }; socket.on(ServerEvents.DATA_UPDATE, handleDataUpdate); return () => { socket.off(ServerEvents.DATA_UPDATE, handleDataUpdate); }; }, [socket, isConnected, refetch]); const filteredIndexes = useMemo(() => { if (!searchQuery.trim()) { return allIndexes; } const query = searchQuery.toLowerCase(); return allIndexes.filter( (index) => index.indexName.toLowerCase().includes(query) || index.tableName.toLowerCase().includes(query) ); }, [allIndexes, searchQuery]); const handleRefresh = async () => { setIsRefreshing(true); try { setSearchQuery(''); await refetch(); } finally { setIsRefreshing(false); } }; const columns: DataGridColumn[] = useMemo( () => [ { key: 'tableName', name: 'Table', width: 'minmax(180px, 1.5fr)', resizable: true, sortable: true, }, { key: 'indexName', name: 'Name', width: 'minmax(200px, 2fr)', resizable: true, sortable: true, }, { key: 'isPrimary', name: 'Type', width: 'minmax(120px, 1fr)', resizable: true, sortable: true, renderCell: ({ row }) => { if (row.isPrimary) { return ( Primary ); } if (row.isUnique) { return ( Unique ); } return ( Index ); }, }, { key: 'indexDef', name: 'Definition', width: 'minmax(300px, 5fr)', resizable: true, }, ], [] ); if (error) { return (
); } return (

Database Indexes

{/* Separator */}
{/* Refresh button */}

{isRefreshing ? 'Refreshing...' : 'Refresh'}

{isLoading ? (
) : (
{searchQuery ? 'No indexes match your search criteria' : 'No indexes found'}
} />
)}
); }