Merge branch 'such-redux'

This commit is contained in:
Maximilian Hils 2016-06-05 18:23:46 -07:00
commit b6ebde3b1d
6 changed files with 1401 additions and 1310 deletions

View File

@ -1212,251 +1212,221 @@ var _utils2 = require("../utils.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var TLSColumn = _react2.default.createClass({ function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
displayName: "TLSColumn",
statics: { function TLSColumn(_ref) {
Title: _react2.default.createClass({ var flow = _ref.flow;
displayName: "Title",
render: function render() { var ssl = flow.request.scheme === "https";
return _react2.default.createElement("th", _extends({}, this.props, { className: "col-tls " + (this.props.className || "") })); var classes = void 0;
} if (ssl) {
}), classes = "col-tls col-tls-https";
sortKeyFun: function sortKeyFun(flow) { } else {
return flow.request.scheme; classes = "col-tls col-tls-http";
}
},
render: function render() {
var flow = this.props.flow;
var ssl = flow.request.scheme === "https";
var classes;
if (ssl) {
classes = "col-tls col-tls-https";
} else {
classes = "col-tls col-tls-http";
}
return _react2.default.createElement("td", { className: classes });
} }
}); return _react2.default.createElement("td", { className: classes });
}
TLSColumn.Title = function (_ref2) {
var _ref2$className = _ref2.className;
var className = _ref2$className === undefined ? "" : _ref2$className;
var IconColumn = _react2.default.createClass({ var props = _objectWithoutProperties(_ref2, ["className"]);
displayName: "IconColumn",
statics: { return _react2.default.createElement("th", _extends({}, props, { className: "col-tls " + className }));
Title: _react2.default.createClass({ };
displayName: "Title", TLSColumn.sortKeyFun = function (flow) {
return flow.request.scheme;
};
render: function render() { function IconColumn(_ref3) {
return _react2.default.createElement("th", _extends({}, this.props, { className: "col-icon " + (this.props.className || "") })); var flow = _ref3.flow;
}
})
},
render: function render() {
var flow = this.props.flow;
var icon; var icon = void 0;
if (flow.response) { if (flow.response) {
var contentType = _utils.ResponseUtils.getContentType(flow.response); var contentType = _utils.ResponseUtils.getContentType(flow.response);
//TODO: We should assign a type to the flow somewhere else. //TODO: We should assign a type to the flow somewhere else.
if (flow.response.status_code === 304) { if (flow.response.status_code === 304) {
icon = "resource-icon-not-modified"; icon = "resource-icon-not-modified";
} else if (300 <= flow.response.status_code && flow.response.status_code < 400) { } else if (300 <= flow.response.status_code && flow.response.status_code < 400) {
icon = "resource-icon-redirect"; icon = "resource-icon-redirect";
} else if (contentType && contentType.indexOf("image") >= 0) { } else if (contentType && contentType.indexOf("image") >= 0) {
icon = "resource-icon-image"; icon = "resource-icon-image";
} else if (contentType && contentType.indexOf("javascript") >= 0) { } else if (contentType && contentType.indexOf("javascript") >= 0) {
icon = "resource-icon-js"; icon = "resource-icon-js";
} else if (contentType && contentType.indexOf("css") >= 0) { } else if (contentType && contentType.indexOf("css") >= 0) {
icon = "resource-icon-css"; icon = "resource-icon-css";
} else if (contentType && contentType.indexOf("html") >= 0) { } else if (contentType && contentType.indexOf("html") >= 0) {
icon = "resource-icon-document"; icon = "resource-icon-document";
}
} }
if (!icon) {
icon = "resource-icon-plain";
}
icon += " resource-icon";
return _react2.default.createElement(
"td",
{ className: "col-icon" },
_react2.default.createElement("div", { className: icon })
);
} }
}); if (!icon) {
icon = "resource-icon-plain";
var PathColumn = _react2.default.createClass({
displayName: "PathColumn",
statics: {
Title: _react2.default.createClass({
displayName: "Title",
render: function render() {
return _react2.default.createElement(
"th",
_extends({}, this.props, { className: "col-path " + (this.props.className || "") }),
"Path"
);
}
}),
sortKeyFun: function sortKeyFun(flow) {
return _utils.RequestUtils.pretty_url(flow.request);
}
},
render: function render() {
var flow = this.props.flow;
return _react2.default.createElement(
"td",
{ className: "col-path" },
flow.request.is_replay ? _react2.default.createElement("i", { className: "fa fa-fw fa-repeat pull-right" }) : null,
flow.intercepted ? _react2.default.createElement("i", { className: "fa fa-fw fa-pause pull-right" }) : null,
_utils.RequestUtils.pretty_url(flow.request)
);
} }
});
var MethodColumn = _react2.default.createClass({ icon += " resource-icon";
displayName: "MethodColumn", return _react2.default.createElement(
"td",
{ className: "col-icon" },
_react2.default.createElement("div", { className: icon })
);
}
IconColumn.Title = function (_ref4) {
var _ref4$className = _ref4.className;
var className = _ref4$className === undefined ? "" : _ref4$className;
statics: { var props = _objectWithoutProperties(_ref4, ["className"]);
Title: _react2.default.createClass({
displayName: "Title",
render: function render() { return _react2.default.createElement("th", _extends({}, props, { className: "col-icon " + className }));
return _react2.default.createElement( };
"th",
_extends({}, this.props, { className: "col-method " + (this.props.className || "") }), function PathColumn(_ref5) {
"Method" var flow = _ref5.flow;
);
} return _react2.default.createElement(
}), "td",
sortKeyFun: function sortKeyFun(flow) { { className: "col-path" },
return flow.request.method; flow.request.is_replay ? _react2.default.createElement("i", { className: "fa fa-fw fa-repeat pull-right" }) : null,
} flow.intercepted ? _react2.default.createElement("i", { className: "fa fa-fw fa-pause pull-right" }) : null,
}, _utils.RequestUtils.pretty_url(flow.request)
render: function render() { );
var flow = this.props.flow; }
return _react2.default.createElement( PathColumn.Title = function (_ref6) {
"td", var _ref6$className = _ref6.className;
{ className: "col-method" }, var className = _ref6$className === undefined ? "" : _ref6$className;
flow.request.method
); var props = _objectWithoutProperties(_ref6, ["className"]);
return _react2.default.createElement(
"th",
_extends({}, props, { className: "col-path " + className }),
"Path"
);
};
PathColumn.sortKeyFun = function (flow) {
return _utils.RequestUtils.pretty_url(flow.request);
};
function MethodColumn(_ref7) {
var flow = _ref7.flow;
return _react2.default.createElement(
"td",
{ className: "col-method" },
flow.request.method
);
}
MethodColumn.Title = function (_ref8) {
var _ref8$className = _ref8.className;
var className = _ref8$className === undefined ? "" : _ref8$className;
var props = _objectWithoutProperties(_ref8, ["className"]);
return _react2.default.createElement(
"th",
_extends({}, props, { className: "col-method " + className }),
"Method"
);
};
MethodColumn.sortKeyFun = function (flow) {
return flow.request.method;
};
function StatusColumn(_ref9) {
var flow = _ref9.flow;
var status = void 0;
if (flow.response) {
status = flow.response.status_code;
} else {
status = null;
} }
}); return _react2.default.createElement(
"td",
{ className: "col-status" },
status
);
}
StatusColumn.Title = function (_ref10) {
var _ref10$className = _ref10.className;
var className = _ref10$className === undefined ? "" : _ref10$className;
var StatusColumn = _react2.default.createClass({ var props = _objectWithoutProperties(_ref10, ["className"]);
displayName: "StatusColumn",
statics: { return _react2.default.createElement(
Title: _react2.default.createClass({ "th",
displayName: "Title", _extends({}, props, { className: "col-status " + className }),
"Status"
);
};
StatusColumn.sortKeyFun = function (flow) {
return flow.response ? flow.response.status_code : undefined;
};
render: function render() { function SizeColumn(_ref11) {
return _react2.default.createElement( var flow = _ref11.flow;
"th",
_extends({}, this.props, { className: "col-status " + (this.props.className || "") }), var total = flow.request.contentLength;
"Status" if (flow.response) {
); total += flow.response.contentLength || 0;
}
}),
sortKeyFun: function sortKeyFun(flow) {
return flow.response ? flow.response.status_code : undefined;
}
},
render: function render() {
var flow = this.props.flow;
var status;
if (flow.response) {
status = flow.response.status_code;
} else {
status = null;
}
return _react2.default.createElement(
"td",
{ className: "col-status" },
status
);
} }
}); var size = (0, _utils2.formatSize)(total);
return _react2.default.createElement(
"td",
{ className: "col-size" },
size
);
}
SizeColumn.Title = function (_ref12) {
var _ref12$className = _ref12.className;
var className = _ref12$className === undefined ? "" : _ref12$className;
var SizeColumn = _react2.default.createClass({ var props = _objectWithoutProperties(_ref12, ["className"]);
displayName: "SizeColumn",
statics: { return _react2.default.createElement(
Title: _react2.default.createClass({ "th",
displayName: "Title", _extends({}, props, { className: "col-size " + className }),
"Size"
render: function render() { );
return _react2.default.createElement( };
"th", SizeColumn.sortKeyFun = function (flow) {
_extends({}, this.props, { className: "col-size " + (this.props.className || "") }), var total = flow.request.contentLength;
"Size" if (flow.response) {
); total += flow.response.contentLength || 0;
}
}),
sortKeyFun: function sortKeyFun(flow) {
var total = flow.request.contentLength;
if (flow.response) {
total += flow.response.contentLength || 0;
}
return total;
}
},
render: function render() {
var flow = this.props.flow;
var total = flow.request.contentLength;
if (flow.response) {
total += flow.response.contentLength || 0;
}
var size = (0, _utils2.formatSize)(total);
return _react2.default.createElement(
"td",
{ className: "col-size" },
size
);
} }
}); return total;
};
var TimeColumn = _react2.default.createClass({ function TimeColumn(_ref13) {
displayName: "TimeColumn", var flow = _ref13.flow;
statics: { var time = void 0;
Title: _react2.default.createClass({ if (flow.response) {
displayName: "Title", time = (0, _utils2.formatTimeDelta)(1000 * (flow.response.timestamp_end - flow.request.timestamp_start));
} else {
render: function render() { time = "...";
return _react2.default.createElement(
"th",
_extends({}, this.props, { className: "col-time " + (this.props.className || "") }),
"Time"
);
}
}),
sortKeyFun: function sortKeyFun(flow) {
if (flow.response) {
return flow.response.timestamp_end - flow.request.timestamp_start;
}
}
},
render: function render() {
var flow = this.props.flow;
var time;
if (flow.response) {
time = (0, _utils2.formatTimeDelta)(1000 * (flow.response.timestamp_end - flow.request.timestamp_start));
} else {
time = "...";
}
return _react2.default.createElement(
"td",
{ className: "col-time" },
time
);
} }
}); return _react2.default.createElement(
"td",
{ className: "col-time" },
time
);
}
TimeColumn.Title = function (_ref14) {
var _ref14$className = _ref14.className;
var className = _ref14$className === undefined ? "" : _ref14$className;
var props = _objectWithoutProperties(_ref14, ["className"]);
return _react2.default.createElement(
"th",
_extends({}, props, { className: "col-time " + className }),
"Time"
);
};
TimeColumn.sortKeyFun = function (flow) {
return flow.response.timestamp_end - flow.request.timestamp_start;
};
var all_columns = [TLSColumn, IconColumn, PathColumn, MethodColumn, StatusColumn, SizeColumn, TimeColumn]; var all_columns = [TLSColumn, IconColumn, PathColumn, MethodColumn, StatusColumn, SizeColumn, TimeColumn];
@ -1525,12 +1495,17 @@ FlowRow.propTypes = {
selected: _react2.default.PropTypes.bool selected: _react2.default.PropTypes.bool
}; };
function FlowRow(props) { function FlowRow(_ref) {
var flow = props.flow; var flow = _ref.flow;
var selected = _ref.selected;
var highlight = _ref.highlight;
var columns = _ref.columns;
var selectFlow = _ref.selectFlow;
var className = (0, _classnames2.default)({ var className = (0, _classnames2.default)({
"selected": props.selected, "selected": selected,
"highlighted": props.highlight && parseFilter(props.highlight)(flow), "highlighted": highlight && parseFilter(highlight)(flow),
"intercepted": flow.intercepted, "intercepted": flow.intercepted,
"has-request": flow.request, "has-request": flow.request,
"has-response": flow.response "has-response": flow.response
@ -1539,10 +1514,10 @@ function FlowRow(props) {
return _react2.default.createElement( return _react2.default.createElement(
"tr", "tr",
{ className: className, onClick: function onClick() { { className: className, onClick: function onClick() {
return props.selectFlow(flow); return selectFlow(flow);
} }, } },
props.columns.map(function (Column) { columns.map(function (Column) {
return _react2.default.createElement(Column, { key: Column.displayName, flow: flow }); return _react2.default.createElement(Column, { key: Column.name, flow: flow });
}) })
); );
} }
@ -1553,8 +1528,6 @@ var FlowRowContainer = (0, _reactRedux.connect)(function (state, ownProps) {
highlight: state.flows.highlight, highlight: state.flows.highlight,
selected: state.flows.selected.indexOf(ownProps.flowId) >= 0 selected: state.flows.selected.indexOf(ownProps.flowId) >= 0
}; };
}, function (dispatch, ownProps) {
return {};
})(FlowRow); })(FlowRow);
var FlowTableHead = function (_React$Component) { var FlowTableHead = function (_React$Component) {
@ -1608,11 +1581,11 @@ var FlowTableHead = function (_React$Component) {
null, null,
this.props.columns.map(function (Column) { this.props.columns.map(function (Column) {
return _react2.default.createElement(Column.Title, { return _react2.default.createElement(Column.Title, {
key: Column.displayName, key: Column.name,
onClick: function onClick() { onClick: function onClick() {
return _this2.onClick(Column); return _this2.onClick(Column);
}, },
className: sortColumn === Column && sortType className: sortColumn === Column ? sortType : undefined
}); });
}) })
); );
@ -1769,8 +1742,6 @@ var FlowTableContainer = (0, _reactRedux.connect)(function (state) {
return { return {
flows: state.flows.view flows: state.flows.view
}; };
}, function (dispatch) {
return {};
})(FlowTable); })(FlowTable);
exports.default = FlowTableContainer; exports.default = FlowTableContainer;
@ -3831,7 +3802,7 @@ var MainView = _react2.default.createClass({
componentWillReceiveProps: function componentWillReceiveProps(nextProps) { componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
// Update redux store with route changes // Update redux store with route changes
if (nextProps.routeParams.flowId !== (nextProps.selectedFlow || {}).id) { if (nextProps.routeParams.flowId !== (nextProps.selectedFlow || {}).id) {
this.props.selectFlow(nextProps.routeParams.flowId); // FIXME this.props.selectFlow(nextProps.routeParams.flowId)
} }
if (nextProps.location.query[_actions.Query.SEARCH] !== nextProps.filter) { if (nextProps.location.query[_actions.Query.SEARCH] !== nextProps.filter) {
this.props.setFilter(nextProps.location.query[_actions.Query.SEARCH], false); this.props.setFilter(nextProps.location.query[_actions.Query.SEARCH], false);
@ -3844,6 +3815,7 @@ var MainView = _react2.default.createClass({
// FIXME: Move to redux. This requires that sortKeyFun is not a function anymore. // FIXME: Move to redux. This requires that sortKeyFun is not a function anymore.
}, },
selectFlow: function selectFlow(flow) { selectFlow: function selectFlow(flow) {
return this.props.selectFlow(flow.id);
// TODO: This belongs into redux // TODO: This belongs into redux
if (flow) { if (flow) {
var tab = this.props.routeParams.detailTab || "request"; var tab = this.props.routeParams.detailTab || "request";
@ -4145,7 +4117,7 @@ exports.default = Prompt;
Object.defineProperty(exports, "__esModule", { Object.defineProperty(exports, "__esModule", {
value: true value: true
}); });
exports.App = undefined; exports.history = exports.App = undefined;
var _react = require("react"); var _react = require("react");
@ -4326,6 +4298,7 @@ var App = exports.App = _react2.default.createElement(
_react2.default.createElement(_reactRouter.Route, { path: "reports", component: Reports }) _react2.default.createElement(_reactRouter.Route, { path: "reports", component: Reports })
) )
); );
exports.history = _reactRouter.hashHistory;
},{"../store/store.js":31,"../utils.js":32,"./common.js":4,"./eventlog.js":6,"./footer.js":14,"./header.js":15,"./mainview.js":18,"lodash":"lodash","react":"react","react-dom":"react-dom","react-redux":"react-redux","react-router":"react-router"}],21:[function(require,module,exports){ },{"../store/store.js":31,"../utils.js":32,"./common.js":4,"./eventlog.js":6,"./footer.js":14,"./header.js":15,"./mainview.js":18,"lodash":"lodash","react":"react","react-dom":"react-dom","react-redux":"react-redux","react-router":"react-router"}],21:[function(require,module,exports){
"use strict"; "use strict";
@ -4544,6 +4517,8 @@ var _filt2 = _interopRequireDefault(_filt);
var _view = require("./utils/view"); var _view = require("./utils/view");
var _proxyapp = require("../components/proxyapp");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var UPDATE_FLOWS = exports.UPDATE_FLOWS = "UPDATE_FLOWS"; var UPDATE_FLOWS = exports.UPDATE_FLOWS = "UPDATE_FLOWS";
@ -4614,6 +4589,23 @@ function setHighlight(highlight) {
}; };
} }
function selectFlow(flowId) { function selectFlow(flowId) {
var detailTab = arguments.length <= 1 || arguments[1] === undefined ? "request" : arguments[1];
var pathname = void 0;
if (flowId) {
pathname = "/flows/" + flowId + "/" + detailTab;
} else {
pathname = "/flows";
}
/*
let location
history.listen(l => {location = l})()
history.replace({
...location,
pathname
})
*/
return { return {
type: SELECT_FLOW, type: SELECT_FLOW,
flowId: flowId flowId: flowId
@ -4623,7 +4615,7 @@ function selectFlow(flowId) {
exports.updateFlows = updateList; exports.updateFlows = updateList;
exports.fetchFlows = fetchList; exports.fetchFlows = fetchList;
},{"../filt/filt":29,"./utils/list":26,"./utils/view":27}],25:[function(require,module,exports){ },{"../components/proxyapp":20,"../filt/filt":29,"./utils/list":26,"./utils/view":27}],25:[function(require,module,exports){
'use strict'; 'use strict';
Object.defineProperty(exports, "__esModule", { Object.defineProperty(exports, "__esModule", {
@ -4757,7 +4749,7 @@ function makeList(actionType, fetchURL) {
list = [].concat(_toConsumableArray(state.list)); list = [].concat(_toConsumableArray(state.list));
itemIndex = state.indexOf[action.item.id]; itemIndex = state.indexOf[action.item.id];
list[itemIndex] = action.item; list[itemIndex] = action.item;
return _extends({}, defaultState, { return _extends({}, state, {
list: list list: list
}); });
@ -4765,14 +4757,14 @@ function makeList(actionType, fetchURL) {
list = [].concat(_toConsumableArray(state.list)); list = [].concat(_toConsumableArray(state.list));
itemIndex = state.indexOf[action.item.id]; itemIndex = state.indexOf[action.item.id];
list.splice(itemIndex, 1); list.splice(itemIndex, 1);
return _extends({}, defaultState, { return _extends({}, state, {
list: list, list: list,
byId: _extends({}, state.byId, _defineProperty({}, action.item.id, undefined)), byId: _extends({}, state.byId, _defineProperty({}, action.item.id, undefined)),
indexOf: _extends({}, state.indexOf, _defineProperty({}, action.item.id, undefined)) indexOf: _extends({}, state.indexOf, _defineProperty({}, action.item.id, undefined))
}); });
case REQUEST_LIST: case REQUEST_LIST:
return _extends({}, defaultState, { return _extends({}, state, {
isFetching: true isFetching: true
}); });

File diff suppressed because it is too large Load Diff

View File

@ -21,8 +21,8 @@
"flux": "^2.1.1", "flux": "^2.1.1",
"jquery": "^2.2.3", "jquery": "^2.2.3",
"lodash": "^4.11.2", "lodash": "^4.11.2",
"react": "^15.0.2", "react": "^15.1.0",
"react-dom": "^15.0.2", "react-dom": "^15.1.0",
"react-redux": "^4.4.5", "react-redux": "^4.4.5",
"react-router": "^2.4.0", "react-router": "^2.4.0",
"redux": "^3.5.2", "redux": "^3.5.2",
@ -53,7 +53,6 @@
"gulp-sourcemaps": "^1.6.0", "gulp-sourcemaps": "^1.6.0",
"gulp-util": "^3.0.7", "gulp-util": "^3.0.7",
"jest": "^0.1.40", "jest": "^0.1.40",
"redux-thunk": "^2.1.0",
"uglifyify": "^3.0.1", "uglifyify": "^3.0.1",
"vinyl-buffer": "^1.0.0", "vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0", "vinyl-source-stream": "^1.1.0",

View File

@ -1,190 +1,121 @@
import React from "react"; import React from "react"
import {RequestUtils, ResponseUtils} from "../flow/utils.js"; import {RequestUtils, ResponseUtils} from "../flow/utils.js"
import {formatSize, formatTimeDelta} from "../utils.js"; import {formatSize, formatTimeDelta} from "../utils.js"
var TLSColumn = React.createClass({
statics: { function TLSColumn({flow}) {
Title: React.createClass({ let ssl = (flow.request.scheme === "https")
render: function(){ let classes
return <th {...this.props} className={"col-tls " + (this.props.className || "") }></th>; if (ssl) {
} classes = "col-tls col-tls-https"
}), } else {
sortKeyFun: function(flow){ classes = "col-tls col-tls-http"
return flow.request.scheme;
}
},
render: function () {
var flow = this.props.flow;
var ssl = (flow.request.scheme === "https");
var classes;
if (ssl) {
classes = "col-tls col-tls-https";
} else {
classes = "col-tls col-tls-http";
}
return <td className={classes}></td>;
} }
}); return <td className={classes}></td>
}
TLSColumn.Title = ({className = "", ...props}) => <th {...props} className={"col-tls " + className }></th>
TLSColumn.sortKeyFun = flow => flow.request.scheme
var IconColumn = React.createClass({ function IconColumn({flow}) {
statics: { let icon
Title: React.createClass({ if (flow.response) {
render: function(){ var contentType = ResponseUtils.getContentType(flow.response)
return <th {...this.props} className={"col-icon " + (this.props.className || "") }></th>;
}
})
},
render: function () {
var flow = this.props.flow;
var icon; //TODO: We should assign a type to the flow somewhere else.
if (flow.response) { if (flow.response.status_code === 304) {
var contentType = ResponseUtils.getContentType(flow.response); icon = "resource-icon-not-modified"
} else if (300 <= flow.response.status_code && flow.response.status_code < 400) {
//TODO: We should assign a type to the flow somewhere else. icon = "resource-icon-redirect"
if (flow.response.status_code === 304) { } else if (contentType && contentType.indexOf("image") >= 0) {
icon = "resource-icon-not-modified"; icon = "resource-icon-image"
} else if (300 <= flow.response.status_code && flow.response.status_code < 400) { } else if (contentType && contentType.indexOf("javascript") >= 0) {
icon = "resource-icon-redirect"; icon = "resource-icon-js"
} else if (contentType && contentType.indexOf("image") >= 0) { } else if (contentType && contentType.indexOf("css") >= 0) {
icon = "resource-icon-image"; icon = "resource-icon-css"
} else if (contentType && contentType.indexOf("javascript") >= 0) { } else if (contentType && contentType.indexOf("html") >= 0) {
icon = "resource-icon-js"; icon = "resource-icon-document"
} else if (contentType && contentType.indexOf("css") >= 0) {
icon = "resource-icon-css";
} else if (contentType && contentType.indexOf("html") >= 0) {
icon = "resource-icon-document";
}
} }
if (!icon) {
icon = "resource-icon-plain";
}
icon += " resource-icon";
return <td className="col-icon">
<div className={icon}></div>
</td>;
} }
}); if (!icon) {
icon = "resource-icon-plain"
var PathColumn = React.createClass({
statics: {
Title: React.createClass({
render: function(){
return <th {...this.props} className={"col-path " + (this.props.className || "") }>Path</th>;
}
}),
sortKeyFun: function(flow){
return RequestUtils.pretty_url(flow.request);
}
},
render: function () {
var flow = this.props.flow;
return <td className="col-path">
{flow.request.is_replay ? <i className="fa fa-fw fa-repeat pull-right"></i> : null}
{flow.intercepted ? <i className="fa fa-fw fa-pause pull-right"></i> : null}
{ RequestUtils.pretty_url(flow.request) }
</td>;
} }
});
icon += " resource-icon"
return <td className="col-icon">
<div className={icon}></div>
</td>
}
IconColumn.Title = ({className = "", ...props}) => <th {...props} className={"col-icon " + className }></th>
var MethodColumn = React.createClass({ function PathColumn({flow}) {
statics: { return <td className="col-path">
Title: React.createClass({ {flow.request.is_replay ? <i className="fa fa-fw fa-repeat pull-right"></i> : null}
render: function(){ {flow.intercepted ? <i className="fa fa-fw fa-pause pull-right"></i> : null}
return <th {...this.props} className={"col-method " + (this.props.className || "") }>Method</th>; { RequestUtils.pretty_url(flow.request) }
} </td>
}), }
sortKeyFun: function(flow){ PathColumn.Title = ({className = "", ...props}) =>
return flow.request.method; <th {...props} className={"col-path " + className }>Path</th>
} PathColumn.sortKeyFun = flow => RequestUtils.pretty_url(flow.request)
},
render: function () {
var flow = this.props.flow; function MethodColumn({flow}) {
return <td className="col-method">{flow.request.method}</td>; return <td className="col-method">{flow.request.method}</td>
}
MethodColumn.Title = ({className = "", ...props}) =>
<th {...props} className={"col-method " + className }>Method</th>
MethodColumn.sortKeyFun = flow => flow.request.method
function StatusColumn({flow}) {
let status
if (flow.response) {
status = flow.response.status_code
} else {
status = null
} }
}); return <td className="col-status">{status}</td>
}
StatusColumn.Title = ({className = "", ...props}) =>
<th {...props} className={"col-status " + className }>Status</th>
StatusColumn.sortKeyFun = flow => flow.response ? flow.response.status_code : undefined
var StatusColumn = React.createClass({ function SizeColumn({flow}) {
statics: { let total = flow.request.contentLength
Title: React.createClass({ if (flow.response) {
render: function(){ total += flow.response.contentLength || 0
return <th {...this.props} className={"col-status " + (this.props.className || "") }>Status</th>;
}
}),
sortKeyFun: function(flow){
return flow.response ? flow.response.status_code : undefined;
}
},
render: function () {
var flow = this.props.flow;
var status;
if (flow.response) {
status = flow.response.status_code;
} else {
status = null;
}
return <td className="col-status">{status}</td>;
} }
}); let size = formatSize(total)
return <td className="col-size">{size}</td>
}
var SizeColumn = React.createClass({ SizeColumn.Title = ({className = "", ...props}) =>
statics: { <th {...props} className={"col-size " + className }>Size</th>
Title: React.createClass({ SizeColumn.sortKeyFun = flow => {
render: function(){ let total = flow.request.contentLength
return <th {...this.props} className={"col-size " + (this.props.className || "") }>Size</th>; if (flow.response) {
} total += flow.response.contentLength || 0
}),
sortKeyFun: function(flow){
var total = flow.request.contentLength;
if (flow.response) {
total += flow.response.contentLength || 0;
}
return total;
}
},
render: function () {
var flow = this.props.flow;
var total = flow.request.contentLength;
if (flow.response) {
total += flow.response.contentLength || 0;
}
var size = formatSize(total);
return <td className="col-size">{size}</td>;
} }
}); return total
}
var TimeColumn = React.createClass({ function TimeColumn({flow}) {
statics: { let time
Title: React.createClass({ if (flow.response) {
render: function(){ time = formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start))
return <th {...this.props} className={"col-time " + (this.props.className || "") }>Time</th>; } else {
} time = "..."
}),
sortKeyFun: function(flow){
if(flow.response) {
return flow.response.timestamp_end - flow.request.timestamp_start;
}
}
},
render: function () {
var flow = this.props.flow;
var time;
if (flow.response) {
time = formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start));
} else {
time = "...";
}
return <td className="col-time">{time}</td>;
} }
}); return <td className="col-time">{time}</td>
}
TimeColumn.Title = ({className = "", ...props}) =>
<th {...props} className={"col-time " + className }>Time</th>
TimeColumn.sortKeyFun = flow => flow.response.timestamp_end - flow.request.timestamp_start
var all_columns = [ var all_columns = [
@ -195,6 +126,6 @@ var all_columns = [
StatusColumn, StatusColumn,
SizeColumn, SizeColumn,
TimeColumn TimeColumn
]; ]
export default all_columns; export default all_columns

View File

@ -19,21 +19,20 @@ FlowRow.propTypes = {
selected: React.PropTypes.bool, selected: React.PropTypes.bool,
}; };
function FlowRow(props) { function FlowRow({flow, selected, highlight, columns, selectFlow}) {
const flow = props.flow;
const className = classNames({ const className = classNames({
"selected": props.selected, "selected": selected,
"highlighted": props.highlight && parseFilter(props.highlight)(flow), "highlighted": highlight && parseFilter(highlight)(flow),
"intercepted": flow.intercepted, "intercepted": flow.intercepted,
"has-request": flow.request, "has-request": flow.request,
"has-response": flow.response, "has-response": flow.response,
}); });
return ( return (
<tr className={className} onClick={() => props.selectFlow(flow)}> <tr className={className} onClick={() => selectFlow(flow)}>
{props.columns.map(Column => ( {columns.map(Column => (
<Column key={Column.displayName} flow={flow}/> <Column key={Column.name} flow={flow}/>
))} ))}
</tr> </tr>
); );
@ -44,11 +43,8 @@ const FlowRowContainer = connect(
flow: state.flows.all.byId[ownProps.flowId], flow: state.flows.all.byId[ownProps.flowId],
highlight: state.flows.highlight, highlight: state.flows.highlight,
selected: state.flows.selected.indexOf(ownProps.flowId) >= 0 selected: state.flows.selected.indexOf(ownProps.flowId) >= 0
}),
(dispatch, ownProps) => ({
}) })
)(FlowRow); )(FlowRow)
class FlowTableHead extends React.Component { class FlowTableHead extends React.Component {
@ -59,7 +55,7 @@ class FlowTableHead extends React.Component {
constructor(props, context) { constructor(props, context) {
super(props, context); super(props, context);
this.state = { sortColumn: undefined, sortDesc: false }; this.state = {sortColumn: undefined, sortDesc: false};
} }
onClick(Column) { onClick(Column) {
@ -69,20 +65,20 @@ class FlowTableHead extends React.Component {
if (Column === this.state.sortColumn) { if (Column === this.state.sortColumn) {
sortDesc = !sortDesc; sortDesc = !sortDesc;
this.setState({ sortDesc }); this.setState({sortDesc});
} else { } else {
this.setState({ sortColumn: hasSort && Column, sortDesc: false }); this.setState({sortColumn: hasSort && Column, sortDesc: false});
} }
let sortKeyFun = Column.sortKeyFun; let sortKeyFun = Column.sortKeyFun;
if (sortDesc) { if (sortDesc) {
sortKeyFun = hasSort && function() { sortKeyFun = hasSort && function () {
const k = Column.sortKeyFun.apply(this, arguments); const k = Column.sortKeyFun.apply(this, arguments);
if (_.isString(k)) { if (_.isString(k)) {
return reverseString("" + k); return reverseString("" + k);
} }
return -k; return -k;
}; };
} }
this.props.setSortKeyFun(sortKeyFun); this.props.setSortKeyFun(sortKeyFun);
@ -95,9 +91,9 @@ class FlowTableHead extends React.Component {
<tr> <tr>
{this.props.columns.map(Column => ( {this.props.columns.map(Column => (
<Column.Title <Column.Title
key={Column.displayName} key={Column.name}
onClick={() => this.onClick(Column)} onClick={() => this.onClick(Column)}
className={sortColumn === Column && sortType} className={sortColumn === Column ? sortType : undefined}
/> />
))} ))}
</tr> </tr>
@ -118,7 +114,7 @@ class FlowTable extends React.Component {
constructor(props, context) { constructor(props, context) {
super(props, context); super(props, context);
this.state = { vScroll: calcVScroll() }; this.state = {vScroll: calcVScroll()};
this.onViewportUpdate = this.onViewportUpdate.bind(this); this.onViewportUpdate = this.onViewportUpdate.bind(this);
} }
@ -132,7 +128,7 @@ class FlowTable extends React.Component {
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if(nextProps.selected && nextProps.selected !== this.props.selected){ if (nextProps.selected && nextProps.selected !== this.props.selected) {
window.setTimeout(() => this.scrollIntoView(nextProps.selected), 1) window.setTimeout(() => this.scrollIntoView(nextProps.selected), 1)
} }
} }
@ -154,7 +150,7 @@ class FlowTable extends React.Component {
if (!shallowEqual(this.state.vScroll, vScroll) || if (!shallowEqual(this.state.vScroll, vScroll) ||
this.state.viewportTop !== viewportTop) { this.state.viewportTop !== viewportTop) {
this.setState({ vScroll, viewportTop }); this.setState({vScroll, viewportTop});
} }
} }
@ -190,22 +186,22 @@ class FlowTable extends React.Component {
<div className="flow-table" onScroll={this.onViewportUpdate}> <div className="flow-table" onScroll={this.onViewportUpdate}>
<table> <table>
<thead ref="head" style={{ transform }}> <thead ref="head" style={{ transform }}>
<FlowTableHead <FlowTableHead
columns={flowtable_columns} columns={flowtable_columns}
setSortKeyFun={this.props.setSortKeyFun} setSortKeyFun={this.props.setSortKeyFun}
/> />
</thead> </thead>
<tbody> <tbody>
<tr style={{ height: vScroll.paddingTop }}></tr> <tr style={{ height: vScroll.paddingTop }}></tr>
{flows.map(flow => ( {flows.map(flow => (
<FlowRowContainer <FlowRowContainer
key={flow.id} key={flow.id}
flowId={flow.id} flowId={flow.id}
columns={flowtable_columns} columns={flowtable_columns}
selectFlow={this.props.selectFlow} selectFlow={this.props.selectFlow}
/> />
))} ))}
<tr style={{ height: vScroll.paddingBottom }}></tr> <tr style={{ height: vScroll.paddingBottom }}></tr>
</tbody> </tbody>
</table> </table>
</div> </div>
@ -221,8 +217,6 @@ const parseFilter = _.memoize(Filt.parse)
const FlowTableContainer = connect( const FlowTableContainer = connect(
state => ({ state => ({
flows: state.flows.view, flows: state.flows.view,
}),
dispatch => ({
}) })
)(FlowTable) )(FlowTable)

View File

@ -62,7 +62,7 @@ export default function makeList(actionType, fetchURL) {
itemIndex = state.indexOf[action.item.id] itemIndex = state.indexOf[action.item.id]
list[itemIndex] = action.item list[itemIndex] = action.item
return { return {
...defaultState, ...state,
list list
} }
@ -71,7 +71,7 @@ export default function makeList(actionType, fetchURL) {
itemIndex = state.indexOf[action.item.id] itemIndex = state.indexOf[action.item.id]
list.splice(itemIndex, 1) list.splice(itemIndex, 1)
return { return {
...defaultState, ...state,
list, list,
byId: {...state.byId, [action.item.id]: undefined}, byId: {...state.byId, [action.item.id]: undefined},
indexOf: {...state.indexOf, [action.item.id]: undefined}, indexOf: {...state.indexOf, [action.item.id]: undefined},
@ -79,7 +79,7 @@ export default function makeList(actionType, fetchURL) {
case REQUEST_LIST: case REQUEST_LIST:
return { return {
...defaultState, ...state,
isFetching: true isFetching: true
} }