[web] eliminate Router mixin

This commit is contained in:
Jason 2016-05-24 23:08:21 +08:00
parent c160a47e51
commit 61453aa847
6 changed files with 66 additions and 71 deletions

View File

@ -2,32 +2,6 @@ import React from "react"
import ReactDOM from "react-dom" import ReactDOM from "react-dom"
import _ from "lodash" import _ from "lodash"
export var Router = {
contextTypes: {
location: React.PropTypes.object,
router: React.PropTypes.object.isRequired
},
updateLocation: function (pathname, queryUpdate) {
if (pathname === undefined) {
pathname = this.context.location.pathname;
}
var query = this.context.location.query;
if (queryUpdate !== undefined) {
for (var i in queryUpdate) {
if (queryUpdate.hasOwnProperty(i)) {
query[i] = queryUpdate[i] || undefined; //falsey values shall be removed.
}
}
}
this.context.router.replace({pathname, query});
},
getQuery: function () {
// For whatever reason, react-router always returns the same object, which makes comparing
// the current props with nextProps impossible. As a workaround, we just clone the query object.
return _.clone(this.context.location.query);
}
};
export var Splitter = React.createClass({ export var Splitter = React.createClass({
getDefaultProps: function () { getDefaultProps: function () {
return { return {

View File

@ -1,7 +1,6 @@
import React from "react" import React from "react"
import ReactDOM from "react-dom" import ReactDOM from "react-dom"
import shallowEqual from "shallowequal" import shallowEqual from "shallowequal"
import {Router} from "./common.js"
import {Query} from "../actions.js" import {Query} from "../actions.js"
import AutoScroll from "./helpers/AutoScroll"; import AutoScroll from "./helpers/AutoScroll";
import {calcVScroll} from "./helpers/VirtualScroll" import {calcVScroll} from "./helpers/VirtualScroll"
@ -144,7 +143,6 @@ function ToggleFilter ({ name, active, toggleLevel }) {
const AutoScrollEventLog = AutoScroll(EventLogContents); const AutoScrollEventLog = AutoScroll(EventLogContents);
var EventLog = React.createClass({ var EventLog = React.createClass({
mixins: [Router],
getInitialState() { getInitialState() {
return { return {
filter: { filter: {
@ -157,7 +155,7 @@ var EventLog = React.createClass({
close() { close() {
var d = {}; var d = {};
d[Query.SHOW_EVENTLOG] = undefined; d[Query.SHOW_EVENTLOG] = undefined;
this.updateLocation(undefined, d); this.props.updateLocation(undefined, d);
}, },
toggleLevel(level) { toggleLevel(level) {
var filter = _.extend({}, this.state.filter); var filter = _.extend({}, this.state.filter);

View File

@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import {Router, StickyHeadMixin} from "../common.js"
import Nav from "./nav.js"; import Nav from "./nav.js";
import {Request, Response, Error} from "./messages.js"; import {Request, Response, Error} from "./messages.js";
import Details from "./details.js"; import Details from "./details.js";
@ -15,7 +14,6 @@ var allTabs = {
}; };
var FlowView = React.createClass({ var FlowView = React.createClass({
mixins: [StickyHeadMixin, Router],
getInitialState: function () { getInitialState: function () {
return { return {
prompt: false prompt: false
@ -39,7 +37,7 @@ var FlowView = React.createClass({
this.selectTab(tabs[nextIndex]); this.selectTab(tabs[nextIndex]);
}, },
selectTab: function (panel) { selectTab: function (panel) {
this.updateLocation(`/flows/${this.props.flow.id}/${panel}`); this.props.updateLocation(`/flows/${this.props.flow.id}/${panel}`);
}, },
promptEdit: function () { promptEdit: function () {
var options; var options;

View File

@ -4,7 +4,7 @@ import $ from "jquery";
import Filt from "../filt/filt.js"; import Filt from "../filt/filt.js";
import {Key} from "../utils.js"; import {Key} from "../utils.js";
import {Router, ToggleComponent} from "./common.js"; import {ToggleComponent} 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";
@ -161,7 +161,6 @@ var FilterInput = React.createClass({
}); });
export var MainMenu = React.createClass({ export var MainMenu = React.createClass({
mixins: [Router],
propTypes: { propTypes: {
settings: React.PropTypes.object.isRequired, settings: React.PropTypes.object.isRequired,
}, },
@ -172,19 +171,19 @@ export var MainMenu = React.createClass({
onSearchChange: function (val) { onSearchChange: function (val) {
var d = {}; var d = {};
d[Query.SEARCH] = val; d[Query.SEARCH] = val;
this.updateLocation(undefined, d); this.props.updateLocation(undefined, d);
}, },
onHighlightChange: function (val) { onHighlightChange: function (val) {
var d = {}; var d = {};
d[Query.HIGHLIGHT] = val; d[Query.HIGHLIGHT] = val;
this.updateLocation(undefined, d); this.props.updateLocation(undefined, d);
}, },
onInterceptChange: function (val) { onInterceptChange: function (val) {
SettingsActions.update({intercept: val}); SettingsActions.update({intercept: val});
}, },
render: function () { render: function () {
var search = this.getQuery()[Query.SEARCH] || ""; var search = this.props.query[Query.SEARCH] || "";
var highlight = this.getQuery()[Query.HIGHLIGHT] || ""; var highlight = this.props.query[Query.HIGHLIGHT] || "";
var intercept = this.props.settings.intercept || ""; var intercept = this.props.settings.intercept || "";
return ( return (
@ -224,20 +223,19 @@ var ViewMenu = React.createClass({
title: "View", title: "View",
route: "flows" route: "flows"
}, },
mixins: [Router],
toggleEventLog: function () { toggleEventLog: function () {
var d = {}; var d = {};
if (this.getQuery()[Query.SHOW_EVENTLOG]) { if (this.props.query[Query.SHOW_EVENTLOG]) {
d[Query.SHOW_EVENTLOG] = undefined; d[Query.SHOW_EVENTLOG] = undefined;
} else { } else {
d[Query.SHOW_EVENTLOG] = "t"; // any non-false value will do it, keep it short d[Query.SHOW_EVENTLOG] = "t"; // any non-false value will do it, keep it short
} }
this.updateLocation(undefined, d); this.props.updateLocation(undefined, d);
console.log('toggleevent'); console.log('toggleevent');
}, },
render: function () { render: function () {
var showEventLog = this.getQuery()[Query.SHOW_EVENTLOG]; var showEventLog = this.props.query[Query.SHOW_EVENTLOG];
return ( return (
<div> <div>
<ToggleComponent <ToggleComponent
@ -391,7 +389,6 @@ var header_entries = [MainMenu, ViewMenu, OptionMenu /*, ReportsMenu */];
export var Header = React.createClass({ export var Header = React.createClass({
mixins: [Router],
propTypes: { propTypes: {
settings: React.PropTypes.object.isRequired, settings: React.PropTypes.object.isRequired,
}, },
@ -402,7 +399,7 @@ export var Header = React.createClass({
}, },
handleClick: function (active, e) { handleClick: function (active, e) {
e.preventDefault(); e.preventDefault();
this.updateLocation(active.route); this.props.updateLocation(active.route);
this.setState({active: active}); this.setState({active: active});
}, },
render: function () { render: function () {
@ -430,7 +427,12 @@ export var Header = React.createClass({
{header} {header}
</nav> </nav>
<div className="menu"> <div className="menu">
<this.state.active ref="active" settings={this.props.settings}/> <this.state.active
ref="active"
settings={this.props.settings}
updateLocation={this.props.updateLocation}
query={this.props.query}
/>
</div> </div>
</header> </header>
); );

View File

@ -5,12 +5,11 @@ import {Query} from "../actions.js";
import {Key} from "../utils.js"; import {Key} from "../utils.js";
import {StoreView} from "../store/view.js"; import {StoreView} from "../store/view.js";
import Filt from "../filt/filt.js"; import Filt from "../filt/filt.js";
import { Router, Splitter} from "./common.js" import {Splitter} from "./common.js"
import FlowTable from "./flowtable.js"; import FlowTable from "./flowtable.js";
import FlowView from "./flowview/index.js"; import FlowView from "./flowview/index.js";
var MainView = React.createClass({ var MainView = React.createClass({
mixins: [Router],
contextTypes: { contextTypes: {
flowStore: React.PropTypes.object.isRequired, flowStore: React.PropTypes.object.isRequired,
}, },
@ -41,9 +40,9 @@ var MainView = React.createClass({
}, },
getViewFilt: function () { getViewFilt: function () {
try { try {
var filtStr = this.getQuery()[Query.SEARCH]; var filtStr = this.props.query[Query.SEARCH];
var filt = filtStr ? Filt.parse(filtStr) : () => true; var filt = filtStr ? Filt.parse(filtStr) : () => true;
var highlightStr = this.getQuery()[Query.HIGHLIGHT]; var highlightStr = this.props.query[Query.HIGHLIGHT];
var highlight = highlightStr ? Filt.parse(highlightStr) : () => false; var highlight = highlightStr ? Filt.parse(highlightStr) : () => false;
} catch (e) { } catch (e) {
console.error("Error when processing filter: " + e); console.error("Error when processing filter: " + e);
@ -94,10 +93,10 @@ var MainView = React.createClass({
selectFlow: function (flow) { selectFlow: function (flow) {
if (flow) { if (flow) {
var tab = this.props.routeParams.detailTab || "request"; var tab = this.props.routeParams.detailTab || "request";
this.updateLocation(`/flows/${flow.id}/${tab}`); this.props.updateLocation(`/flows/${flow.id}/${tab}`);
this.refs.flowTable.scrollIntoView(flow); this.refs.flowTable.scrollIntoView(flow);
} else { } else {
this.updateLocation("/flows"); this.props.updateLocation("/flows");
} }
}, },
selectFlowRelative: function (shift) { selectFlowRelative: function (shift) {
@ -225,6 +224,8 @@ var MainView = React.createClass({
key="flowDetails" key="flowDetails"
ref="flowDetails" ref="flowDetails"
tab={this.props.routeParams.detailTab} tab={this.props.routeParams.detailTab}
query={this.props.query}
updateLocation={this.props.updateLocation}
flow={selected}/> flow={selected}/>
]; ];
} else { } else {

View File

@ -2,7 +2,7 @@ import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import _ from "lodash"; import _ from "lodash";
import {Router, Splitter} from "./common.js" import {Splitter} from "./common.js"
import MainView from "./mainview.js"; import MainView from "./mainview.js";
import Footer from "./footer.js"; import Footer from "./footer.js";
import {Header, MainMenu} from "./header.js"; import {Header, MainMenu} from "./header.js";
@ -21,13 +21,35 @@ var Reports = React.createClass({
var ProxyAppMain = React.createClass({ var ProxyAppMain = React.createClass({
mixins: [Router],
childContextTypes: { childContextTypes: {
flowStore: React.PropTypes.object.isRequired, flowStore: React.PropTypes.object.isRequired,
eventStore: React.PropTypes.object.isRequired, eventStore: React.PropTypes.object.isRequired,
returnFocus: React.PropTypes.func.isRequired, returnFocus: React.PropTypes.func.isRequired,
location: React.PropTypes.object.isRequired, location: React.PropTypes.object.isRequired,
}, },
contextTypes: {
location: React.PropTypes.object,
router: React.PropTypes.object.isRequired
},
updateLocation: function (pathname, queryUpdate) {
if (pathname === undefined) {
pathname = this.context.location.pathname;
}
var query = this.context.location.query;
if (queryUpdate !== undefined) {
for (var i in queryUpdate) {
if (queryUpdate.hasOwnProperty(i)) {
query[i] = queryUpdate[i] || undefined; //falsey values shall be removed.
}
}
}
this.context.router.replace({pathname, query});
},
getQuery: function () {
// For whatever reason, react-router always returns the same object, which makes comparing
// the current props with nextProps impossible. As a workaround, we just clone the query object.
return _.clone(this.context.location.query);
},
componentDidMount: function () { componentDidMount: function () {
this.focus(); this.focus();
this.settingsStore.addListener("recalculate", this.onSettingsChange); this.settingsStore.addListener("recalculate", this.onSettingsChange);
@ -97,23 +119,23 @@ var ProxyAppMain = React.createClass({
e.preventDefault(); e.preventDefault();
}, },
render: function () { render: function () {
var query = this.getQuery();
var eventlog; var eventlog;
if (this.props.location.query[Query.SHOW_EVENTLOG]) { if (this.props.location.query[Query.SHOW_EVENTLOG]) {
eventlog = [ eventlog = [
<Splitter key="splitter" axis="y"/>, <Splitter key="splitter" axis="y"/>,
<EventLog key="eventlog"/> <EventLog key="eventlog" updateLocation={this.updateLocation}/>
]; ];
} else { } else {
eventlog = null; eventlog = null;
} }
var children = React.cloneElement(
this.props.children,
{ ref: "view", location: this.props.location }
);
return ( return (
<div id="container" tabIndex="0" onKeyDown={this.onKeydown}> <div id="container" tabIndex="0" onKeyDown={this.onKeydown}>
<Header ref="header" settings={this.state.settings}/> <Header ref="header" settings={this.state.settings} updateLocation={this.updateLocation} query={query} />
{children} {React.cloneElement(
this.props.children,
{ ref: "view", location: this.props.location , updateLocation: this.updateLocation, query }
)}
{eventlog} {eventlog}
<Footer settings={this.state.settings}/> <Footer settings={this.state.settings}/>
</div> </div>
@ -125,12 +147,12 @@ var ProxyAppMain = React.createClass({
import { Route, Router as ReactRouter, hashHistory, Redirect} from "react-router"; import { Route, Router as ReactRouter, hashHistory, Redirect} from "react-router";
export var app = ( export var app = (
<ReactRouter history={hashHistory}> <ReactRouter history={hashHistory}>
<Redirect from="/" to="/flows" /> <Redirect from="/" to="/flows" />
<Route path="/" component={ProxyAppMain}> <Route path="/" component={ProxyAppMain}>
<Route path="flows" component={MainView}/> <Route path="flows" component={MainView}/>
<Route path="flows/:flowId/:detailTab" component={MainView}/> <Route path="flows/:flowId/:detailTab" component={MainView}/>
<Route path="reports" component={Reports}/> <Route path="reports" component={Reports}/>
</Route> </Route>
</ReactRouter> </ReactRouter>
); );