Console
A Console allows for persistent logs of rich text to be displayed.
Usage
Consoles use the Data Source system, and accept a dataSource
prop. This allows for persistent storage of logs when navigating through the application.
import { Console } from '@electricui/components-desktop-blueprint-timeseries'import { useMessageDataSource } from '@electricui/core-timeseries' const OverviewPage = () => { const textDataSource = useMessageDataSource <string>('text') return <Console dataSource ={textDataSource } />}
While text can be passed through directly, usually a simpler data type will be used in the Event which can be expanded to text via the component's accessor.
const counterDataSource = useMessageDataSource <number>('counter') const OverviewPage = () => { return ( <Console dataSource ={counterDataSource } accessor ={num => `The hardware counted to ${num }!`} /> )}
Complex objects
Complex objects can be logged inline, in additional other log methods being used.
By passing an object of the form { method: "log", args: ["Simply log", num] }
, each argument will be rendered with the default inspector view for its type.
const OverviewPage = () => { const counterDataSource = useMessageDataSource <number>('counter') return ( <Console dataSource ={counterDataSource } accessor ={(num : number) => { switch (num ) { case 0: return { method : `warn`, args : [`Warn the user about`, num ] } case 1: return { method : `error`, args : [`Error about...`, num ] } case 2: return { method : `debug`, args : [`Debug log about...`, num ] } default: return { method : `log`, args : [`Simply log`, num ] } } }} /> )}
Ordering
The display ordering can be changed via the orderBy
and order
props.
Note that changing the ordering causes a re-fetch from the persistence engine.
Make sure to memoise the ordering function before passing it to the Console component, otherwise a new instance will be produced each render, resulting in degraded performance.
import { Console , ConsoleRefAPI ,} from '@electricui/components-desktop-blueprint-timeseries'import { useMessageDataSource , Time } from '@electricui/core-timeseries'import { useState , useCallback , useMemo } from 'react'import { Button as BlueprintButton } from '@blueprintjs/core'import { IconNames } from '@blueprintjs/icons' const OverviewPage = () => { const counterDataSource = useMessageDataSource <number>('counter') const [order , setOrder ] = useState (1) const onClick = useCallback (() => setOrder (state => state * -1), [setOrder ]) const ordering = useMemo (() => { if (order === 1) { return (a : Time , b : Time ) => a - b } else { return (a : Time , b : Time ) => b - a } }, [order ]) return ( <> <div style ={{ display : 'flex', justifyContent : 'end', padding : 5 }}> <BlueprintButton onClick ={onClick } icon ={ order === 1 ? IconNames .SORT_NUMERICAL : IconNames .SORT_NUMERICAL_DESC } > {order === 1 ? 'Ordered By Ascending Time' : 'Ordered By Descending Time'} </BlueprintButton > </div > <Console order ={ordering } dataSource ={counterDataSource } accessor ={(data , time ) => `Message received at time: ${time }`} /> </> )}
Clearing
The internal store of data can be cleared via an imperative ref handle. Any re-fetching (via a component re-render, or an ordering change for example) may cause the data to re-appear. This feature is intended for 'quick development interfaces'.
import { Console , ConsoleRefAPI ,} from '@electricui/components-desktop-blueprint-timeseries'import { useMessageDataSource } from '@electricui/core-timeseries'import { useRef , useCallback } from 'react'import { Button as BlueprintButton } from '@blueprintjs/core' const OverviewPage = () => { const counterDataSource = useMessageDataSource <number>('counter') const consoleRef = useRef <ConsoleRefAPI >(null) const onClear = useCallback (() => consoleRef .current ?.clear (), []) return ( <> <div style ={{ display : 'flex', justifyContent : 'end', padding : 5 }}> <BlueprintButton onClick ={onClear }>Clear</BlueprintButton > </div > <Console ref ={consoleRef } dataSource ={counterDataSource } accessor ={(num : number) => { switch (num ) { case 0: return { method : `warn`, args : [`Warn the user about`, num ] } case 1: return { method : `error`, args : [`Error about...`, num ] } case 2: return { method : `debug`, args : [`Debug log about...`, num ] } default: return { method : `log`, args : [`Simply log`, num ] } } }} /> </> )}