import { useEffect, useRef, useState } from "react"; import { ExclamationTriangleIcon } from "@heroicons/react/24/solid"; import format from "date-fns/format"; import { DebounceInput } from "react-debounce-input"; import { APIClient } from "../api/APIClient"; import { Checkbox } from "../components/Checkbox"; import { classNames } from "../utils"; import { SettingsContext } from "../utils/Context"; type LogEvent = { time: string; level: string; message: string; }; type LogLevel = "TRACE" | "DEBUG" | "INFO" | "ERROR"; const LogColors: Record = { "TRACE": "text-purple-300", "DEBUG": "text-yellow-500", "INFO": "text-green-500", "ERROR": "text-red-500" }; export const Logs = () => { const [settings, setSettings] = SettingsContext.use(); const messagesEndRef = useRef(null); const [logs, setLogs] = useState([]); const [searchFilter, setSearchFilter] = useState(""); const [filteredLogs, setFilteredLogs] = useState([]); const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: "auto" }); }; useEffect(() => { const es = APIClient.events.logs(); es.onmessage = (event) => { const newData = JSON.parse(event.data) as LogEvent; setLogs((prevState) => [...prevState, newData]); if (settings.scrollOnNewLog) scrollToBottom(); }; return () => es.close(); }, [setLogs, settings]); useEffect(() => { if (!searchFilter.length) { setFilteredLogs(logs); return; } const newLogs: LogEvent[] = []; logs.forEach((log) => { if (log.message.indexOf(searchFilter) !== -1) newLogs.push(log); }); setFilteredLogs(newLogs); }, [logs, searchFilter]); const onSetValue = ( key: "scrollOnNewLog" | "indentLogLines" | "hideWrappedText", newValue: boolean ) => setSettings((prevState) => ({ ...prevState, [key]: newValue })); return (

Logs

setSearchFilter(event.target.value.toLowerCase().trim())} id="filter" type="text" autoComplete="off" className={classNames( "focus:ring-blue-500 dark:focus:ring-blue-500 focus:border-blue-500 dark:focus:border-blue-500 border-gray-300 dark:border-gray-700", "block w-full dark:bg-gray-800 shadow-sm dark:text-gray-100 sm:text-sm rounded-md" )} placeholder="Enter a string to filter logs by..." />
{filteredLogs.map((entry, idx) => (
{format(new Date(entry.time), "HH:mm:ss.SSS")} {entry.level in LogColors ? ( {entry.level} {" "} ) : null} {entry.message}
))}
onSetValue("scrollOnNewLog", newValue)} /> onSetValue("indentLogLines", newValue)} /> onSetValue("hideWrappedText", newValue)} />
); };