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 TriggerRow extends DataGridRowType { id: string; tableName: string; triggerName: string; actionTiming: string; eventManipulation: string; actionStatement: string; [key: string]: ConvertedValue | { [key: string]: string }[]; } function parseTriggersFromMetadata(metadata: ExportDatabaseResponse | undefined): TriggerRow[] { if (!metadata || metadata.format !== 'json' || typeof metadata.data === 'string') { return []; } const data = metadata.data as ExportDatabaseJsonData; const triggers: TriggerRow[] = []; Object.entries(data.tables).forEach(([tableName, tableData]) => { if (isSystemTable(tableName)) { return; } tableData.triggers.forEach((trigger) => { triggers.push({ id: `${tableName}_${trigger.triggerName}`, tableName, triggerName: trigger.triggerName, actionTiming: trigger.actionTiming, eventManipulation: trigger.eventManipulation, actionStatement: trigger.actionStatement, }); }); }); return triggers; } export default function TriggersPage() { const [searchQuery, setSearchQuery] = useState(''); const [isRefreshing, setIsRefreshing] = useState(false); const { data: metadata, isLoading, error, refetch } = useFullMetadata(true); const { socket, isConnected } = useSocket(); const allTriggers = useMemo(() => parseTriggersFromMetadata(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 filteredTriggers = useMemo(() => { if (!searchQuery.trim()) { return allTriggers; } const query = searchQuery.toLowerCase(); return allTriggers.filter( (trigger) => trigger.triggerName.toLowerCase().includes(query) || trigger.tableName.toLowerCase().includes(query) ); }, [allTriggers, 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: 'triggerName', name: 'Name', width: 'minmax(200px, 2fr)', resizable: true, sortable: true, }, { key: 'actionTiming', name: 'Timing', width: 'minmax(100px, 1fr)', resizable: true, sortable: true, renderCell: ({ row }) => { const timing = row.actionTiming.toUpperCase(); return ( {timing} ); }, }, { key: 'eventManipulation', name: 'Event', width: 'minmax(100px, 1fr)', resizable: true, sortable: true, renderCell: ({ row }) => { const event = row.eventManipulation.toUpperCase(); return ( {event} ); }, }, { key: 'actionStatement', name: 'Statement', width: 'minmax(300px, 3fr)', resizable: true, }, ], [] ); if (error) { return (
); } return (

Database Triggers

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

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

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