import { useMemo } from "react"; import { Button, Checkbox, Group, Paper, ScrollArea, Stack, Text, Title, } from "@mantine/core"; import { LogEntry } from "../../elements/LogEntry/LogEntry"; import type { LogEntryData } from "../../elements/LogEntry/LogEntry"; export interface LogStreamPanelProps { entries: LogEntryData[]; filterText: string; visibleLevels: Record; autoScroll: boolean; onToggleAutoScroll: () => void; onCopyAll: () => void; onClear: () => void; onExport: () => void; } const PanelContainer = Paper.withProps({ withBorder: true, p: "lg", flex: 1, variant: "panel", }); const ToolbarButton = Button.withProps({ variant: "light", size: "sm", }); const EmptyCenter = Stack.withProps({ flex: 1, align: "center", justify: "center", }); function formatData(data: unknown): string { if (data === undefined || data === null) return ""; if (typeof data === "string") return data; return JSON.stringify(data); } function matchesFilters( entry: LogEntryData, filterText: string, visibleLevels: Record, ): boolean { if (!visibleLevels[entry.params.level]) return false; if (filterText) { const term = filterText.toLowerCase(); const searchable = `${formatData(entry.params.data)} ${entry.params.logger ?? ""} ${entry.params.level}`.toLowerCase(); if (!searchable.includes(term)) return false; } return true; } export function LogStreamPanel({ entries, filterText, visibleLevels, autoScroll, onToggleAutoScroll, onCopyAll, onClear, onExport, }: LogStreamPanelProps) { const filteredEntries = useMemo( () => entries.filter((e) => matchesFilters(e, filterText, visibleLevels)), [entries, filterText, visibleLevels], ); return ( Log Stream Clear Export Copy All {filteredEntries.length > 0 ? ( {filteredEntries.map((entry, index) => ( ))} ) : ( No log entries )} ); }