web: various fixes, add clear button

This commit is contained in:
Maximilian Hils
2014-11-28 19:16:47 +01:00
parent 7ca1ac0f3b
commit c39b6e4277
9 changed files with 176 additions and 90 deletions

View File

@@ -4,9 +4,9 @@ var FlowDetailNav = React.createClass({
var items = this.props.tabs.map(function (e) {
var str = e.charAt(0).toUpperCase() + e.slice(1);
var className = this.props.active === e ? "active" : "";
var onClick = function (e) {
var onClick = function (event) {
this.props.selectTab(e);
e.preventDefault();
event.preventDefault();
}.bind(this);
return <a key={e}
href="#"
@@ -302,7 +302,6 @@ var FlowDetail = React.createClass({
);
},
render: function () {
var flow = JSON.stringify(this.props.flow, null, 2);
var Tab = tabs[this.props.active];
return (
<div className="flow-detail" onScroll={this.adjustHead}>

View File

@@ -83,20 +83,23 @@ var FlowTable = React.createClass({
scrollIntoView: function (flow) {
// Now comes the fun part: Scroll the flow into the view.
var viewport = this.getDOMNode();
var flowNode = this.refs.body.refs[flow.id].getDOMNode();
var thead_height = this.refs.body.getDOMNode().offsetTop;
var flow_top = (this.props.view.index(flow) * ROW_HEIGHT) + thead_height;
var viewport_top = viewport.scrollTop;
var viewport_bottom = viewport_top + viewport.offsetHeight;
var flowNode_top = flowNode.offsetTop;
var flowNode_bottom = flowNode_top + flowNode.offsetHeight;
var flow_bottom = flow_top + ROW_HEIGHT;
// Account for pinned thead by pretending that the flowNode starts
// -thead_height pixel earlier.
flowNode_top -= this.refs.body.getDOMNode().offsetTop;
// Account for pinned thead
if (flowNode_top < viewport_top) {
viewport.scrollTop = flowNode_top;
} else if (flowNode_bottom > viewport_bottom) {
viewport.scrollTop = flowNode_bottom - viewport.offsetHeight;
console.log("scrollInto", flow_top, flow_bottom, viewport_top, viewport_bottom, thead_height);
if (flow_top - thead_height < viewport_top) {
viewport.scrollTop = flow_top - thead_height;
} else if (flow_bottom > viewport_bottom) {
viewport.scrollTop = flow_bottom - viewport.offsetHeight;
}
},
render: function () {
@@ -134,7 +137,7 @@ var FlowTable = React.createClass({
<table>
<FlowTableHead ref="head"
columns={this.state.columns}/>
<tbody>
<tbody ref="body">
<tr style={{height: space_top}}></tr>
{ fix_nth_row }
{rows}

View File

@@ -8,12 +8,17 @@ var MainMenu = React.createClass({
showEventLog: !this.props.settings.showEventLog
});
},
clearFlows: function(){
$.post("/flows/clear");
},
render: function () {
return (
<div>
<button className={"btn " + (this.props.settings.showEventLog ? "btn-primary" : "btn-default")} onClick={this.toggleEventLog}>
<i className="fa fa-database"></i>
Display Event Log
<i className="fa fa-database"></i>&nbsp;Display Event Log
</button>&nbsp;
<button className="btn btn-default" onClick={this.clearFlows}>
<i className="fa fa-eraser"></i>&nbsp;Clear Flows
</button>
</div>
);

View File

@@ -35,8 +35,7 @@ var MainView = React.createClass({
detailTab: this.getParams().detailTab || "request"
}
);
console.log("TODO: Scroll into view");
//this.refs.flowTable.scrollIntoView(flow);
this.refs.flowTable.scrollIntoView(flow);
} else {
this.replaceWith("flows");
}

View File

@@ -95,4 +95,21 @@ var Splitter = React.createClass({
</div>
);
}
});
function getCookie(name) {
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return r ? r[1] : undefined;
}
var xsrf = $.param({_xsrf: getCookie("_xsrf")});
//Tornado XSRF Protection.
$.ajaxPrefilter(function(options){
if(options.type === "post" && options.url[0] === "/"){
if(options.data){
options.data += ("&" + xsrf);
} else {
options.data = xsrf;
}
}
});

View File

@@ -45,7 +45,8 @@ _.extend(FlowStore.prototype, {
function LiveFlowStore(endpoint) {
FlowStore.call(this);
this.updates_before_init = []; // (empty array is true in js)
this.updates_before_fetch = undefined;
this._fetchxhr = false;
this.endpoint = endpoint || "/flows";
this.conn = new Connection(this.endpoint + "/updates");
this.conn.onopen = this._onopen.bind(this);
@@ -60,32 +61,45 @@ _.extend(LiveFlowStore.prototype, FlowStore.prototype, {
},
add: function (flow) {
// Make sure that deferred adds don't add an element twice.
if (!this._pos_map[flow.id]) {
if (!(flow.id in this._pos_map)) {
FlowStore.prototype.add.call(this, flow);
}
},
handle_update: function (type, data) {
console.log("LiveFlowStore.handle_update", type, data);
if (this.updates_before_init) {
console.log("defer update", type, data);
this.updates_before_init.push(arguments);
} else {
this[type](data);
}
},
handle_fetch: function (data) {
console.log("Flows fetched.");
this.reset(data.flows);
var updates = this.updates_before_init;
this.updates_before_init = false;
for (var i = 0; i < updates.length; i++) {
this.handle_update.apply(this, updates[i]);
}
},
_onopen: function () {
//Update stream openend, fetch list of flows.
console.log("Update Connection opened, fetching flows...");
$.getJSON(this.endpoint, this.handle_fetch.bind(this));
this.fetch();
},
fetch: function () {
if (this._fetchxhr) {
this._fetchxhr.abort();
}
this._fetchxhr = $.getJSON(this.endpoint, this.handle_fetch.bind(this));
this.updates_before_fetch = []; // (JS: empty array is true)
},
handle_update: function (type, data) {
console.log("LiveFlowStore.handle_update", type, data);
if (type === "reset") {
return this.fetch();
}
if (this.updates_before_fetch) {
console.log("defer update", type, data);
this.updates_before_fetch.push(arguments);
} else {
this[type](data);
}
},
handle_fetch: function (data) {
this._fetchxhr = false;
console.log("Flows fetched.");
this.reset(data.flows);
var updates = this.updates_before_fetch;
this.updates_before_fetch = false;
for (var i = 0; i < updates.length; i++) {
this.handle_update.apply(this, updates[i]);
}
},
});
@@ -130,20 +144,22 @@ _.extend(FlowView.prototype, EventEmitter.prototype, {
//Ugly workaround: Call .sortfun() for each flow once in order,
//so that SortByInsertionOrder make sense.
var i = flows.length;
while(i--){
for(var i = 0; i < flows.length; i++) {
this.sortfun(flows[i]);
}
this.flows = flows.filter(this.filt);
this.flows.sort(function (a, b) {
return this.sortfun(b) - this.sortfun(a);
return this.sortfun(a) - this.sortfun(b);
}.bind(this));
this.emit("recalculate");
},
index: function (flow) {
return _.sortedIndex(this.flows, flow, this.sortfun);
},
add: function (flow) {
if (this.filt(flow)) {
var idx = _.sortedIndex(this.flows, flow, this.sortfun);
var idx = this.index(flow);
if (idx === this.flows.length) { //happens often, .push is way faster.
this.flows.push(flow);
} else {