Console

A Console allows for persistent logs of rich text to be displayed.

Screenshot of component Console overview

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.

Screenshot of component Console transformed-text
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.

Screenshot of component Console other-methods
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.

Screenshot of component Console ordering

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'.

Screenshot of component Console clear-button
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] }
}
}}
/>
</>
)
}