mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-25 19:13:56 +03:00
Initial addition of JSON Tree Inspector
This commit is contained in:
parent
9e9d23daf3
commit
45086e246c
|
@ -47,6 +47,8 @@
|
||||||
"redux": "^1.0.0 || 1.0.0-rc"
|
"redux": "^1.0.0 || 1.0.0-rc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"lodash.assign": "^3.2.0",
|
||||||
|
"react-mixin": "^1.7.0",
|
||||||
"react-redux": "^0.2.2",
|
"react-redux": "^0.2.2",
|
||||||
"redux": "^1.0.0-rc"
|
"redux": "^1.0.0-rc"
|
||||||
}
|
}
|
||||||
|
|
109
src/react/JSONTree/JSONArrayNode.js
Normal file
109
src/react/JSONTree/JSONArrayNode.js
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
import React from 'react';
|
||||||
|
import reactMixin from 'react-mixin';
|
||||||
|
import { ExpandedStateHandlerMixin } from './mixins';
|
||||||
|
import JSONArrow from './JSONArrow';
|
||||||
|
import grabNode from './grab-node';
|
||||||
|
import assign from 'lodash.assign';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 2,
|
||||||
|
paddingRight: 4,
|
||||||
|
letterSpacing: 1,
|
||||||
|
marginLeft: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
display: 'inline-block',
|
||||||
|
color: '#8fa1b2'
|
||||||
|
},
|
||||||
|
span: {
|
||||||
|
color: '#C042DF',
|
||||||
|
fontSize: 12,
|
||||||
|
cursor: 'default'
|
||||||
|
},
|
||||||
|
spanExpanded: {
|
||||||
|
color: '#D7D5D8'
|
||||||
|
},
|
||||||
|
spanType: {
|
||||||
|
marginLeft: 5,
|
||||||
|
marginRight: 5,
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@reactMixin.decorate(ExpandedStateHandlerMixin)
|
||||||
|
export default class JSONArrayNode extends React.Component {
|
||||||
|
defaultProps = {
|
||||||
|
data: [],
|
||||||
|
initialExpanded: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// flag to see if we still need to render our child nodes
|
||||||
|
needsChildNodes = true;
|
||||||
|
|
||||||
|
// cache store for our child nodes
|
||||||
|
renderedChildren = [];
|
||||||
|
|
||||||
|
// cache store for the number of items string we display
|
||||||
|
itemString = false;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
expanded: this.props.initialExpanded,
|
||||||
|
createdChildNodes: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the child nodes for each element in the array. If we have
|
||||||
|
// generated them previously, we return from cache, otherwise we create
|
||||||
|
// them.
|
||||||
|
getChildNodes() {
|
||||||
|
let childNodes = [];
|
||||||
|
if (this.state.expanded && this.needsChildNodes) {
|
||||||
|
this.props.data.forEach((element, idx) => {
|
||||||
|
childNodes.push(grabNode(idx, element));
|
||||||
|
});
|
||||||
|
this.needsChildNodes = false;
|
||||||
|
this.renderedChildren = childNodes;
|
||||||
|
}
|
||||||
|
return this.renderedChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the "n Items" string for this node, generating and
|
||||||
|
// caching it if it hasn't been created yet.
|
||||||
|
getItemString() {
|
||||||
|
if (!this.itemString) {
|
||||||
|
this.itemString = this.props.data.length + ' Item' + (this.props.data.length > 1 ? 's' : '');
|
||||||
|
}
|
||||||
|
return this.itemString;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const childNodes = this.getChildNodes();
|
||||||
|
const childListStyle = {
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
listStyle: 'none',
|
||||||
|
display: (this.state.expanded) ? 'block' : 'none'
|
||||||
|
};
|
||||||
|
let containerStyle = assign({}, styles.base, styles.parentNode);
|
||||||
|
let spanStyle = assign({}, styles.span, this.state.expanded ? styles.spanExpanded : {});
|
||||||
|
return (
|
||||||
|
<li style={containerStyle} onClick={::this.handleClick}>
|
||||||
|
<JSONArrow open={this.state.expanded}/>
|
||||||
|
<label style={styles.label}>{this.props.keyName}:</label>
|
||||||
|
<span style={spanStyle}>
|
||||||
|
<span style={styles.spanType}>[]</span>
|
||||||
|
{this.getItemString()}
|
||||||
|
</span>
|
||||||
|
<ol style={childListStyle}>
|
||||||
|
{childNodes}
|
||||||
|
</ol>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
32
src/react/JSONTree/JSONArrow.js
Normal file
32
src/react/JSONTree/JSONArrow.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import React from 'react';
|
||||||
|
import assign from 'lodash.assign';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
display: 'inline-block',
|
||||||
|
marginLeft: -15,
|
||||||
|
'float': 'left',
|
||||||
|
transition: '150ms',
|
||||||
|
marginTop: 7,
|
||||||
|
WebkitTransition: '150ms',
|
||||||
|
MozTransition: '150ms',
|
||||||
|
borderLeft: '5px solid transparent',
|
||||||
|
borderRight: '5px solid transparent',
|
||||||
|
borderTop: '5px solid #39ace6',
|
||||||
|
WebkitTransform: 'rotateZ(-90deg)',
|
||||||
|
MozTransform: 'rotateZ(-90deg)',
|
||||||
|
transform: 'rotateZ(-90deg)'
|
||||||
|
},
|
||||||
|
open: {
|
||||||
|
WebkitTransform: 'rotateZ(0deg)',
|
||||||
|
MozTransform: 'rotateZ(0deg)',
|
||||||
|
transform: 'rotateZ(0deg)'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class JSONArrow extends React.Component {
|
||||||
|
render() {
|
||||||
|
const style = assign({}, styles.base, this.props.open ? styles.open : {});
|
||||||
|
return <div style={style}/>;
|
||||||
|
}
|
||||||
|
}
|
34
src/react/JSONTree/JSONBooleanNode.js
Normal file
34
src/react/JSONTree/JSONBooleanNode.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import React from 'react';
|
||||||
|
import reactMixin from 'react-mixin';
|
||||||
|
import { SquashClickEventMixin } from './mixins';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 2,
|
||||||
|
paddingRight: 4,
|
||||||
|
letterSpacing: 1,
|
||||||
|
marginLeft: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
display: 'inline-block',
|
||||||
|
marginRight: 5,
|
||||||
|
color: '#8fa1b2'
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
color: '#08c6eE'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@reactMixin.decorate(SquashClickEventMixin)
|
||||||
|
export default class JSONBooleanNode extends React.Component {
|
||||||
|
render() {
|
||||||
|
const truthString = (this.props.value) ? 'true' : 'false';
|
||||||
|
return (
|
||||||
|
<li style={styles.base} onClick={::this.handleClick}>
|
||||||
|
<label style={styles.label}>{this.props.keyName}:</label>
|
||||||
|
<span style={styles.value}>{truthString}</span>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
33
src/react/JSONTree/JSONNullNode.js
Normal file
33
src/react/JSONTree/JSONNullNode.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react';
|
||||||
|
import reactMixin from 'react-mixin';
|
||||||
|
import { SquashClickEventMixin } from './mixins';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 2,
|
||||||
|
paddingRight: 4,
|
||||||
|
letterSpacing: 1,
|
||||||
|
marginLeft: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
display: 'inline-block',
|
||||||
|
marginRight: 5,
|
||||||
|
color: '#8fa1b2'
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
color: '#DF113A'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@reactMixin.decorate(SquashClickEventMixin)
|
||||||
|
export default class JSONNullNode extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<li style={styles.base} onClick={::this.handleClick}>
|
||||||
|
<label style={styles.label}>{this.props.keyName}:</label>
|
||||||
|
<span style={styles.value}>null</span>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
33
src/react/JSONTree/JSONNumberNode.js
Normal file
33
src/react/JSONTree/JSONNumberNode.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react';
|
||||||
|
import reactMixin from 'react-mixin';
|
||||||
|
import { SquashClickEventMixin } from './mixins';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 2,
|
||||||
|
paddingRight: 4,
|
||||||
|
letterSpacing: 1,
|
||||||
|
marginLeft: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
display: 'inline-block',
|
||||||
|
marginRight: 5,
|
||||||
|
color: '#8fa1b2'
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
color: '#0B75F5'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@reactMixin.decorate(SquashClickEventMixin)
|
||||||
|
export default class JSONNumberNode extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<li style={styles.base} onClick={::this.handleClick}>
|
||||||
|
<label style={styles.label}>{this.props.keyName}:</label>
|
||||||
|
<span style={styles.value}>{this.props.value}</span>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
111
src/react/JSONTree/JSONObjectNode.js
Normal file
111
src/react/JSONTree/JSONObjectNode.js
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
import React from 'react';
|
||||||
|
import reactMixin from 'react-mixin';
|
||||||
|
import { ExpandedStateHandlerMixin } from './mixins';
|
||||||
|
import JSONArrow from './JSONArrow';
|
||||||
|
import assign from 'lodash.assign';
|
||||||
|
import grabNode from './grab-node';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 2,
|
||||||
|
paddingRight: 4,
|
||||||
|
letterSpacing: 1,
|
||||||
|
marginLeft: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
display: 'inline-block',
|
||||||
|
color: '#8fa1b2'
|
||||||
|
},
|
||||||
|
span: {
|
||||||
|
color: '#049977',
|
||||||
|
fontSize: 12,
|
||||||
|
cursor: 'default'
|
||||||
|
},
|
||||||
|
spanExpanded: {
|
||||||
|
color: '#D7D5D8'
|
||||||
|
},
|
||||||
|
spanType: {
|
||||||
|
marginLeft: 5,
|
||||||
|
marginRight: 5,
|
||||||
|
fontSize: 16
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@reactMixin.decorate(ExpandedStateHandlerMixin)
|
||||||
|
export default class JSONObjectNode extends React.Component {
|
||||||
|
defaultProps = {
|
||||||
|
data: [],
|
||||||
|
initialExpanded: false
|
||||||
|
};
|
||||||
|
// cache store for the number of items string we display
|
||||||
|
itemString = false;
|
||||||
|
|
||||||
|
// flag to see if we still need to render our child nodes
|
||||||
|
needsChildNodes = true;
|
||||||
|
|
||||||
|
// cache store for our child nodes
|
||||||
|
renderedChildren = [];
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
expanded: this.props.initialExpanded,
|
||||||
|
createdChildNodes: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the child nodes for each element in the object. If we have
|
||||||
|
// generated them previously, we return from cache, otherwise we create
|
||||||
|
// them.
|
||||||
|
getChildNodes() {
|
||||||
|
if (this.state.expanded && this.needsChildNodes) {
|
||||||
|
const obj = this.props.data;
|
||||||
|
let childNodes = [];
|
||||||
|
for (let k in obj) {
|
||||||
|
if (obj.hasOwnProperty(k)) {
|
||||||
|
childNodes.push(grabNode(k, obj[k]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.needsChildNodes = false;
|
||||||
|
this.renderedChildren = childNodes;
|
||||||
|
}
|
||||||
|
return this.renderedChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the "n Items" string for this node, generating and
|
||||||
|
// caching it if it hasn't been created yet.
|
||||||
|
getItemString() {
|
||||||
|
if (!this.itemString) {
|
||||||
|
const len = Object.keys(this.props.data).length;
|
||||||
|
this.itemString = len + ' Item' + (len > 1 ? 's' : '');
|
||||||
|
}
|
||||||
|
return this.itemString;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let childListStyle = {
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
listStyle: 'none',
|
||||||
|
display: (this.state.expanded) ? 'block' : 'none'
|
||||||
|
};
|
||||||
|
let containerStyle = assign({}, styles.base, styles.parentNode);
|
||||||
|
let spanStyle = assign({}, styles.span, this.state.expanded ? styles.spanExpanded : {});
|
||||||
|
return (
|
||||||
|
<li style={containerStyle} onClick={::this.handleClick}>
|
||||||
|
<JSONArrow open={this.state.expanded}/>
|
||||||
|
<label style={styles.label}>{this.props.keyName}:</label>
|
||||||
|
<span style={spanStyle}>
|
||||||
|
<span style={styles.spanType}>{}</span>
|
||||||
|
{this.getItemString()}
|
||||||
|
</span>
|
||||||
|
<ul style={childListStyle}>
|
||||||
|
{this.getChildNodes()}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
33
src/react/JSONTree/JSONStringNode.js
Normal file
33
src/react/JSONTree/JSONStringNode.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react';
|
||||||
|
import reactMixin from 'react-mixin';
|
||||||
|
import { SquashClickEventMixin } from './mixins';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
base: {
|
||||||
|
paddingTop: 2,
|
||||||
|
paddingBottom: 2,
|
||||||
|
paddingRight: 4,
|
||||||
|
letterSpacing: 1,
|
||||||
|
marginLeft: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
display: 'inline-block',
|
||||||
|
marginRight: 5,
|
||||||
|
color: '#8fa1b2'
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
color: '#717c93'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@reactMixin.decorate(SquashClickEventMixin)
|
||||||
|
export default class JSONStringNode extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<li style={styles.base} onClick={::this.handleClick}>
|
||||||
|
<label style={styles.label}>{this.props.keyName}:</label>
|
||||||
|
<span style={styles.value}>{this.props.value}</span>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
28
src/react/JSONTree/grab-node.js
Normal file
28
src/react/JSONTree/grab-node.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import React from 'react';
|
||||||
|
import objType from './obj-type';
|
||||||
|
import JSONObjectNode from './JSONObjectNode';
|
||||||
|
import JSONArrayNode from './JSONArrayNode';
|
||||||
|
import JSONStringNode from './JSONStringNode';
|
||||||
|
import JSONNumberNode from './JSONNumberNode';
|
||||||
|
import JSONBooleanNode from './JSONBooleanNode';
|
||||||
|
import JSONNullNode from './JSONNullNode';
|
||||||
|
|
||||||
|
export default function(key, value) {
|
||||||
|
const nodeType = objType(value);
|
||||||
|
const aKey = key + Date.now();
|
||||||
|
if (nodeType === 'Object') {
|
||||||
|
return <JSONObjectNode data={value} keyName={key} key={aKey} />;
|
||||||
|
} else if (nodeType === 'Array') {
|
||||||
|
return <JSONArrayNode data={value} keyName={key} key={aKey} />;
|
||||||
|
} else if (nodeType === 'String') {
|
||||||
|
return <JSONStringNode keyName={key} value={value} key={aKey} />;
|
||||||
|
} else if (nodeType === 'Number') {
|
||||||
|
return <JSONNumberNode keyName={key} value={value} key={aKey} />;
|
||||||
|
} else if (nodeType === 'Boolean') {
|
||||||
|
return <JSONBooleanNode keyName={key} value={value} key={aKey} />;
|
||||||
|
} else if (nodeType === 'Null') {
|
||||||
|
return <JSONNullNode keyName={key} value={value} key={aKey} />;
|
||||||
|
}
|
||||||
|
console.error('Unknown node type:', nodeType);
|
||||||
|
return false;
|
||||||
|
}
|
50
src/react/JSONTree/index.js
Normal file
50
src/react/JSONTree/index.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// ES6 + inline style port of JSONViewer https://bitbucket.org/davevedder/react-json-viewer/
|
||||||
|
// all credits and original code to the author
|
||||||
|
// Dave Vedder <veddermatic@gmail.com> http://www.eskimospy.com/
|
||||||
|
// port by Daniele Zannotti http://www.github.com/dzannotti <dzannotti@me.com>
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import objectType from './obj-type';
|
||||||
|
import JSONObjectNode from './JSONObjectNode';
|
||||||
|
import JSONArrayNode from './JSONArrayNode';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
tree: {
|
||||||
|
border: 0,
|
||||||
|
padding: 0,
|
||||||
|
margin: 0,
|
||||||
|
fontSize: 14,
|
||||||
|
listStyle: 'none',
|
||||||
|
fontFamily: '"Helvetica Neue", Helvetica, Arial, freesans, sans-serif',
|
||||||
|
MozUserSelect: 'none',
|
||||||
|
WebkitUserSelect: 'none'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class JSONTree extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
data: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.array,
|
||||||
|
React.PropTypes.object
|
||||||
|
]).isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const nodeType = objectType(this.props.data);
|
||||||
|
let rootNode = false;
|
||||||
|
if (nodeType === 'Object') {
|
||||||
|
rootNode = <JSONObjectNode data={this.props.data} keyName="(root)" initialExpanded={true} />;
|
||||||
|
} else if (nodeType === 'Array') {
|
||||||
|
rootNode = <JSONArrayNode data={this.props.data} initialExpanded={true} keyName="(root)" />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ul style={styles.tree}>
|
||||||
|
{rootNode}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
15
src/react/JSONTree/mixins/expanded-state-handler.js
Normal file
15
src/react/JSONTree/mixins/expanded-state-handler.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
export default {
|
||||||
|
handleClick(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
this.setState({
|
||||||
|
expanded: !this.state.expanded
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillReceiveProps() {
|
||||||
|
// resets our caches and flags we need to build child nodes again
|
||||||
|
this.renderedChildren = [];
|
||||||
|
this.itemString = false;
|
||||||
|
this.needsChildNodes = true;
|
||||||
|
}
|
||||||
|
};
|
2
src/react/JSONTree/mixins/index.js
Normal file
2
src/react/JSONTree/mixins/index.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default as SquashClickEventMixin } from './squash-click-event';
|
||||||
|
export { default as ExpandedStateHandlerMixin } from './expanded-state-handler';
|
5
src/react/JSONTree/mixins/squash-click-event.js
Normal file
5
src/react/JSONTree/mixins/squash-click-event.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export default {
|
||||||
|
handleClick(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
};
|
3
src/react/JSONTree/obj-type.js
Normal file
3
src/react/JSONTree/obj-type.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default function(obj) {
|
||||||
|
return Object.prototype.toString.call(obj).slice(8, -1);
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { PropTypes } from 'react';
|
import React, { PropTypes } from 'react';
|
||||||
|
import JSONTree from './JSONTree';
|
||||||
|
|
||||||
function hsvToRgb(h, s, v) {
|
function hsvToRgb(h, s, v) {
|
||||||
const i = Math.floor(h);
|
const i = Math.floor(h);
|
||||||
|
@ -49,7 +50,7 @@ export default class LogMonitorEntry {
|
||||||
let errorText = error;
|
let errorText = error;
|
||||||
if (!errorText) {
|
if (!errorText) {
|
||||||
try {
|
try {
|
||||||
return JSON.stringify(this.props.select(state));
|
return <JSONTree data={this.props.select(state)} />
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorText = 'Error selecting state.';
|
errorText = 'Error selecting state.';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user