aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmproxy/web/static/css/app.css43
-rw-r--r--libmproxy/web/static/js/app.js121
-rw-r--r--web/src/css/eventlog.less45
-rw-r--r--web/src/css/flowdetail.less14
-rw-r--r--web/src/css/layout.less2
-rw-r--r--web/src/js/actions.js7
-rw-r--r--web/src/js/components/eventlog.jsx.js102
-rw-r--r--web/src/js/components/flowdetail.jsx.js2
-rw-r--r--web/src/js/components/mainview.jsx.js1
-rw-r--r--web/src/js/connection.js6
-rw-r--r--web/src/js/stores/eventlogstore.js4
11 files changed, 291 insertions, 56 deletions
diff --git a/libmproxy/web/static/css/app.css b/libmproxy/web/static/css/app.css
index f0ed95dd..8cdfbac6 100644
--- a/libmproxy/web/static/css/app.css
+++ b/libmproxy/web/static/css/app.css
@@ -60,6 +60,7 @@ body,
flex: 1 1 auto;
display: flex;
flex-direction: row;
+ outline: 0;
}
.main-view.vertical {
flex-direction: column;
@@ -212,27 +213,61 @@ header .menu {
table-layout: fixed;
word-break: break-all;
}
-.flow-detail table tr {
+.flow-detail table tr:not(:first-child) {
border-top: 1px solid #f7f7f7;
}
.flow-detail table td {
vertical-align: top;
}
.connection-table td:first-child {
- width: 33%;
+ width: 50%;
padding-right: 1em;
}
.header-table .header-name {
width: 33%;
padding-right: 1em;
}
+.connection-table td,
+.timing-table td {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
.eventlog {
+ height: 200px;
+ flex: 0 0 auto;
+ display: flex;
+ flex-direction: column;
+}
+.eventlog > div {
+ background-color: #F2F2F2;
+ padding: 0 5px;
flex: 0 0 auto;
+}
+.eventlog > pre {
+ flex: 1 1 auto;
margin: 0;
border-radius: 0;
- height: 200px;
- overflow: auto;
+ overflow-x: auto;
overflow-y: scroll;
+ background-color: #fcfcfc;
+}
+.eventlog .fa-close {
+ cursor: pointer;
+ float: right;
+ color: grey;
+ padding: 3px 0;
+ padding-left: 10px;
+}
+.eventlog .fa-close:hover {
+ color: black;
+}
+.eventlog .label {
+ cursor: pointer;
+ vertical-align: middle;
+ display: inline-block;
+ margin-top: -2px;
+ margin-left: 3px;
}
footer {
box-shadow: 0 -1px 3px #d3d3d3;
diff --git a/libmproxy/web/static/js/app.js b/libmproxy/web/static/js/app.js
index 4fb9f92d..fe317d7f 100644
--- a/libmproxy/web/static/js/app.js
+++ b/libmproxy/web/static/js/app.js
@@ -121,14 +121,15 @@ var SettingsActions = {
}
};
+var event_id = 0;
var EventLogActions = {
- add_event: function(message, level){
+ add_event: function(message){
AppDispatcher.dispatchViewAction({
type: ActionTypes.ADD_EVENT,
data: {
message: message,
- level: level || "info",
- source: "ui"
+ level: "web",
+ id: "viewAction-"+event_id++
}
});
}
@@ -263,7 +264,7 @@ _.extend(EventLogView.prototype, EventEmitter.prototype, {
},
add: function (entry) {
this.log.push(entry);
- if(this.log.length > 50){
+ if(this.log.length > 200){
this.log.shift();
}
this.emit("change");
@@ -334,7 +335,6 @@ _.extend(_EventLogStore.prototype, EventEmitter.prototype, {
var EventLogStore = new _EventLogStore();
AppDispatcher.register(EventLogStore.handle.bind(EventLogStore));
-
function FlowView(store, live) {
EventEmitter.call(this);
this._store = store;
@@ -443,7 +443,7 @@ _Connection.prototype.openWebSocketConnection = function () {
ws.onclose = this.onclose.bind(this);
};
_Connection.prototype.onopen = function (open) {
- console.log("onopen", this, arguments);
+ console.debug("onopen", this, arguments);
};
_Connection.prototype.onmessage = function (message) {
//AppDispatcher.dispatchServerAction(...);
@@ -452,11 +452,11 @@ _Connection.prototype.onmessage = function (message) {
};
_Connection.prototype.onerror = function (error) {
EventLogActions.add_event("WebSocket Connection Error.");
- console.log("onerror", this, arguments);
+ console.debug("onerror", this, arguments);
};
_Connection.prototype.onclose = function (close) {
EventLogActions.add_event("WebSocket Connection closed.");
- console.log("onclose", this, arguments);
+ console.debug("onclose", this, arguments);
};
var Connection = new _Connection(location.origin + "/updates");
@@ -1139,7 +1139,7 @@ var Timing = React.createClass({displayName: 'Timing',
return (
React.DOM.div(null,
React.DOM.h4(null, "Timing"),
- React.DOM.table(null,
+ React.DOM.table({className: "timing-table"},
React.DOM.tbody(null,
rows
)
@@ -1214,7 +1214,6 @@ var MainView = React.createClass({displayName: 'MainView',
};
},
componentDidMount: function () {
- console.log("get view");
this.flowStore = FlowStore.getView();
this.flowStore.addListener("change",this.onFlowChange);
},
@@ -1334,7 +1333,32 @@ var MainView = React.createClass({displayName: 'MainView',
});
/** @jsx React.DOM */
-var EventLog = React.createClass({displayName: 'EventLog',
+var LogMessage = React.createClass({displayName: 'LogMessage',
+ render: function(){
+ var entry = this.props.entry;
+ var indicator;
+ switch(entry.level){
+ case "web":
+ indicator = React.DOM.i({className: "fa fa-fw fa-html5"});
+ break;
+ case "debug":
+ indicator = React.DOM.i({className: "fa fa-fw fa-bug"});
+ break;
+ default:
+ indicator = React.DOM.i({className: "fa fa-fw fa-info"});
+ }
+ return (
+ React.DOM.div(null,
+ indicator, " ", entry.message
+ )
+ );
+ },
+ shouldComponentUpdate: function(){
+ return false; // log entries are immutable.
+ }
+});
+
+var EventLogContents = React.createClass({displayName: 'EventLogContents',
mixins:[AutoScrollMixin],
getInitialState: function () {
return {
@@ -1354,23 +1378,76 @@ var EventLog = React.createClass({displayName: 'EventLog',
log: this.log.getAll()
});
},
+ render: function () {
+ var messages = this.state.log.map(function(row) {
+ if(!this.props.filter[row.level]){
+ return null;
+ }
+ return LogMessage({key: row.id, entry: row});
+ }.bind(this));
+ return React.DOM.pre(null, messages);
+ }
+});
+
+var ToggleFilter = React.createClass({displayName: 'ToggleFilter',
+ toggle: function(){
+ return this.props.toggleLevel(this.props.name);
+ },
+ render: function(){
+ var className = "label ";
+ if (this.props.active) {
+ className += "label-primary";
+ } else {
+ className += "label-default";
+ }
+ return (
+ React.DOM.a({
+ href: "#",
+ className: className,
+ onClick: this.toggle},
+ this.props.name
+ )
+ );
+ }
+});
+
+var EventLog = React.createClass({displayName: 'EventLog',
+ getInitialState: function(){
+ return {
+ filter: {
+ "debug": false,
+ "info": true,
+ "web": true
+ }
+ };
+ },
close: function () {
SettingsActions.update({
showEventLog: false
});
},
+ toggleLevel: function(level){
+ var filter = this.state.filter;
+ filter[level] = !filter[level];
+ this.setState({filter: filter});
+ return false;
+ },
render: function () {
- var messages = this.state.log.map(function(row) {
- var indicator = null;
- if(row.source === "ui"){
- indicator = React.DOM.i({className: "fa fa-html5"});
- }
- return (
- React.DOM.div({key: row.id},
- indicator, " ", row.message
- ));
- });
- return React.DOM.pre({className: "eventlog"}, messages);
+ return (
+ React.DOM.div({className: "eventlog"},
+ React.DOM.div(null,
+ "Eventlog",
+ React.DOM.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}),
+ React.DOM.i({onClick: this.close, className: "fa fa-close"})
+ )
+
+ ),
+ EventLogContents({filter: this.state.filter})
+ )
+ );
}
});
/** @jsx React.DOM */
diff --git a/web/src/css/eventlog.less b/web/src/css/eventlog.less
index 993304cf..8b0a7647 100644
--- a/web/src/css/eventlog.less
+++ b/web/src/css/eventlog.less
@@ -1,10 +1,45 @@
.eventlog {
+ height: 200px;
flex: 0 0 auto;
- margin: 0;
- border-radius: 0;
- height: 200px;
- overflow: auto;
- overflow-y: scroll;
+ display: flex;
+ flex-direction: column;
+
+
+ > div {
+ background-color: #F2F2F2;
+ padding: 0 5px;
+ flex: 0 0 auto;
+ }
+
+ > pre {
+ flex: 1 1 auto;
+
+ margin: 0;
+ border-radius: 0;
+ overflow-x: auto;
+ overflow-y: scroll;
+ background-color: #fcfcfc;
+ }
+
+
+ .fa-close {
+ cursor: pointer;
+ float: right;
+ color: grey;
+ padding: 3px 0;
+ padding-left: 10px;
+ &:hover {
+ color: black;
+ }
+ }
+
+ .label {
+ cursor: pointer;
+ vertical-align: middle;
+ display: inline-block;
+ margin-top: -2px;
+ margin-left: 3px;
+ }
} \ No newline at end of file
diff --git a/web/src/css/flowdetail.less b/web/src/css/flowdetail.less
index 94920caa..3a6191d4 100644
--- a/web/src/css/flowdetail.less
+++ b/web/src/css/flowdetail.less
@@ -35,9 +35,9 @@
word-break: break-all;
tr {
- //&:not(:first-child){
+ &:not(:first-child){
border-top: 1px solid #f7f7f7;
- //}
+ }
}
td {
@@ -51,7 +51,7 @@
.connection-table {
td:first-child {
- width: 33%;
+ width: 50%;
padding-right: 1em;
}
}
@@ -64,4 +64,12 @@
.header-value {
}
+}
+
+.connection-table, .timing-table {
+ td {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
} \ No newline at end of file
diff --git a/web/src/css/layout.less b/web/src/css/layout.less
index 510fde6a..f6807f24 100644
--- a/web/src/css/layout.less
+++ b/web/src/css/layout.less
@@ -19,6 +19,8 @@ html, body, #container {
display: flex;
flex-direction: row;
+ outline: 0;
+
&.vertical {
flex-direction: column;
}
diff --git a/web/src/js/actions.js b/web/src/js/actions.js
index 43fbfb14..9211403f 100644
--- a/web/src/js/actions.js
+++ b/web/src/js/actions.js
@@ -23,14 +23,15 @@ var SettingsActions = {
}
};
+var event_id = 0;
var EventLogActions = {
- add_event: function(message, level){
+ add_event: function(message){
AppDispatcher.dispatchViewAction({
type: ActionTypes.ADD_EVENT,
data: {
message: message,
- level: level || "info",
- source: "ui"
+ level: "web",
+ id: "viewAction-"+event_id++
}
});
}
diff --git a/web/src/js/components/eventlog.jsx.js b/web/src/js/components/eventlog.jsx.js
index df212177..08a6dfb4 100644
--- a/web/src/js/components/eventlog.jsx.js
+++ b/web/src/js/components/eventlog.jsx.js
@@ -1,6 +1,31 @@
/** @jsx React.DOM */
-var EventLog = React.createClass({
+var LogMessage = React.createClass({
+ render: function(){
+ var entry = this.props.entry;
+ var indicator;
+ switch(entry.level){
+ case "web":
+ indicator = <i className="fa fa-fw fa-html5"></i>;
+ break;
+ case "debug":
+ indicator = <i className="fa fa-fw fa-bug"></i>;
+ break;
+ default:
+ indicator = <i className="fa fa-fw fa-info"></i>;
+ }
+ return (
+ <div>
+ { indicator } {entry.message}
+ </div>
+ );
+ },
+ shouldComponentUpdate: function(){
+ return false; // log entries are immutable.
+ }
+});
+
+var EventLogContents = React.createClass({
mixins:[AutoScrollMixin],
getInitialState: function () {
return {
@@ -20,22 +45,75 @@ var EventLog = React.createClass({
log: this.log.getAll()
});
},
+ render: function () {
+ var messages = this.state.log.map(function(row) {
+ if(!this.props.filter[row.level]){
+ return null;
+ }
+ return <LogMessage key={row.id} entry={row}/>;
+ }.bind(this));
+ return <pre>{messages}</pre>;
+ }
+});
+
+var ToggleFilter = React.createClass({
+ toggle: function(){
+ return this.props.toggleLevel(this.props.name);
+ },
+ render: function(){
+ var className = "label ";
+ if (this.props.active) {
+ className += "label-primary";
+ } else {
+ className += "label-default";
+ }
+ return (
+ <a
+ href="#"
+ className={className}
+ onClick={this.toggle}>
+ {this.props.name}
+ </a>
+ );
+ }
+});
+
+var EventLog = React.createClass({
+ getInitialState: function(){
+ return {
+ filter: {
+ "debug": false,
+ "info": true,
+ "web": true
+ }
+ };
+ },
close: function () {
SettingsActions.update({
showEventLog: false
});
},
+ toggleLevel: function(level){
+ var filter = this.state.filter;
+ filter[level] = !filter[level];
+ this.setState({filter: filter});
+ return false;
+ },
render: function () {
- var messages = this.state.log.map(function(row) {
- var indicator = null;
- if(row.source === "ui"){
- indicator = <i className="fa fa-html5"></i>;
- }
- return (
- <div key={row.id}>
- { indicator } {row.message}
- </div>);
- });
- return <pre className="eventlog">{messages}</pre>;
+ 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>
+ <EventLogContents filter={this.state.filter}/>
+ </div>
+ );
}
}); \ 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 ad1cfe67..3ba025a9 100644
--- a/web/src/js/components/flowdetail.jsx.js
+++ b/web/src/js/components/flowdetail.jsx.js
@@ -231,7 +231,7 @@ var Timing = React.createClass({
return (
<div>
<h4>Timing</h4>
- <table>
+ <table className="timing-table">
<tbody>
{rows}
</tbody>
diff --git a/web/src/js/components/mainview.jsx.js b/web/src/js/components/mainview.jsx.js
index d521635a..795b8136 100644
--- a/web/src/js/components/mainview.jsx.js
+++ b/web/src/js/components/mainview.jsx.js
@@ -7,7 +7,6 @@ var MainView = React.createClass({
};
},
componentDidMount: function () {
- console.log("get view");
this.flowStore = FlowStore.getView();
this.flowStore.addListener("change",this.onFlowChange);
},
diff --git a/web/src/js/connection.js b/web/src/js/connection.js
index 640e9742..3edbfc20 100644
--- a/web/src/js/connection.js
+++ b/web/src/js/connection.js
@@ -14,7 +14,7 @@ _Connection.prototype.openWebSocketConnection = function () {
ws.onclose = this.onclose.bind(this);
};
_Connection.prototype.onopen = function (open) {
- console.log("onopen", this, arguments);
+ console.debug("onopen", this, arguments);
};
_Connection.prototype.onmessage = function (message) {
//AppDispatcher.dispatchServerAction(...);
@@ -23,11 +23,11 @@ _Connection.prototype.onmessage = function (message) {
};
_Connection.prototype.onerror = function (error) {
EventLogActions.add_event("WebSocket Connection Error.");
- console.log("onerror", this, arguments);
+ console.debug("onerror", this, arguments);
};
_Connection.prototype.onclose = function (close) {
EventLogActions.add_event("WebSocket Connection closed.");
- console.log("onclose", this, arguments);
+ console.debug("onclose", this, arguments);
};
var Connection = new _Connection(location.origin + "/updates");
diff --git a/web/src/js/stores/eventlogstore.js b/web/src/js/stores/eventlogstore.js
index dc6dbbbf..e356959a 100644
--- a/web/src/js/stores/eventlogstore.js
+++ b/web/src/js/stores/eventlogstore.js
@@ -26,7 +26,7 @@ _.extend(EventLogView.prototype, EventEmitter.prototype, {
},
add: function (entry) {
this.log.push(entry);
- if(this.log.length > 50){
+ if(this.log.length > 200){
this.log.shift();
}
this.emit("change");
@@ -96,4 +96,4 @@ _.extend(_EventLogStore.prototype, EventEmitter.prototype, {
var EventLogStore = new _EventLogStore();
-AppDispatcher.register(EventLogStore.handle.bind(EventLogStore));
+AppDispatcher.register(EventLogStore.handle.bind(EventLogStore)); \ No newline at end of file