diff --git a/wallets/client/components/logger.js b/wallets/client/components/logger.js index 881a593d..a67a2ae8 100644 --- a/wallets/client/components/logger.js +++ b/wallets/client/components/logger.js @@ -5,6 +5,7 @@ import { useCallback, useEffect, useState, Fragment } from 'react' import { timeSince } from '@/lib/time' import classNames from 'classnames' import { ModalClosedError } from '@/components/modal' +import { isTemplate } from '@/wallets/lib/util' // TODO(wallet-v2): // when we delete logs for a protocol, the cache is not updated @@ -28,40 +29,105 @@ export function WalletLogs ({ protocol, className, debug }) { const embedded = !!protocol + // avoid unnecessary clutter when attaching new wallet + const hideLogs = logs.length === 0 && protocol && isTemplate(protocol) + if (hideLogs) return null + + // showing delete button and logs footer for temporary template logs is unnecessary clutter + const template = protocol && isTemplate(protocol) + return ( - <> -
- clear logs - -
+
+ {!template && ( +
+ clear logs + +
+ )}
{logs.map((log, i) => ( ))} - {loading - ?
loading...
- : logs.length === 0 &&
empty
} - {hasMore - ?
- :
------ start of logs ------
} + {!template && }
+
+ ) +} + +function WalletLogsFooter ({ empty, loading, hasMore, loadMore }) { + return ( + <> + {loading + ?
loading...
+ : empty &&
empty
} + {hasMore + ?
+ :
------ start of logs ------
} ) } export function LogMessage ({ tag, level, message, context, ts }) { - const [show, setShow] = useState(false) + const [showContext, setShowContext] = useState(false) + 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) { setShowContext(show => !show) } + } + const style = hasContext ? { cursor: 'pointer' } : { cursor: 'inherit' } + + return ( + <> +
+ + {tag !== null && } + + + {hasContext && } +
+ {hasContext && showContext && } + + ) +} + +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}
+} + +function Tag ({ tag }) { + return
{`[${tag}]`}
+} + +function Level ({ level }) { let className switch (level.toLowerCase()) { case 'ok': @@ -80,69 +146,29 @@ export function LogMessage ({ tag, level, message, context, ts }) { 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 - }, {}) - : {} + return
{level}
+} - const hasContext = context && Object.keys(filtered).length > 0 +function Message ({ message }) { + return
{message}
+} - const handleClick = () => { - if (hasContext) { setShow(show => !show) } - } - - const style = hasContext ? { cursor: 'pointer' } : { cursor: 'inherit' } - const indicator = hasContext ? (show ? '-' : '+') : <> - - // TODO(wallet-v2): show invoice context +function Indicator ({ show }) { + return
{show ? '-' : '+'}
+} +function Context ({ context }) { return ( - <> -
- -
{`[${nameToTag(tag)}]`}
-
{level}
-
{message}
-
{indicator}
-
- {show && hasContext && ( -
- {Object.entries(filtered) - .map(([key, value], i) => { - return ( - -
{key}:
-
{value}
-
- ) - })} -
- )} - +
+ {Object.entries(context) + .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}
-} diff --git a/wallets/client/hooks/logger.js b/wallets/client/hooks/logger.js index 58db41da..27279022 100644 --- a/wallets/client/hooks/logger.js +++ b/wallets/client/hooks/logger.js @@ -88,21 +88,21 @@ export function useWalletLogs (protocol, debug) { const { templateLogs, clearTemplateLogs } = useContext(TemplateLogsContext) const [cursor, setCursor] = useState(null) - // if we're configuring a protocol template, there are no logs to fetch - const skip = protocol && isTemplate(protocol) - const [logs, setLogs] = useState(skip ? templateLogs : []) + const [logs, setLogs] = useState([]) // if no protocol was given, we want to fetch all logs const protocolId = protocol ? Number(protocol.id) : undefined + // if we're configuring a protocol template, there are no logs to fetch + const noFetch = protocol && isTemplate(protocol) const [fetchLogs, { called, loading, error }] = useLazyQuery(WALLET_LOGS, { variables: { protocolId, debug }, - skip, + skip: noFetch, fetchPolicy: 'network-only' }) useEffect(() => { - if (skip) return + if (noFetch) return const interval = setInterval(async () => { const { data, error } = await fetchLogs({ variables: { protocolId, debug } }) @@ -118,7 +118,7 @@ export function useWalletLogs (protocol, debug) { }, FAST_POLL_INTERVAL) return () => clearInterval(interval) - }, [fetchLogs, called, skip, debug]) + }, [fetchLogs, called, noFetch, debug]) const loadMore = useCallback(async () => { const { data } = await fetchLogs({ variables: { protocolId, cursor, debug } }) @@ -135,14 +135,14 @@ export function useWalletLogs (protocol, debug) { return useMemo(() => { return { - loading: skip ? false : (!called ? true : loading), - logs: skip ? templateLogs : logs, + loading: noFetch ? false : (!called ? true : loading), + logs: noFetch ? templateLogs : logs, error, loadMore, hasMore: cursor !== null, clearLogs } - }, [loading, skip, called, templateLogs, logs, error, loadMore, clearLogs]) + }, [loading, noFetch, called, templateLogs, logs, error, loadMore, clearLogs]) } function mapLevelToConsole (level) {