aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/src/css/flowdetail.less2
-rw-r--r--web/src/js/actions.js4
-rw-r--r--web/src/js/components/flowdetail.jsx.js2
-rw-r--r--web/src/js/components/header.jsx.js36
-rw-r--r--web/src/js/components/mainview.jsx.js4
-rw-r--r--web/src/js/utils.js44
6 files changed, 83 insertions, 9 deletions
diff --git a/web/src/css/flowdetail.less b/web/src/css/flowdetail.less
index 3a6191d4..7649057f 100644
--- a/web/src/css/flowdetail.less
+++ b/web/src/css/flowdetail.less
@@ -24,6 +24,8 @@
padding: 4px 8px;
border-radius: 5px;
word-break: break-all;
+ max-height: 100px;
+ overflow-y: auto;
}
}
diff --git a/web/src/js/actions.js b/web/src/js/actions.js
index 2c4183e4..3d9b89e6 100644
--- a/web/src/js/actions.js
+++ b/web/src/js/actions.js
@@ -62,4 +62,8 @@ var EventLogActions = {
}
});
}
+};
+
+Query = {
+ FILTER: "f"
}; \ No newline at end of file
diff --git a/web/src/js/components/flowdetail.jsx.js b/web/src/js/components/flowdetail.jsx.js
index 6d46cd2e..5727ec75 100644
--- a/web/src/js/components/flowdetail.jsx.js
+++ b/web/src/js/components/flowdetail.jsx.js
@@ -294,7 +294,7 @@ var allTabs = {
};
var FlowDetail = React.createClass({
- mixins: [StickyHeadMixin, ReactRouter.Navigation, ReactRouter.State],
+ mixins: [StickyHeadMixin, Navigation, State],
getTabs: function (flow) {
var tabs = [];
["request", "response", "error"].forEach(function (e) {
diff --git a/web/src/js/components/header.jsx.js b/web/src/js/components/header.jsx.js
index a23afa9b..b181b670 100644
--- a/web/src/js/components/header.jsx.js
+++ b/web/src/js/components/header.jsx.js
@@ -1,4 +1,13 @@
var MainMenu = React.createClass({
+ mixins: [Navigation, State],
+ getInitialState: function(){
+ this.onQueryChange(Query.FILTER, function(oldVal, nextVal){
+ this.setState({filter: nextVal});
+ }.bind(this));
+ return {
+ filter: this.getQuery()[Query.FILTER]
+ };
+ },
statics: {
title: "Traffic",
route: "flows"
@@ -11,6 +20,13 @@ var MainMenu = React.createClass({
clearFlows: function () {
$.post("/flows/clear");
},
+ setFilter: function(e){
+ e.preventDefault();
+ this.setQuery(Query.FILTER, this.state.filter);
+ },
+ onFilterChange: function(e){
+ this.setState({filter: e.target.value});
+ },
render: function () {
return (
<div>
@@ -23,6 +39,14 @@ var MainMenu = React.createClass({
<i className="fa fa-eraser"></i>
&nbsp;Clear Flows
</button>
+ &nbsp;
+ <form className="form-inline" onSubmit={this.setFilter} style={{display:"inline-block"}}>
+ <input type="text" placeholder="filter expression"
+ onChange={this.onFilterChange} value={this.state.filter}
+ className="form-control"
+ />
+ </form>
+
</div>
);
}
@@ -70,19 +94,19 @@ var FileMenu = React.createClass({
});
}
},
- handleNewClick: function(e){
+ handleNewClick: function (e) {
e.preventDefault();
console.error("unimplemented: handleNewClick");
},
- handleOpenClick: function(e){
+ handleOpenClick: function (e) {
e.preventDefault();
console.error("unimplemented: handleOpenClick");
},
- handleSaveClick: function(e){
+ handleSaveClick: function (e) {
e.preventDefault();
console.error("unimplemented: handleSaveClick");
},
- handleShutdownClick: function(e){
+ handleShutdownClick: function (e) {
e.preventDefault();
console.error("unimplemented: handleShutdownClick");
},
@@ -129,7 +153,7 @@ var header_entries = [MainMenu, ToolsMenu, ReportsMenu];
var Header = React.createClass({
- mixins: [ReactRouter.Navigation],
+ mixins: [Navigation],
getInitialState: function () {
return {
active: header_entries[0]
@@ -137,7 +161,7 @@ var Header = React.createClass({
},
handleClick: function (active, e) {
e.preventDefault();
- this.transitionTo(active.route);
+ this.replaceWith(active.route);
this.setState({active: active});
},
render: function () {
diff --git a/web/src/js/components/mainview.jsx.js b/web/src/js/components/mainview.jsx.js
index 17a024ee..6e216b6a 100644
--- a/web/src/js/components/mainview.jsx.js
+++ b/web/src/js/components/mainview.jsx.js
@@ -1,5 +1,5 @@
var MainView = React.createClass({
- mixins: [ReactRouter.Navigation, ReactRouter.State],
+ mixins: [Navigation, State],
getInitialState: function () {
return {
flows: []
@@ -52,7 +52,7 @@ var MainView = React.createClass({
);
this.refs.flowTable.scrollIntoView(flow);
} else {
- this.replaceWith("flows");
+ this.replaceWith("flows", {});
}
},
selectFlowRelative: function (shift) {
diff --git a/web/src/js/utils.js b/web/src/js/utils.js
index 8ae7aa54..b475980a 100644
--- a/web/src/js/utils.js
+++ b/web/src/js/utils.js
@@ -23,6 +23,50 @@ var StickyHeadMixin = {
};
+var Navigation = _.extend({}, ReactRouter.Navigation, {
+ setQuery: function (k, v) {
+ var q = this.context.getCurrentQuery();
+ q[k] = v;
+ this.replaceWith(this.context.getCurrentPath(), this.context.getCurrentParams(), q);
+ },
+ replaceWith: function(routeNameOrPath, params, query) {
+ if(routeNameOrPath === undefined){
+ routeNameOrPath = this.context.getCurrentPath();
+ }
+ if(params === undefined){
+ params = this.context.getCurrentParams();
+ }
+ if(query === undefined){
+ query = this.context.getCurrentQuery();
+ }
+ ReactRouter.Navigation.replaceWith.call(this, routeNameOrPath, params, query);
+ }
+});
+
+var State = _.extend({}, ReactRouter.State, {
+ getInitialState: function () {
+ this._query = this.context.getCurrentQuery();
+ this._queryWatches = [];
+ return null;
+ },
+ onQueryChange: function (key, callback) {
+ this._queryWatches.push({
+ key: key,
+ callback: callback
+ });
+ },
+ componentWillReceiveProps: function (nextProps, nextState) {
+ var q = this.context.getCurrentQuery();
+ for (var i = 0; i < this._queryWatches.length; i++) {
+ var watch = this._queryWatches[i];
+ if (this._query[watch.key] !== q[watch.key]) {
+ watch.callback(this._query[watch.key], q[watch.key], watch.key);
+ }
+ }
+ this._query = q;
+ }
+});
+
var Key = {
UP: 38,
DOWN: 40,