[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 _ 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({
getDefaultProps: function () {
return {
@ -143,4 +117,4 @@ export const ToggleComponent = (props) =>
ToggleComponent.propTypes = {
name: React.PropTypes.string.isRequired,
onToggleChanged: React.PropTypes.func.isRequired
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ import React from "react";
import ReactDOM from "react-dom";
import _ from "lodash";
import {Router, Splitter} from "./common.js"
import {Splitter} from "./common.js"
import MainView from "./mainview.js";
import Footer from "./footer.js";
import {Header, MainMenu} from "./header.js";
@ -21,13 +21,35 @@ var Reports = React.createClass({
var ProxyAppMain = React.createClass({
mixins: [Router],
childContextTypes: {
flowStore: React.PropTypes.object.isRequired,
eventStore: React.PropTypes.object.isRequired,
returnFocus: React.PropTypes.func.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 () {
this.focus();
this.settingsStore.addListener("recalculate", this.onSettingsChange);
@ -97,23 +119,23 @@ var ProxyAppMain = React.createClass({
e.preventDefault();
},
render: function () {
var query = this.getQuery();
var eventlog;
if (this.props.location.query[Query.SHOW_EVENTLOG]) {
eventlog = [
<Splitter key="splitter" axis="y"/>,
<EventLog key="eventlog"/>
<EventLog key="eventlog" updateLocation={this.updateLocation}/>
];
} else {
eventlog = null;
}
var children = React.cloneElement(
this.props.children,
{ ref: "view", location: this.props.location }
);
return (
<div id="container" tabIndex="0" onKeyDown={this.onKeydown}>
<Header ref="header" settings={this.state.settings}/>
{children}
<Header ref="header" settings={this.state.settings} updateLocation={this.updateLocation} query={query} />
{React.cloneElement(
this.props.children,
{ ref: "view", location: this.props.location , updateLocation: this.updateLocation, query }
)}
{eventlog}
<Footer settings={this.state.settings}/>
</div>
@ -125,12 +147,12 @@ var ProxyAppMain = React.createClass({
import { Route, Router as ReactRouter, hashHistory, Redirect} from "react-router";
export var app = (
<ReactRouter history={hashHistory}>
<Redirect from="/" to="/flows" />
<Route path="/" component={ProxyAppMain}>
<Route path="flows" component={MainView}/>
<Route path="flows/:flowId/:detailTab" component={MainView}/>
<Route path="reports" component={Reports}/>
</Route>
</ReactRouter>
);
<ReactRouter history={hashHistory}>
<Redirect from="/" to="/flows" />
<Route path="/" component={ProxyAppMain}>
<Route path="flows" component={MainView}/>
<Route path="flows/:flowId/:detailTab" component={MainView}/>
<Route path="reports" component={Reports}/>
</Route>
</ReactRouter>
);