Add message history to frontend
This commit is contained in:
87
app/src/components/Sidebar/History.tsx
Normal file
87
app/src/components/Sidebar/History.tsx
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
import * as q from '../../../../backend/src/Model'
|
||||||
|
|
||||||
|
import { Badge, Typography } from '@material-ui/core'
|
||||||
|
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||||
|
|
||||||
|
interface HistoryItem {
|
||||||
|
title: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
items: HistoryItem[]
|
||||||
|
onClick?: (index: number) => void
|
||||||
|
classes: any
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
collapsed: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageHistory extends React.Component<Props, State> {
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props)
|
||||||
|
this.state = {
|
||||||
|
collapsed: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderHistory() {
|
||||||
|
const messageStyle: React.CSSProperties = { textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden' }
|
||||||
|
const elements = this.props.items.map((element, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(80, 80, 80, 0.6)',
|
||||||
|
margin: '8px',
|
||||||
|
padding: '8px 8px 0 8px',
|
||||||
|
cursor: this.props.onClick ? 'pointer' : 'inherit',
|
||||||
|
}}
|
||||||
|
onClick={() => this.props.onClick && this.props.onClick(index)}
|
||||||
|
>
|
||||||
|
<div><i>{element.title}</i></div>
|
||||||
|
<div style={messageStyle}>
|
||||||
|
<span><pre>{element.value}</pre></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ backgroundColor: 'rgba(60, 60, 60, 0.6)', marginTop: '16px' }}>
|
||||||
|
<Typography
|
||||||
|
onClick={this.toggle}
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
>
|
||||||
|
{this.state.collapsed ? '▶' : '▼'} History
|
||||||
|
</Typography>
|
||||||
|
{this.state.collapsed ? null : elements}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const visible = this.props.items.length > 0 && this.state.collapsed
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
style={{display: 'block', width: '100%'}}
|
||||||
|
invisible={!visible}
|
||||||
|
badgeContent={this.props.items.length}
|
||||||
|
color="primary"
|
||||||
|
classes={{badge: this.props.classes.badge}}
|
||||||
|
>
|
||||||
|
{this.renderHistory()}
|
||||||
|
</Badge>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private toggle = () => {
|
||||||
|
this.setState({ collapsed: !this.state.collapsed })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = (theme: Theme) => ({
|
||||||
|
badge: {top: '-8px', left:'64px'}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default withStyles(styles)(MessageHistory)
|
||||||
49
app/src/components/Sidebar/MessageHistory.tsx
Normal file
49
app/src/components/Sidebar/MessageHistory.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
import * as q from '../../../../backend/src/Model'
|
||||||
|
|
||||||
|
import { Theme, withTheme } from '@material-ui/core/styles'
|
||||||
|
|
||||||
|
import History from './History'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
node?: q.TreeNode
|
||||||
|
theme: Theme
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessageHistory extends React.Component<Props, {}> {
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props)
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateNode = () => {
|
||||||
|
this.setState(this.state)
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
|
this.props.node && this.props.node.onMessage.unsubscribe(this.updateNode)
|
||||||
|
nextProps.node && nextProps.node.onMessage.subscribe(this.updateNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillMount() {
|
||||||
|
this.props.node && this.props.node.onMessage.subscribe(this.updateNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillUnMount() {
|
||||||
|
this.props.node && this.props.node.onMessage.unsubscribe(this.updateNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
if (!this.props.node) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const history = this.props.node.messageHistory.toArray()
|
||||||
|
const historyElements = history.map(message => ({
|
||||||
|
title: message.received.toGMTString(),
|
||||||
|
value: message.value,
|
||||||
|
}))
|
||||||
|
|
||||||
|
return <History items={historyElements} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withTheme()(MessageHistory)
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
import * as React from 'react'
|
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { bindActionCreators } from 'redux'
|
|
||||||
import { sidebarActions } from '../../../actions'
|
|
||||||
import { Typography } from '@material-ui/core'
|
|
||||||
import Message from './Model/Message'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
message: Message
|
|
||||||
actions: any
|
|
||||||
}
|
|
||||||
|
|
||||||
class HystoryEntry extends React.Component<Props, {}> {
|
|
||||||
public render() {
|
|
||||||
const { message } = this.props
|
|
||||||
return (
|
|
||||||
<Typography onClick={this.setPublishPreset}>
|
|
||||||
<div style={{ width: '100%', cursor: 'pointer', marginTop: '8px' }}>
|
|
||||||
<div><b>{message.topic}</b></div>
|
|
||||||
<div><i>{message.payload}</i></div>
|
|
||||||
</div>
|
|
||||||
</Typography>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private setPublishPreset = (e: React.MouseEvent) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
this.props.actions.setPublishTopic(this.props.message.topic)
|
|
||||||
this.props.actions.setPublishPayload(this.props.message.payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: any) => {
|
|
||||||
return {
|
|
||||||
actions: bindActionCreators(sidebarActions, dispatch),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(HystoryEntry)
|
|
||||||
@@ -1,20 +1,3 @@
|
|||||||
import * as React from 'react'
|
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { bindActionCreators } from 'redux'
|
|
||||||
import * as q from '../../../../../backend/src/Model'
|
|
||||||
import { AppState } from '../../../reducers'
|
|
||||||
import { rendererEvents, makePublishEvent } from '../../../../../events'
|
|
||||||
import { sidebarActions } from '../../../actions'
|
|
||||||
import Navigation from '@material-ui/icons/Navigation'
|
|
||||||
import {
|
|
||||||
Button, Fab, InputAdornment, FormControlLabel, Radio,
|
|
||||||
RadioGroup, TextField, Typography,
|
|
||||||
} from '@material-ui/core'
|
|
||||||
import Message from './Model/Message'
|
|
||||||
import HistoryEntry from './HistoryEntry'
|
|
||||||
|
|
||||||
import * as brace from 'brace'
|
|
||||||
import { default as AceEditor } from 'react-ace'
|
|
||||||
// tslint:disable-next-line
|
// tslint:disable-next-line
|
||||||
import 'react-ace'
|
import 'react-ace'
|
||||||
import 'brace/mode/json'
|
import 'brace/mode/json'
|
||||||
@@ -22,6 +5,31 @@ import 'brace/mode/text'
|
|||||||
import 'brace/mode/xml'
|
import 'brace/mode/xml'
|
||||||
import 'brace/theme/monokai'
|
import 'brace/theme/monokai'
|
||||||
|
|
||||||
|
import * as React from 'react'
|
||||||
|
import * as brace from 'brace'
|
||||||
|
import * as q from '../../../../../backend/src/Model'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Fab,
|
||||||
|
FormControlLabel,
|
||||||
|
InputAdornment,
|
||||||
|
Radio,
|
||||||
|
RadioGroup,
|
||||||
|
TextField,
|
||||||
|
Typography,
|
||||||
|
} from '@material-ui/core'
|
||||||
|
import { makePublishEvent, rendererEvents } from '../../../../../events'
|
||||||
|
|
||||||
|
import { default as AceEditor } from 'react-ace'
|
||||||
|
import { AppState } from '../../../reducers'
|
||||||
|
import History from '../History'
|
||||||
|
import Message from './Model/Message'
|
||||||
|
import Navigation from '@material-ui/icons/Navigation'
|
||||||
|
import { bindActionCreators } from 'redux'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { sidebarActions } from '../../../actions'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
node?: q.TreeNode
|
node?: q.TreeNode
|
||||||
connectionId?: string
|
connectionId?: string
|
||||||
@@ -35,7 +43,7 @@ interface State {
|
|||||||
history: Message[]
|
history: Message[]
|
||||||
}
|
}
|
||||||
|
|
||||||
class Publisher extends React.Component<Props, State> {
|
class Publish extends React.Component<Props, State> {
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = { mode: 'json', history: [] }
|
this.state = { mode: 'json', history: [] }
|
||||||
@@ -140,7 +148,7 @@ class Publisher extends React.Component<Props, State> {
|
|||||||
const labelStyle = { margin: '0 8px 0 8px' }
|
const labelStyle = { margin: '0 8px 0 8px' }
|
||||||
return (
|
return (
|
||||||
<div style={{ marginTop: '16px' }}>
|
<div style={{ marginTop: '16px' }}>
|
||||||
<Typography style={{ width: '100%', lineHeight: '64px' }}>
|
<div style={{ width: '100%', lineHeight: '64px' }}>
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
style={{ display: 'inline-block', float: 'left' }}
|
style={{ display: 'inline-block', float: 'left' }}
|
||||||
value={this.state.mode}
|
value={this.state.mode}
|
||||||
@@ -172,22 +180,24 @@ class Publisher extends React.Component<Props, State> {
|
|||||||
<div style={{ float: 'right', marginRight: '16px' }}>
|
<div style={{ float: 'right', marginRight: '16px' }}>
|
||||||
{this.publishButton()}
|
{this.publishButton()}
|
||||||
</div>
|
</div>
|
||||||
</Typography>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private history() {
|
private history() {
|
||||||
const entries = this.state.history.map(message => (
|
const items = this.state.history.map(message => ({
|
||||||
<HistoryEntry message={message} />
|
title: message.topic,
|
||||||
))
|
value: message.payload,
|
||||||
|
}))
|
||||||
|
|
||||||
return (
|
return <History items={items} onClick={this.didSelectHistoryEntry} />
|
||||||
<div style={{ marginTop: '8px' }}>
|
}
|
||||||
<Typography>History</Typography>
|
|
||||||
{entries}
|
private didSelectHistoryEntry = (index: number) => {
|
||||||
</div>
|
let message = this.state.history[index]
|
||||||
)
|
this.props.actions.setPublishTopic(message.topic)
|
||||||
|
this.props.actions.setPublishPayload(message.payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
private editor() {
|
private editor() {
|
||||||
@@ -224,4 +234,4 @@ const mapStateToProps = (state: AppState) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Publisher)
|
export default connect(mapStateToProps, mapDispatchToProps)(Publish)
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { connect } from 'react-redux'
|
|
||||||
import { AppState } from '../../reducers'
|
|
||||||
import * as q from '../../../../backend/src/Model'
|
import * as q from '../../../../backend/src/Model'
|
||||||
import { ExpansionPanel, ExpansionPanelDetails, ExpansionPanelSummary, Typography } from '@material-ui/core'
|
|
||||||
import { withStyles, Theme, StyleRulesCallback } from '@material-ui/core/styles'
|
|
||||||
import ExpandMore from '@material-ui/icons/ExpandMore'
|
|
||||||
import Publish from './Publish/Publish'
|
|
||||||
|
|
||||||
|
import { ExpansionPanel, ExpansionPanelDetails, ExpansionPanelSummary, Typography } from '@material-ui/core'
|
||||||
|
import { StyleRulesCallback, Theme, withStyles } from '@material-ui/core/styles'
|
||||||
|
|
||||||
|
import { AppState } from '../../reducers'
|
||||||
import Copy from '../Copy'
|
import Copy from '../Copy'
|
||||||
import ValueRenderer from './ValueRenderer'
|
import ExpandMore from '@material-ui/icons/ExpandMore'
|
||||||
import NodeStats from './NodeStats'
|
import NodeStats from './NodeStats'
|
||||||
|
import Publish from './Publish/Publish'
|
||||||
import Topic from './Topic'
|
import Topic from './Topic'
|
||||||
|
import ValueRenderer from './ValueRenderer'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
node?: q.TreeNode,
|
node?: q.TreeNode,
|
||||||
@@ -74,20 +75,21 @@ class Sidebar extends React.Component<Props, State> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private detailsStyle = { padding: '0px 16px 8px 8px' }
|
||||||
|
|
||||||
private renderNode() {
|
private renderNode() {
|
||||||
const { classes, node } = this.props
|
const { classes, node } = this.props
|
||||||
|
|
||||||
const copyTopic = node ? <Copy value={node.path()} /> : null
|
const copyTopic = node ? <Copy value={node.path()} /> : null
|
||||||
const copyValue = node && node.message ? <Copy value={node.message.value} /> : null
|
const copyValue = node && node.message ? <Copy value={node.message.value} /> : null
|
||||||
const summeryStyle = { minHeight: '0' }
|
const summeryStyle = { minHeight: '0' }
|
||||||
const detailsStyle = { padding: '0px 16px 8px 8px' }
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ExpansionPanel key="topic" defaultExpanded={true}>
|
<ExpansionPanel key="topic" defaultExpanded={true} disabled={!Boolean(this.props.node)}>
|
||||||
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
||||||
<Typography className={classes.heading}>Topic {copyTopic}</Typography>
|
<Typography className={classes.heading}>Topic {copyTopic}</Typography>
|
||||||
</ExpansionPanelSummary>
|
</ExpansionPanelSummary>
|
||||||
<ExpansionPanelDetails style={detailsStyle}>
|
<ExpansionPanelDetails style={this.detailsStyle}>
|
||||||
<Topic node={this.props.node} didSelectNode={this.updateNode} />
|
<Topic node={this.props.node} didSelectNode={this.updateNode} />
|
||||||
</ExpansionPanelDetails>
|
</ExpansionPanelDetails>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
@@ -95,7 +97,7 @@ class Sidebar extends React.Component<Props, State> {
|
|||||||
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
||||||
<Typography className={classes.heading}>Value {copyValue}</Typography>
|
<Typography className={classes.heading}>Value {copyValue}</Typography>
|
||||||
</ExpansionPanelSummary>
|
</ExpansionPanelSummary>
|
||||||
<ExpansionPanelDetails style={detailsStyle}>
|
<ExpansionPanelDetails style={this.detailsStyle}>
|
||||||
<ValueRenderer node={this.props.node} />
|
<ValueRenderer node={this.props.node} />
|
||||||
</ExpansionPanelDetails>
|
</ExpansionPanelDetails>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
@@ -103,21 +105,31 @@ class Sidebar extends React.Component<Props, State> {
|
|||||||
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
||||||
<Typography className={classes.heading}>Publish</Typography>
|
<Typography className={classes.heading}>Publish</Typography>
|
||||||
</ExpansionPanelSummary>
|
</ExpansionPanelSummary>
|
||||||
<ExpansionPanelDetails style={detailsStyle}>
|
<ExpansionPanelDetails style={this.detailsStyle}>
|
||||||
<Publish node={this.props.node} connectionId={this.props.connectionId} />
|
<Publish node={this.props.node} connectionId={this.props.connectionId} />
|
||||||
</ExpansionPanelDetails>
|
</ExpansionPanelDetails>
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
<ExpansionPanel defaultExpanded={true}>
|
<ExpansionPanel defaultExpanded={Boolean(this.props.node)}>
|
||||||
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
<ExpansionPanelSummary expandIcon={<ExpandMore />} style={summeryStyle}>
|
||||||
<Typography className={classes.heading}>Stats</Typography>
|
<Typography className={classes.heading}>Stats</Typography>
|
||||||
</ExpansionPanelSummary>
|
</ExpansionPanelSummary>
|
||||||
<ExpansionPanelDetails style={detailsStyle}>
|
{this.renderNodeStats()}
|
||||||
{this.props.node ? <NodeStats node={this.props.node} /> : null}
|
|
||||||
</ExpansionPanelDetails>
|
|
||||||
</ExpansionPanel>
|
</ExpansionPanel>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderNodeStats() {
|
||||||
|
if (!this.props.node) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ExpansionPanelDetails style={this.detailsStyle}>
|
||||||
|
<NodeStats node={this.props.node} />
|
||||||
|
</ExpansionPanelDetails>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState) => {
|
const mapStateToProps = (state: AppState) => {
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import * as q from '../../../../backend/src/Model'
|
import * as q from '../../../../backend/src/Model'
|
||||||
|
|
||||||
|
import { Theme, withTheme } from '@material-ui/core/styles'
|
||||||
|
|
||||||
|
import MessageHistory from './MessageHistory'
|
||||||
import { default as ReactJson } from 'react-json-view'
|
import { default as ReactJson } from 'react-json-view'
|
||||||
import { withTheme, Theme } from '@material-ui/core/styles'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
node?: q.TreeNode | undefined
|
node?: q.TreeNode
|
||||||
theme: Theme
|
theme: Theme
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
node?: q.TreeNode | undefined
|
node?: q.TreeNode
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValueRenderer extends React.Component<Props, State> {
|
class ValueRenderer extends React.Component<Props, State> {
|
||||||
@@ -28,6 +31,15 @@ class ValueRenderer extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
|
return (
|
||||||
|
<div style={{width: '100%'}}>
|
||||||
|
{this.renderValue()}
|
||||||
|
<MessageHistory node={this.props.node} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderValue() {
|
||||||
const node = this.props.node
|
const node = this.props.node
|
||||||
if (!node || !node.message) {
|
if (!node || !node.message) {
|
||||||
return null
|
return null
|
||||||
@@ -47,19 +59,20 @@ class ValueRenderer extends React.Component<Props, State> {
|
|||||||
} else if (typeof json === 'boolean') {
|
} else if (typeof json === 'boolean') {
|
||||||
return this.renderRawValue(node.message.value)
|
return this.renderRawValue(node.message.value)
|
||||||
} else {
|
} else {
|
||||||
const theme = this.props.theme.palette.type === 'dark' ? 'monokai' : 'bright:inverted'
|
const theme = (this.props.theme.palette.type === 'dark') ? 'monokai' : 'bright:inverted'
|
||||||
return <ReactJson
|
return (
|
||||||
style={{ width: '100%' }}
|
<ReactJson
|
||||||
src={json}
|
style={{ width: '100%' }}
|
||||||
theme={theme}
|
src={json}
|
||||||
onEdit={(val) => {
|
theme={theme}
|
||||||
console.log(val)
|
/>
|
||||||
}} />
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderRawValue(value: string) {
|
private renderRawValue(value: string) {
|
||||||
const style: React.CSSProperties = {
|
const style: React.CSSProperties = {
|
||||||
|
backgroundColor: 'rgba(80, 80, 80, 0.6)',
|
||||||
wordBreak: 'break-all',
|
wordBreak: 'break-all',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
overflow: 'scroll',
|
overflow: 'scroll',
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class Tree extends React.Component<Props, TreeState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Typography style={style}>
|
<div style={style}>
|
||||||
<TreeNode
|
<TreeNode
|
||||||
animateChages={true}
|
animateChages={true}
|
||||||
autoExpandLimit={this.props.autoExpandLimit}
|
autoExpandLimit={this.props.autoExpandLimit}
|
||||||
@@ -120,7 +120,7 @@ class Tree extends React.Component<Props, TreeState> {
|
|||||||
key="rootNode"
|
key="rootNode"
|
||||||
lastUpdate={this.state.tree.lastUpdate}
|
lastUpdate={this.state.tree.lastUpdate}
|
||||||
/>
|
/>
|
||||||
</Typography>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class TreeNodeTitle extends React.Component<TreeNodeProps, {}> {
|
|||||||
|
|
||||||
private renderValue() {
|
private renderValue() {
|
||||||
const style: React.CSSProperties = {
|
const style: React.CSSProperties = {
|
||||||
width: '15em',
|
maxWidth: '15em',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
|
|||||||
@@ -30,5 +30,5 @@ ReactDOM.render(
|
|||||||
<App name="" />
|
<App name="" />
|
||||||
</Provider>
|
</Provider>
|
||||||
</MuiThemeProvider>,
|
</MuiThemeProvider>,
|
||||||
document.getElementById('example'),
|
document.getElementById('app'),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { EventDispatcher } from '../../../events'
|
|||||||
export class TreeNode {
|
export class TreeNode {
|
||||||
public sourceEdge?: Edge
|
public sourceEdge?: Edge
|
||||||
public message?: Message
|
public message?: Message
|
||||||
public messageHistory = new RingBuffer<Message>(3000, 100)
|
public messageHistory: RingBuffer<Message> = new RingBuffer<Message>(3000, 100)
|
||||||
public edges: {[s: string]: Edge} = {}
|
public edges: {[s: string]: Edge} = {}
|
||||||
public collapsed = false
|
public collapsed = false
|
||||||
public messages: number = 0
|
public messages: number = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user