import { Button } from 'react-bootstrap' import styles from '@/styles/logger.module.css' import { useWalletLogs, useDeleteWalletLogs } from '@/wallets/client/hooks' import { useCallback, useEffect, useState, Fragment } from 'react' import { timeSince } from '@/lib/time' import classNames from 'classnames' import { ModalClosedError } from '@/components/modal' // TODO(wallet-v2): // when we delete logs for a protocol, the cache is not updated // so when we go to all wallet logs, we still see the deleted logs until the query is refetched export function WalletLogs ({ protocol, className, debug }) { const { logs, loadMore, hasMore, loading, clearLogs } = useWalletLogs(protocol, debug) const deleteLogs = useDeleteWalletLogs(protocol, debug) const onDelete = useCallback(async () => { try { await deleteLogs() clearLogs() } catch (err) { if (err instanceof ModalClosedError) { return } console.error('error deleting logs:', err) } }, [deleteLogs, clearLogs]) const embedded = !!protocol return ( <>
clear logs
{logs.map((log, i) => ( ))} {loading ?
loading...
: logs.length === 0 &&
empty
} {hasMore ?
:
------ start of logs ------
}
) } export function LogMessage ({ tag, level, message, context, ts }) { const [show, setShow] = useState(false) let className switch (level.toLowerCase()) { case 'ok': case 'success': level = 'ok' className = 'text-success'; break case 'error': className = 'text-danger'; break case 'warning': level = 'warn' className = 'text-warning'; break case 'info': className = 'text-info'; break case 'debug': default: className = 'text-muted'; break } const filtered = context ? Object.keys(context) .filter(key => !['send', 'recv', 'status'].includes(key)) .reduce((obj, key) => { obj[key] = context[key] return obj }, {}) : {} const hasContext = context && Object.keys(filtered).length > 0 const handleClick = () => { if (hasContext) { setShow(show => !show) } } const style = hasContext ? { cursor: 'pointer' } : { cursor: 'inherit' } const indicator = hasContext ? (show ? '-' : '+') : <> // TODO(wallet-v2): show invoice context return ( <>
{`[${nameToTag(tag)}]`}
{level}
{message}
{indicator}
{show && hasContext && (
{Object.entries(filtered) .map(([key, value], i) => { return (
{key}:
{value}
) })}
)} ) } function nameToTag (name) { switch (name) { case undefined: return 'system' default: return name.toLowerCase() } } function TimeSince ({ timestamp }) { const [time, setTime] = useState(timeSince(new Date(timestamp))) useEffect(() => { const timer = setInterval(() => { setTime(timeSince(new Date(timestamp))) }, 1000) return () => clearInterval(timer) }, [timestamp]) return
{time}
}