Improve ui & performance
This commit is contained in:
41
app/src/components/Sidebar/NodeStats.tsx
Normal file
41
app/src/components/Sidebar/NodeStats.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
// import Drawer from '@material-ui/core/Drawer'
|
||||
import { Typography } from '@material-ui/core'
|
||||
import { withStyles, Theme, StyleRulesCallback } from '@material-ui/core/styles'
|
||||
|
||||
interface Props {
|
||||
node: q.TreeNode,
|
||||
classes: any,
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
interface State {
|
||||
node?: q.TreeNode | undefined
|
||||
}
|
||||
|
||||
class NodeStats extends React.Component<Props, State> {
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
public static styles: StyleRulesCallback<string> = (theme: Theme) => {
|
||||
return {
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const leafes = this.props.node.leafes()
|
||||
const leafMessages = leafes
|
||||
.map(leaf => leaf.messages)
|
||||
.reduce((a, b) => a + b)
|
||||
|
||||
return <Typography>
|
||||
<p>Messages: #{this.props.node.messages}</p>
|
||||
<p>Subtopics: {leafes.length}</p>
|
||||
<p>Messages Subtopics: #{leafMessages}</p>
|
||||
</Typography>
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(NodeStats.styles, { withTheme: true })(NodeStats)
|
||||
105
app/src/components/Sidebar/Sidebar.tsx
Normal file
105
app/src/components/Sidebar/Sidebar.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
// import Drawer from '@material-ui/core/Drawer'
|
||||
import ExpansionPanel from '@material-ui/core/ExpansionPanel'
|
||||
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary'
|
||||
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails'
|
||||
import ExpandMore from '@material-ui/icons/ExpandMore'
|
||||
import ValueRenderer from './ValueRenderer'
|
||||
import NodeStats from './NodeStats'
|
||||
import Topic from './Topic'
|
||||
import { Typography } from '@material-ui/core'
|
||||
import { withStyles, Theme, StyleRulesCallback } from '@material-ui/core/styles'
|
||||
|
||||
interface Props {
|
||||
node?: q.TreeNode | undefined,
|
||||
classes: any,
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
interface State {
|
||||
node?: q.TreeNode | undefined
|
||||
}
|
||||
|
||||
class Sidebar extends React.Component<Props, State> {
|
||||
private updateNode: (node?: q.TreeNode | undefined) => void
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
this.state = {}
|
||||
this.updateNode = (node) => {
|
||||
if (!node) {
|
||||
this.setState(this.state)
|
||||
} else {
|
||||
this.setState({ node })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static styles: StyleRulesCallback<string> = (theme: Theme) => {
|
||||
return {
|
||||
drawer: {
|
||||
display: 'block',
|
||||
height: '100%',
|
||||
},
|
||||
valuePaper: {
|
||||
margin: `${theme.spacing.unit}px ${theme.spacing.unit}px ${theme.spacing.unit}px ${theme.spacing.unit}px`,
|
||||
},
|
||||
heading: {
|
||||
fontSize: theme.typography.pxToRem(15),
|
||||
fontWeight: theme.typography.fontWeightRegular,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
this.props.node && this.props.node.removeListener('update', this.updateNode)
|
||||
nextProps.node && nextProps.node.on('update', this.updateNode)
|
||||
nextProps.node && this.updateNode(nextProps.node)
|
||||
}
|
||||
|
||||
private open(): boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
public render() {
|
||||
return <div className={this.props.classes.drawer}>
|
||||
{this.renderNode()}
|
||||
</div>
|
||||
}
|
||||
|
||||
private renderNode() {
|
||||
const { classes } = this.props
|
||||
if (!this.state.node) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <div>
|
||||
<ExpansionPanel key="topic" defaultExpanded={true}>
|
||||
<ExpansionPanelSummary expandIcon={<ExpandMore />}>
|
||||
<Typography className={classes.heading}>Topic</Typography>
|
||||
</ExpansionPanelSummary>
|
||||
<ExpansionPanelDetails>
|
||||
<Topic node={this.state.node} />
|
||||
</ExpansionPanelDetails>
|
||||
</ExpansionPanel>
|
||||
<ExpansionPanel key="value" defaultExpanded={true}>
|
||||
<ExpansionPanelSummary expandIcon={<ExpandMore />}>
|
||||
<Typography className={classes.heading}>Value</Typography>
|
||||
</ExpansionPanelSummary>
|
||||
<ExpansionPanelDetails>
|
||||
<ValueRenderer node={this.state.node} />
|
||||
</ExpansionPanelDetails>
|
||||
</ExpansionPanel>
|
||||
<ExpansionPanel key="stats" defaultExpanded={true}>
|
||||
<ExpansionPanelSummary expandIcon={<ExpandMore />}>
|
||||
<Typography className={classes.heading}>Stats</Typography>
|
||||
</ExpansionPanelSummary>
|
||||
<ExpansionPanelDetails>
|
||||
<NodeStats node={this.state.node} />
|
||||
</ExpansionPanelDetails>
|
||||
</ExpansionPanel>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(Sidebar.styles, { withTheme: true })(Sidebar)
|
||||
52
app/src/components/Sidebar/Topic.tsx
Normal file
52
app/src/components/Sidebar/Topic.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import { withStyles, Theme, StyleRulesCallback } from '@material-ui/core/styles'
|
||||
import Button from '@material-ui/core/Button'
|
||||
|
||||
interface Props {
|
||||
classes: any
|
||||
theme: Theme
|
||||
node: q.TreeNode
|
||||
selected?: q.TreeNode
|
||||
}
|
||||
|
||||
class Topic extends React.Component<Props, {}> {
|
||||
public static styles: StyleRulesCallback<string> = (theme: Theme) => ({
|
||||
button: {
|
||||
textTransform: 'none',
|
||||
padding: '3px 5px 3px 5px',
|
||||
minWidth: '30px',
|
||||
},
|
||||
})
|
||||
|
||||
public render() {
|
||||
const { node } = this.props
|
||||
let i = 0
|
||||
const breadCrumps = node.branch()
|
||||
.map(node => node.sourceEdge)
|
||||
.filter(edge => Boolean(edge))
|
||||
.map(edge =>
|
||||
[<Button
|
||||
onClick={() => this.setState({ node: edge!.target })}
|
||||
size="small"
|
||||
color="secondary"
|
||||
className={this.props.classes.button}
|
||||
key={edge!.hash()}
|
||||
>
|
||||
{edge!.name}
|
||||
</Button>],
|
||||
)
|
||||
|
||||
if (breadCrumps.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const joinedBreadCrumps = breadCrumps.reduce((prev, current) =>
|
||||
prev.concat([<span key={i += 1}>/</span>]).concat(current),
|
||||
)
|
||||
|
||||
return <span style={{ lineHeight: '2.2em' }}>{joinedBreadCrumps}</span>
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(Topic.styles, { withTheme: true })(Topic)
|
||||
82
app/src/components/Sidebar/ValueRenderer.tsx
Normal file
82
app/src/components/Sidebar/ValueRenderer.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import { default as ReactJson } from 'react-json-view'
|
||||
import { withTheme, Theme } from '@material-ui/core/styles'
|
||||
|
||||
interface Props {
|
||||
node?: q.TreeNode | undefined
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
interface State {
|
||||
node?: q.TreeNode | undefined
|
||||
}
|
||||
|
||||
class ValueRenderer extends React.Component<Props, State> {
|
||||
private updateNode: (node?: q.TreeNode | undefined) => void
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
this.state = {}
|
||||
this.updateNode = (node) => {
|
||||
if (!node) {
|
||||
this.setState(this.state)
|
||||
} else {
|
||||
this.setState({ node })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
this.props.node && this.props.node.removeListener('update', this.updateNode)
|
||||
nextProps.node && nextProps.node.on('update', this.updateNode)
|
||||
nextProps.node && this.updateNode(nextProps.node)
|
||||
}
|
||||
|
||||
private style = (theme: Theme) => {
|
||||
|
||||
}
|
||||
|
||||
public render() {
|
||||
const node = this.props.node
|
||||
if (!node || !node.message) {
|
||||
return null
|
||||
}
|
||||
|
||||
let json
|
||||
try {
|
||||
json = JSON.parse(node.message.value)
|
||||
} catch (error) {
|
||||
return this.renderRawValue(node.message.value)
|
||||
}
|
||||
|
||||
if (typeof json === 'string') {
|
||||
return this.renderRawValue(node.message.value)
|
||||
} else if (typeof json === 'number') {
|
||||
return this.renderRawValue(node.message.value)
|
||||
} else {
|
||||
const theme = this.props.theme.palette.type === 'dark' ? 'monokai' : 'bright:inverted'
|
||||
return <ReactJson
|
||||
style={{ width: '100%' }}
|
||||
src={json}
|
||||
theme={theme}
|
||||
onEdit={(val) => {
|
||||
console.log(val)
|
||||
}} />
|
||||
}
|
||||
}
|
||||
|
||||
private renderRawValue(value: string) {
|
||||
const style: React.CSSProperties = {
|
||||
wordBreak: 'break-all',
|
||||
width: '100%',
|
||||
overflow: 'scroll',
|
||||
display: 'block',
|
||||
lineHeight: '1.2em',
|
||||
padding: '12px 5px 12px 5px',
|
||||
}
|
||||
|
||||
return <pre style={style}><code>{value}</code></pre>
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme()(ValueRenderer)
|
||||
3
app/src/components/Sidebar/index.ts
Normal file
3
app/src/components/Sidebar/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import Sidebar from './Sidebar'
|
||||
|
||||
export { Sidebar }
|
||||
Reference in New Issue
Block a user