2016-01-22 08:22:11 -06:00
|
|
|
import React from 'react'
|
2016-04-09 05:09:53 -05:00
|
|
|
import Influx from 'react-influx'
|
2016-01-22 08:22:11 -06:00
|
|
|
import {ifcat} from '../../libs/utils'
|
2016-04-09 05:09:53 -05:00
|
|
|
import EntryStore from '../../stores/EntryStore';
|
|
|
|
import Dispatcher from '../../dispatchers/Dispatcher';
|
2016-01-22 08:22:11 -06:00
|
|
|
import ObjectInspector from 'react-object-inspector';
|
|
|
|
import _ from 'underscore'
|
2016-04-09 05:09:53 -05:00
|
|
|
import Checkbox from './Checkbox.jsx';
|
2016-01-22 08:22:11 -06:00
|
|
|
|
2016-04-09 05:09:53 -05:00
|
|
|
export default class Entry extends Influx.Component {
|
2016-01-22 08:22:11 -06:00
|
|
|
constructor(...args) {
|
|
|
|
super(...args);
|
2016-04-09 05:09:53 -05:00
|
|
|
this.state = {visible: false, width: window.innerWidth, selected: EntryStore.isSelected(this.props.entry._id)};
|
2016-01-22 08:22:11 -06:00
|
|
|
this._onWindowResize = this._onWindowResize.bind(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
2016-04-09 05:09:53 -05:00
|
|
|
super.componentWillUnmount();
|
|
|
|
|
|
|
|
window.removeEventListener("resize", this._onWindowResize);
|
2016-01-22 08:22:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
2016-04-09 05:09:53 -05:00
|
|
|
super.componentDidMount();
|
|
|
|
|
2016-01-22 08:22:11 -06:00
|
|
|
window.addEventListener("resize", this._onWindowResize, false)
|
|
|
|
}
|
|
|
|
|
2016-04-09 05:09:53 -05:00
|
|
|
componentWillReceiveProps(nextProps) {
|
|
|
|
this.setState({selected: EntryStore.isSelected(nextProps.entry._id)});
|
|
|
|
}
|
|
|
|
|
2016-01-22 08:22:11 -06:00
|
|
|
_onWindowResize() {
|
|
|
|
this.setState({width: window.innerWidth});
|
|
|
|
}
|
|
|
|
|
2016-04-09 05:09:53 -05:00
|
|
|
getListeners() {
|
|
|
|
return [
|
|
|
|
[EntryStore, EntryStore.Events.UPDATED_SELECTED, this._onUpdateSelected]
|
|
|
|
]
|
|
|
|
}
|
|
|
|
|
|
|
|
_onUpdateSelected() {
|
|
|
|
this.setState({selected: EntryStore.isSelected(this.props.entry._id)});
|
|
|
|
}
|
|
|
|
|
2016-01-22 08:22:11 -06:00
|
|
|
_inspectPre(persistent) {
|
2016-04-09 05:09:53 -05:00
|
|
|
return <span className="pre">{`${persistent.app}-${persistent.id}`}</span>;
|
2016-01-22 08:22:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
_inspectTags(tags, persistent) {
|
|
|
|
return (tags || []).map((t, i) => {
|
|
|
|
return <span key={i} className={ifcat('tag',{persistent: persistent})}>{t}</span>;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_inspectExpose(expose) {
|
|
|
|
return <span className={ifcat('tag',{
|
|
|
|
fill: true,
|
2016-04-09 05:09:53 -05:00
|
|
|
bgRed: expose == 'error',
|
2016-01-22 08:22:11 -06:00
|
|
|
//bgBlue: expose == 'express',
|
|
|
|
//bgGreen: expose == 'log'
|
|
|
|
})}>{expose}</span>;
|
|
|
|
}
|
|
|
|
|
|
|
|
_handleClick() {
|
|
|
|
this.setState({visible: !this.state.visible});
|
|
|
|
}
|
|
|
|
|
|
|
|
_inspectMetrics(entry) {
|
|
|
|
return (
|
2016-04-09 05:09:53 -05:00
|
|
|
<span>
|
2016-01-22 08:22:11 -06:00
|
|
|
{_.map(entry.transient.metrics, (value, key)=> {
|
|
|
|
value = typeof value === 'number' ? value.toFixed(3) : value;
|
|
|
|
return (
|
2016-04-09 05:09:53 -05:00
|
|
|
<span key={key}>
|
2016-01-22 08:22:11 -06:00
|
|
|
<span className='tag fill bgPurple'>{key}</span>
|
|
|
|
<span className='tag green'>{value}</span>
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</span>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
_inspectRaw(preSpace) {
|
|
|
|
if (!this.state.visible) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const {entry} = this.props;
|
|
|
|
return (
|
2016-04-09 05:09:53 -05:00
|
|
|
<div className="raw inspector flex">
|
|
|
|
<span className="line" dangerouslySetInnerHTML={{__html:preSpace}}/>
|
|
|
|
<div className="scroll scroll-x">
|
|
|
|
<ObjectInspector data={ entry } initialExpandedPaths={["*"]}/>
|
2016-01-22 08:22:11 -06:00
|
|
|
</div>
|
2016-04-09 05:09:53 -05:00
|
|
|
</div>
|
2016-01-22 08:22:11 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
_inspectArgs(entry) {
|
|
|
|
let args = entry.args;
|
|
|
|
|
|
|
|
if (entry.expose === 'express') {
|
|
|
|
const express = entry.args[0];
|
|
|
|
args = (
|
2016-04-09 05:09:53 -05:00
|
|
|
<span>
|
2016-01-22 08:22:11 -06:00
|
|
|
<span className='tag fill bgGreen'>{express.method}</span>
|
2016-01-23 00:55:46 -06:00
|
|
|
<span className='gray'>{express.originalUrl}</span>
|
2016-01-22 08:22:11 -06:00
|
|
|
<span className="green" style={{margin:'0 4px'}}>{express.status} - {express.contentLength} </span>
|
|
|
|
<span className='darkGray'>{Number(entry.args[0].duration).toFixed(3)}ms</span>
|
|
|
|
</span>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Array.isArray(args)) return <span className="arg-string">{args}</span>;
|
|
|
|
return args.map((data, i) => {
|
|
|
|
if (typeof data === 'object' || typeof data === 'function') {
|
|
|
|
return <ObjectInspector key={i} data={data}/>;
|
|
|
|
}
|
|
|
|
|
|
|
|
return <span key={i} className="arg-string">{data}</span>;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
_inspectCallSite(entry) {
|
|
|
|
let site = entry.transient.callsite;
|
2016-04-09 05:09:53 -05:00
|
|
|
let tooltip;
|
2016-01-22 08:22:11 -06:00
|
|
|
if (entry.expose === 'express') {
|
|
|
|
const express = entry.args[0];
|
2016-04-09 05:09:53 -05:00
|
|
|
site = `${express.ip}`;
|
|
|
|
tooltip = 'remote ip';
|
2016-01-22 08:22:11 -06:00
|
|
|
} else {
|
|
|
|
site = `${site.file.substr(site.file.lastIndexOf('/') + 1)}:${site.line}`;
|
2016-04-09 05:09:53 -05:00
|
|
|
tooltip = site.func || 'anonymous';
|
2016-01-22 08:22:11 -06:00
|
|
|
}
|
2016-04-09 05:09:53 -05:00
|
|
|
return (
|
|
|
|
<span className={ifcat('tag tooltip',{fill: true})}>
|
|
|
|
{site}
|
|
|
|
<span className='tooltiptext tooltip-top'>{tooltip}</span>
|
|
|
|
</span>
|
|
|
|
);
|
2016-01-22 08:22:11 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
let {entry} = this.props;
|
|
|
|
|
|
|
|
const lineNumber = new Array(this.props.maxLineChars - String(this.props.line).length).join(' ') + this.props.line;
|
|
|
|
const preSpace = new Array(this.props.maxLineChars).join(' ');
|
2016-04-09 05:09:53 -05:00
|
|
|
const isPushed = entry._pushed;
|
2016-01-22 08:22:11 -06:00
|
|
|
|
|
|
|
if (this.state.width < 1280) {
|
|
|
|
return (
|
|
|
|
<div className="entry">
|
2016-04-09 05:09:53 -05:00
|
|
|
<div className="pretty flex">
|
2016-01-22 08:22:11 -06:00
|
|
|
<span className="line" dangerouslySetInnerHTML={{__html:lineNumber}}/>
|
2016-04-09 05:09:53 -05:00
|
|
|
<Checkbox type='checkbox' checked={this.state.selected} style={{marginBottom: 4}}
|
|
|
|
onChange={e => Dispatcher.emit(Dispatcher.Events.REQUEST_SELECT_ENTRY, entry._id, e.target.checked)}/>
|
2016-01-22 08:22:11 -06:00
|
|
|
<span>{this._inspectPre(entry.persistent)}</span>
|
|
|
|
<span>{this._inspectTags(entry.persistent.tags, true)}</span>
|
2016-04-09 05:09:53 -05:00
|
|
|
<span>{this._inspectTags(entry.transient.tags, false, isPushed)}</span>
|
2016-01-22 08:22:11 -06:00
|
|
|
<span>{this._inspectMetrics(entry)}</span>
|
2016-04-09 05:09:53 -05:00
|
|
|
<span className="box"/>
|
2016-01-22 08:22:11 -06:00
|
|
|
<span>{this._inspectExpose(entry.expose)}</span>
|
|
|
|
<span>{this._inspectCallSite(entry)}</span>
|
2016-04-09 05:09:53 -05:00
|
|
|
{ isPushed ? <span><span className='tag fill new-entry'>new</span></span> : null }
|
2016-01-22 08:22:11 -06:00
|
|
|
<span className={ifcat("expand-right gray", {rotate:this.state.visible})}
|
|
|
|
onClick={this._handleClick.bind(this)}>◀</span>
|
|
|
|
</div>
|
2016-04-09 05:09:53 -05:00
|
|
|
<div className="flex">
|
|
|
|
<span className="line" dangerouslySetInnerHTML={{__html:preSpace}}/>
|
|
|
|
<span className="white medium inspector box scroll scroll-x"
|
|
|
|
style={{marginLeft: 22}}>{this._inspectArgs(entry)}</span>
|
|
|
|
</div>
|
|
|
|
{ this._inspectRaw(preSpace) }
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="entry">
|
|
|
|
<div className="flex">
|
|
|
|
<span className="line" dangerouslySetInnerHTML={{__html:lineNumber}}/>
|
|
|
|
<Checkbox type='checkbox' checked={this.state.selected}
|
|
|
|
onChange={e => Dispatcher.emit(Dispatcher.Events.REQUEST_SELECT_ENTRY, entry._id, e.target.checked)}/>
|
|
|
|
<span>{this._inspectPre(entry.persistent)}</span>
|
|
|
|
<span>{this._inspectTags(entry.persistent.tags, true)}</span>
|
|
|
|
<span>{this._inspectTags(entry.transient.tags, false, isPushed)}</span>
|
|
|
|
<span>{this._inspectMetrics(entry)}</span>
|
|
|
|
<span className="white medium inspector box scroll scroll-x">{this._inspectArgs(entry)}</span>
|
|
|
|
<span>{this._inspectExpose(entry.expose)}</span>
|
|
|
|
<span>{this._inspectCallSite(entry)}</span>
|
|
|
|
{ isPushed ? <span><span className='tag fill new-entry'>new</span></span> : null }
|
|
|
|
<span className={ifcat("expand-right gray", {rotate:this.state.visible})}
|
|
|
|
onClick={this._handleClick.bind(this)}>◀</span>
|
2016-01-22 08:22:11 -06:00
|
|
|
</div>
|
2016-04-09 05:09:53 -05:00
|
|
|
{this._inspectRaw(preSpace) }
|
|
|
|
</div>
|
2016-01-22 08:22:11 -06:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|