[web] eventlog.js -> EventLog.jsx

This commit is contained in:
Jason 2016-06-09 18:40:59 +08:00
parent 1baefcdc99
commit 6c95635cb8
6 changed files with 182 additions and 191 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,41 @@
import React, { PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { toggleEventLogFilter, toggleEventLogVisibility } from '../ducks/eventLog'
import { ToggleButton } from './common'
import EventList from './EventLog/EventList'
EventLog.propTypes = {
filters: PropTypes.object.isRequired,
events: PropTypes.array.isRequired,
onToggleFilter: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired
}
function EventLog({ filters, events, onToggleFilter, onClose }) {
return (
<div className="eventlog">
<div>
Eventlog
<div className="pull-right">
{['debug', 'info', 'web'].map(type => (
<ToggleButton text={type} checked={filters[type]} onToggle={() => onToggleFilter(type)}/>
))}
<i onClick={onClose} className="fa fa-close"></i>
</div>
</div>
<EventList events={events} />
</div>
)
}
export default connect(
state => ({
filters: state.eventLog.filter,
events: state.eventLog.filteredEvents,
}),
dispatch => bindActionCreators({
onClose: toggleEventLogVisibility,
onToggleFilter: toggleEventLogFilter,
}, dispatch)
)(EventLog)

View File

@ -0,0 +1,90 @@
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import shallowEqual from 'shallowequal'
import AutoScroll from '../helpers/AutoScroll'
import { calcVScroll } from '../helpers/VirtualScroll'
class EventLogList extends Component {
static propTypes = {
events: PropTypes.array.isRequired,
rowHeight: PropTypes.number,
}
static defaultProps = {
rowHeight: 18,
}
constructor(props) {
super(props)
this.heights = {}
this.state = { vScroll: calcVScroll() }
this.onViewportUpdate = this.onViewportUpdate.bind(this)
}
componentDidMount() {
window.addEventListener('resize', this.onViewportUpdate)
this.onViewportUpdate()
}
componentWillUnmount() {
window.removeEventListener('resize', this.onViewportUpdate)
}
componentDidUpdate() {
this.onViewportUpdate()
}
onViewportUpdate() {
const viewport = ReactDOM.findDOMNode(this)
const vScroll = calcVScroll({
itemCount: this.props.events.length,
rowHeight: this.props.rowHeight,
viewportTop: viewport.scrollTop,
viewportHeight: viewport.offsetHeight,
itemHeights: this.props.events.map(entry => this.heights[entry.id]),
})
if (!shallowEqual(this.state.vScroll, vScroll)) {
this.setState({vScroll})
}
}
setHeight(id, node) {
if (node && !this.heights[id]) {
const height = node.offsetHeight
if (this.heights[id] !== height) {
this.heights[id] = height
this.onViewportUpdate()
}
}
}
render() {
const { vScroll } = this.state
const { events } = this.props
return (
<pre onScroll={this.onViewportUpdate}>
<div style={{ height: vScroll.paddingTop }}></div>
{events.slice(vScroll.start, vScroll.end).map(event => (
<div key={event.id} ref={node => this.setHeight(event.id, node)}>
<LogIcon event={event}/>
{event.message}
</div>
))}
<div style={{ height: vScroll.paddingBottom }}></div>
</pre>
)
}
}
function LogIcon({ event }) {
const icon = { web: 'html5', debug: 'bug' }[event.level] || 'info'
return <i className={`fa fa-fw fa-${icon}`}></i>
}
export default AutoScroll(EventLogList)

View File

@ -5,7 +5,7 @@ import { connect } from 'react-redux'
import { Splitter } from "./common.js" import { Splitter } from "./common.js"
import { Header, MainMenu } from "./header.js" import { Header, MainMenu } from "./header.js"
import EventLog from "./eventlog.js" import EventLog from "./EventLog"
import Footer from "./Footer" import Footer from "./Footer"
import { SettingsStore } from "../store/store.js" import { SettingsStore } from "../store/store.js"
import { Key } from "../utils.js" import { Key } from "../utils.js"

View File

@ -1,153 +0,0 @@
import React from "react"
import ReactDOM from "react-dom"
import {connect} from 'react-redux'
import shallowEqual from "shallowequal"
import {toggleEventLogFilter, toggleEventLogVisibility} from "../ducks/eventLog"
import AutoScroll from "./helpers/AutoScroll";
import {calcVScroll} from "./helpers/VirtualScroll"
import {ToggleButton} from "./common";
function LogIcon({event}) {
let icon = {web: "html5", debug: "bug"}[event.level] || "info";
return <i className={`fa fa-fw fa-${icon}`}></i>
}
function LogEntry({event, registerHeight}) {
return <div ref={registerHeight}>
<LogIcon event={event}/>
{event.message}
</div>;
}
class EventLogContents extends React.Component {
static defaultProps = {
rowHeight: 18,
};
constructor(props) {
super(props);
this.heights = {};
this.state = {vScroll: calcVScroll()};
this.onViewportUpdate = this.onViewportUpdate.bind(this);
}
componentDidMount() {
window.addEventListener("resize", this.onViewportUpdate);
this.onViewportUpdate();
}
componentWillUnmount() {
window.removeEventListener("resize", this.onViewportUpdate);
}
componentDidUpdate() {
this.onViewportUpdate();
}
onViewportUpdate() {
const viewport = ReactDOM.findDOMNode(this);
const vScroll = calcVScroll({
itemCount: this.props.events.length,
rowHeight: this.props.rowHeight,
viewportTop: viewport.scrollTop,
viewportHeight: viewport.offsetHeight,
itemHeights: this.props.events.map(entry => this.heights[entry.id]),
});
if (!shallowEqual(this.state.vScroll, vScroll)) {
this.setState({vScroll});
}
}
setHeight(id, node) {
if (node && !this.heights[id]) {
const height = node.offsetHeight;
if (this.heights[id] !== height) {
this.heights[id] = height;
this.onViewportUpdate();
}
}
}
render() {
const vScroll = this.state.vScroll;
const events = this.props.events
.slice(vScroll.start, vScroll.end)
.map(event =>
<LogEntry
event={event}
key={event.id}
registerHeight={(node) => this.setHeight(event.id, node)}
/>
);
return (
<pre onScroll={this.onViewportUpdate}>
<div style={{ height: vScroll.paddingTop }}></div>
{events}
<div style={{ height: vScroll.paddingBottom }}></div>
</pre>
);
}
}
EventLogContents = AutoScroll(EventLogContents);
const EventLogContentsContainer = connect(
state => ({
events: state.eventLog.filteredEvents
})
)(EventLogContents);
export const ToggleEventLog = connect(
state => ({
checked: state.eventLog.visible
}),
dispatch => ({
onToggle: () => dispatch(toggleEventLogVisibility())
})
)(ToggleButton);
const ToggleFilter = connect(
(state, ownProps) => ({
checked: state.eventLog.filter[ownProps.text]
}),
(dispatch, ownProps) => ({
onToggle: () => dispatch(toggleEventLogFilter(ownProps.text))
})
)(ToggleButton);
const EventLog = ({close}) =>
<div className="eventlog">
<div>
Eventlog
<div className="pull-right">
<ToggleFilter text="debug"/>
<ToggleFilter text="info"/>
<ToggleFilter text="web"/>
<i onClick={close} className="fa fa-close"></i>
</div>
</div>
<EventLogContentsContainer/>
</div>;
EventLog.propTypes = {
close: React.PropTypes.func.isRequired
};
const EventLogContainer = connect(
undefined,
dispatch => ({
close: () => dispatch(toggleEventLogVisibility())
})
)(EventLog);
export default EventLogContainer;

View File

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { bindActionCreators } from 'redux'
import $ from "jquery"; import $ from "jquery";
import {connect} from 'react-redux' import {connect} from 'react-redux'
@ -9,7 +10,16 @@ import {ToggleInputButton, ToggleButton} from "./common.js";
import {SettingsActions, FlowActions} from "../actions.js"; import {SettingsActions, FlowActions} from "../actions.js";
import {Query} from "../actions.js"; import {Query} from "../actions.js";
import {SettingsState} from "./common.js"; import {SettingsState} from "./common.js";
import {ToggleEventLog} from "./eventlog" import { toggleEventLogVisibility } from '../ducks/eventLog'
const ToggleEventLog = connect(
state => ({
checked: state.eventLog.visible
}),
dispatch => bindActionCreators({
onToggle: toggleEventLogVisibility,
}, dispatch)
)(ToggleButton)
var FilterDocs = React.createClass({ var FilterDocs = React.createClass({
statics: { statics: {