diff options
author | Maximilian Hils <git@maximilianhils.com> | 2016-06-02 23:45:36 -0700 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2016-06-02 23:45:36 -0700 |
commit | e31aa39fc28645fe27646b1e6c6f7e876280ed69 (patch) | |
tree | 8536a77b278d8182205e8ba757e1e1f00ac67d76 /web/src/js/components/eventlog.js | |
parent | 65fde7f5547f179c80d5858f1ab69583b63fd099 (diff) | |
parent | 5321f15defcef641bf5b7ba39e5c9057d562c5f8 (diff) | |
download | mitmproxy-e31aa39fc28645fe27646b1e6c6f7e876280ed69.tar.gz mitmproxy-e31aa39fc28645fe27646b1e6c6f7e876280ed69.tar.bz2 mitmproxy-e31aa39fc28645fe27646b1e6c6f7e876280ed69.zip |
Merge branch 'redux-ducks'
Diffstat (limited to 'web/src/js/components/eventlog.js')
-rw-r--r-- | web/src/js/components/eventlog.js | 206 |
1 files changed, 88 insertions, 118 deletions
diff --git a/web/src/js/components/eventlog.js b/web/src/js/components/eventlog.js index 6e4f9096..95889a66 100644 --- a/web/src/js/components/eventlog.js +++ b/web/src/js/components/eventlog.js @@ -1,86 +1,72 @@ import React from "react" import ReactDOM from "react-dom" +import {connect} from 'react-redux' import shallowEqual from "shallowequal" -import {Query} from "../actions.js" +import {toggleEventLogFilter, toggleEventLogVisibility} from "../ducks/eventLog" import AutoScroll from "./helpers/AutoScroll"; import {calcVScroll} from "./helpers/VirtualScroll" -import {StoreView} from "../store/view.js" -import _ from "lodash" +import {ToggleButton} from "./common"; -class EventLogContents extends React.Component { +function LogIcon({event}) { + let icon = {web: "html5", debug: "bug"}[event.level] || "info"; + return <i className={`fa fa-fw fa-${icon}`}></i> +} - static contextTypes = { - eventStore: React.PropTypes.object.isRequired, - }; +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, context) { - super(props, context); - - this.view = new StoreView( - this.context.eventStore, - entry => this.props.filter[entry.level] - ); + constructor(props) { + super(props); this.heights = {}; - this.state = { entries: this.view.list, vScroll: calcVScroll() }; + this.state = {vScroll: calcVScroll()}; - this.onChange = this.onChange.bind(this); this.onViewportUpdate = this.onViewportUpdate.bind(this); } componentDidMount() { window.addEventListener("resize", this.onViewportUpdate); - this.view.addListener("add", this.onChange); - this.view.addListener("recalculate", this.onChange); this.onViewportUpdate(); } componentWillUnmount() { window.removeEventListener("resize", this.onViewportUpdate); - this.view.removeListener("add", this.onChange); - this.view.removeListener("recalculate", this.onChange); - this.view.close(); } componentDidUpdate() { this.onViewportUpdate(); } - componentWillReceiveProps(nextProps) { - if (nextProps.filter !== this.props.filter) { - this.view.recalculate( - entry => nextProps.filter[entry.level] - ); - } - } - onViewportUpdate() { const viewport = ReactDOM.findDOMNode(this); const vScroll = calcVScroll({ - itemCount: this.state.entries.length, + itemCount: this.props.events.length, rowHeight: this.props.rowHeight, viewportTop: viewport.scrollTop, viewportHeight: viewport.offsetHeight, - itemHeights: this.state.entries.map(entry => this.heights[entry.id]), + itemHeights: this.props.events.map(entry => this.heights[entry.id]), }); if (!shallowEqual(this.state.vScroll, vScroll)) { - this.setState({ vScroll }); + this.setState({vScroll}); } } - onChange() { - this.setState({ entries: this.view.list }); - } - - setHeight(id, ref) { - if (ref && !this.heights[id]) { - const height = ReactDOM.findDOMNode(ref).offsetHeight; + setHeight(id, node) { + console.log("setHeight", id, node); + if (node && !this.heights[id]) { + const height = node.offsetHeight; if (this.heights[id] !== height) { this.heights[id] = height; this.onViewportUpdate(); @@ -88,97 +74,81 @@ class EventLogContents extends React.Component { } } - getIcon(level) { - return { web: "html5", debug: "bug" }[level] || "info"; - } - render() { const vScroll = this.state.vScroll; - const entries = this.state.entries.slice(vScroll.start, vScroll.end); + 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> - {entries.map((entry, index) => ( - <div key={entry.id} ref={this.setHeight.bind(this, entry.id)}> - <i className={`fa fa-fw fa-${this.getIcon(entry.level)}`}></i> - {entry.message} - </div> - ))} + {events} <div style={{ height: vScroll.paddingBottom }}></div> </pre> ); } } -ToggleFilter.propTypes = { - name: React.PropTypes.string.isRequired, - toggleLevel: React.PropTypes.func.isRequired, - active: React.PropTypes.bool, -}; - -function ToggleFilter ({ name, active, toggleLevel }) { - let className = "label "; - if (active) { - className += "label-primary"; - } else { - className += "label-default"; - } - - function onClick(event) { - event.preventDefault(); - toggleLevel(name); - } - - return ( - <a - href="#" - className={className} - onClick={onClick}> - {name} - </a> - ); -} +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>; -const AutoScrollEventLog = AutoScroll(EventLogContents); +EventLog.propTypes = { + close: React.PropTypes.func.isRequired +}; -var EventLog = React.createClass({ - getInitialState() { - return { - filter: { - "debug": false, - "info": true, - "web": true - } - }; - }, - close() { - var d = {}; - d[Query.SHOW_EVENTLOG] = undefined; - this.props.updateLocation(undefined, d); - }, - toggleLevel(level) { - var filter = _.extend({}, this.state.filter); - filter[level] = !filter[level]; - this.setState({filter: filter}); - }, - render() { - return ( - <div className="eventlog"> - <div> - Eventlog - <div className="pull-right"> - <ToggleFilter name="debug" active={this.state.filter.debug} toggleLevel={this.toggleLevel}/> - <ToggleFilter name="info" active={this.state.filter.info} toggleLevel={this.toggleLevel}/> - <ToggleFilter name="web" active={this.state.filter.web} toggleLevel={this.toggleLevel}/> - <i onClick={this.close} className="fa fa-close"></i> - </div> - - </div> - <AutoScrollEventLog filter={this.state.filter}/> - </div> - ); - } -}); +const EventLogContainer = connect( + undefined, + dispatch => ({ + close: () => dispatch(toggleEventLogVisibility()) + }) +)(EventLog); -export default EventLog; +export default EventLogContainer; |