import React, {useState, useCallback, useEffect} from 'react'; import './LogsSection.css'; import {FixedSizeList} from "fixed-size-list"; import {useEventSource, useEventSourceListener} from "@react-nano/use-event-source"; import LogLine from "./LogLine"; import {useGetLogsQuery, useLazySetLogSettingsQuery} from "./logsApi"; import {connect, ConnectedProps} from "react-redux"; import {RootState} from "../store"; import Loading from "../components/loading/Loading"; const logBuffer: { message: string, id: string, level: number, levelLabel:string }[] = []; interface MinLogInfo { message: string, id: string, level: number levelLabel: string } const createFixedList = (size, initialList: MinLogInfo[] = []): FixedSizeList => { return new FixedSizeList(size, initialList); } let list = createFixedList(50); interface LogLevelButtonProps { name: string, active: boolean, onClick: Function } const LogLevelButton = (props: LogLevelButtonProps) => { const {name, active, onClick} = props; const click = useCallback(() => active ? null : onClick(name), [onClick, name, active]); const className = active ? "mx-1" : "capitalize underline cursor-pointer mx-1"; return {name.toUpperCase()}; } const LogLimitButton = (props: {val: number, active: boolean, onClick: Function}) => { const {val, active, onClick} = props; const click = useCallback(() => active ? null : onClick(val), [onClick, val, active]); const className = active ? "mx-1" : "capitalize underline cursor-pointer mx-1"; return {val}; } const LogsSection = (props: PropsFromRedux) => { const { logs, settings, settings: { limit = 50 } } = props; const [logList, setLogList] = useState(logBuffer); const [logLevel, setLogLevel] = useState('debug') useGetLogsQuery(undefined); useEffect(() => { list = createFixedList(settings.limit, logs.map((x, index) => ({...x, message: x.line, id: index.toString()}))); setLogList(Array.from(list.data)); setLogLevel(settings.level); }, [logs, settings, setLogList, setLogLevel]); const [setSettings] = useLazySetLogSettingsQuery(); const fetchLevel = useCallback(async (val) => { setSettings({level: val}); }, [setSettings]); const fetchLimit = useCallback(async (val) => { setSettings({limit: val}); }, [setSettings]); const [eventSource, eventSourceStatus] = useEventSource("api/logs/stream", false); useEventSourceListener(eventSource, ['messsage', 'stream'], evt => { const data = JSON.parse(evt.data); // @ts-ignore list.add({message: data.message, id: evt.lastEventId, level: data.level, levelLabel: data.levelLabel}); setLogList(Array.from(list.data)); //console.log(evt); }, [setLogList]); // TODO may eventually add log filtering back in but idk if anyone even uses it right now return (

Log (Most Recent)

Level : | | | |
Limit : | |

{ logList.map(x => ) }
); } const mapStateToProps = (state: RootState) => ({ logs: state.logs.data, settings: state.logs.settings }); type PropsFromRedux = ConnectedProps const connector = connect(mapStateToProps); export default connector(LogsSection);