aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/web/static/app.js34
-rw-r--r--web/src/js/__tests__/ducks/ui.js120
-rw-r--r--web/src/js/__tests__/ducks/views/main.js82
-rw-r--r--web/src/js/components/ContentView.jsx108
-rw-r--r--web/src/js/components/ContentView/MetaViews.jsx2
-rw-r--r--web/src/js/components/ContentView/ViewSelector.jsx2
-rw-r--r--web/src/js/components/FlowView.jsx55
-rw-r--r--web/src/js/components/Header.jsx3
-rw-r--r--web/src/js/components/Header/FilterInput.jsx5
-rw-r--r--web/src/js/components/Header/MainMenu.jsx17
-rw-r--r--web/src/js/components/MainView.jsx139
-rwxr-xr-xweb/src/js/components/Prompt.jsx17
-rw-r--r--web/src/js/components/ProxyApp.jsx121
-rwxr-xr-xweb/src/js/components/ValueEditor.jsx12
-rw-r--r--web/src/js/ducks/ui.js248
-rwxr-xr-xweb/src/js/ducks/views/main.js31
16 files changed, 568 insertions, 428 deletions
diff --git a/mitmproxy/web/static/app.js b/mitmproxy/web/static/app.js
index a7d89322..27c7d1db 100644
--- a/mitmproxy/web/static/app.js
+++ b/mitmproxy/web/static/app.js
@@ -5,9 +5,9 @@
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}var _react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_redux=require("redux"),_reactRedux=require("react-redux"),_reduxThunk=require("redux-thunk"),_reduxThunk2=_interopRequireDefault(_reduxThunk),_reactRouter=require("react-router"),_ProxyApp=require("./components/ProxyApp"),_ProxyApp2=_interopRequireDefault(_ProxyApp),_MainView=require("./components/MainView"),_MainView2=_interopRequireDefault(_MainView),_index=require("./ducks/index"),_index2=_interopRequireDefault(_index),_eventLog=require("./ducks/eventLog"),middlewares=[_reduxThunk2["default"]],createLogger,store=(0,_redux.createStore)(_index2["default"],_redux.applyMiddleware.apply(void 0,middlewares));window.addEventListener("error",function(e){store.dispatch((0,_eventLog.add)(e))}),document.addEventListener("DOMContentLoaded",function(){(0,_reactDom.render)(_react2["default"].createElement(_reactRedux.Provider,{store:store,__self:void 0},_react2["default"].createElement(_reactRouter.Router,{history:_reactRouter.hashHistory,__self:void 0},_react2["default"].createElement(_reactRouter.Redirect,{from:"/",to:"/flows",__self:void 0}),_react2["default"].createElement(_reactRouter.Route,{path:"/",component:_ProxyApp2["default"],__self:void 0},_react2["default"].createElement(_reactRouter.Route,{path:"flows",component:_MainView2["default"],__self:void 0}),_react2["default"].createElement(_reactRouter.Route,{path:"flows/:flowId/:detailTab",component:_MainView2["default"],__self:void 0})))),document.getElementById("mitmproxy"))});
},{"./components/MainView":28,"./components/ProxyApp":30,"./ducks/eventLog":42,"./ducks/index":44,"react":"react","react-dom":"react-dom","react-redux":"react-redux","react-router":"react-router","redux":"redux","redux-thunk":"redux-thunk"}],3:[function(require,module,exports){
-"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},_createClass=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_utils=require("../flow/utils.js"),_ContentViews=require("./ContentView/ContentViews"),_MetaViews=require("./ContentView/MetaViews"),MetaViews=_interopRequireWildcard(_MetaViews),_ContentLoader=require("./ContentView/ContentLoader"),_ContentLoader2=_interopRequireDefault(_ContentLoader),_ViewSelector=require("./ContentView/ViewSelector"),_ViewSelector2=_interopRequireDefault(_ViewSelector),ContentView=function(e){function t(e,n){_classCallCheck(this,t);var r=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,n));return r.state={displayLarge:!1,View:_ContentViews.ViewAuto},r.selectView=r.selectView.bind(r),r}return _inherits(t,e),_createClass(t,[{key:"selectView",value:function(e){this.setState({View:e})}},{key:"displayLarge",value:function(){this.setState({displayLarge:!0})}},{key:"componentWillReceiveProps",value:function(e){e.message!==this.props.message&&this.setState({displayLarge:!1,View:_ContentViews.ViewAuto})}},{key:"isContentTooLarge",value:function(e){return e.contentLength>1048576*(_ContentViews.ViewImage.matches(e)?10:.2)}},{key:"render",value:function(){var e=this.props,t=e.flow,n=e.message,r=this.state,i=r.displayLarge,a=r.View;return 0===n.contentLength?_react2["default"].createElement(MetaViews.ContentEmpty,_extends({},this.props,{__self:this})):null===n.contentLength?_react2["default"].createElement(MetaViews.ContentMissing,_extends({},this.props,{__self:this})):!i&&this.isContentTooLarge(n)?_react2["default"].createElement(MetaViews.ContentTooLarge,_extends({},this.props,{onClick:this.displayLarge,__self:this})):_react2["default"].createElement("div",{__self:this},a.textView?_react2["default"].createElement(_ContentLoader2["default"],{flow:t,message:n,__self:this},_react2["default"].createElement(this.state.View,{content:"",__self:this})):_react2["default"].createElement(a,{flow:t,message:n,__self:this}),_react2["default"].createElement("div",{className:"view-options text-center",__self:this},_react2["default"].createElement(_ViewSelector2["default"],{onSelectView:this.selectView,active:a,message:n,__self:this})," ",_react2["default"].createElement("a",{className:"btn btn-default btn-xs",href:_utils.MessageUtils.getContentURL(t,n),__self:this},_react2["default"].createElement("i",{className:"fa fa-download",__self:this}))))}}]),t}(_react.Component);ContentView.propTypes={flow:_react2["default"].PropTypes.object.isRequired,message:_react2["default"].PropTypes.object.isRequired},exports["default"]=ContentView;
+"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function ContentView(e){var t=e.flow,n=e.message,r=e.contentView,i=e.selectView,a=e.displayLarge,s=e.setDisplayLarge;if(0===n.contentLength)return _react2["default"].createElement(MetaViews.ContentEmpty,_extends({},e,{__self:this}));if(null===n.contentLength)return _react2["default"].createElement(MetaViews.ContentMissing,_extends({},e,{__self:this}));if(!a&&ContentView.isContentTooLarge(n))return _react2["default"].createElement(MetaViews.ContentTooLarge,_extends({},e,{onClick:function(){return s(!0)},__self:this}));var o=ContentViews[r];return _react2["default"].createElement("div",{__self:this},o.textView?_react2["default"].createElement(_ContentLoader2["default"],{flow:t,message:n,__self:this},_react2["default"].createElement(o,{content:"",__self:this})):_react2["default"].createElement(o,{flow:t,message:n,__self:this}),_react2["default"].createElement("div",{className:"view-options text-center",__self:this},_react2["default"].createElement(_ViewSelector2["default"],{onSelectView:i,active:o,message:n,__self:this})," ",_react2["default"].createElement("a",{className:"btn btn-default btn-xs",href:_utils.MessageUtils.getContentURL(t,n),__self:this},_react2["default"].createElement("i",{className:"fa fa-download",__self:this}))))}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_utils=require("../flow/utils.js"),_ContentViews=require("./ContentView/ContentViews"),ContentViews=_interopRequireWildcard(_ContentViews),_MetaViews=require("./ContentView/MetaViews"),MetaViews=_interopRequireWildcard(_MetaViews),_ContentLoader=require("./ContentView/ContentLoader"),_ContentLoader2=_interopRequireDefault(_ContentLoader),_ViewSelector=require("./ContentView/ViewSelector"),_ViewSelector2=_interopRequireDefault(_ViewSelector),_ui=require("../ducks/ui");ContentView.propTypes={flow:_react2["default"].PropTypes.object.isRequired,message:_react2["default"].PropTypes.object.isRequired},ContentView.isContentTooLarge=function(e){return e.contentLength>1048576*(ContentViews.ViewImage.matches(e)?10:.2)},exports["default"]=(0,_reactRedux.connect)(function(e){return{contentView:e.ui.contentView,displayLarge:e.ui.displayLarge}},{selectView:_ui.setContentView,setDisplayLarge:_ui.setDisplayLarge})(ContentView);
-},{"../flow/utils.js":54,"./ContentView/ContentLoader":4,"./ContentView/ContentViews":5,"./ContentView/MetaViews":6,"./ContentView/ViewSelector":7,"react":"react"}],4:[function(require,module,exports){
+},{"../ducks/ui":47,"../flow/utils.js":54,"./ContentView/ContentLoader":4,"./ContentView/ContentViews":5,"./ContentView/MetaViews":6,"./ContentView/ViewSelector":7,"react":"react","react-redux":"react-redux"}],4:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_utils=require("../../flow/utils.js"),_jquery=require("jquery"),_jquery2=_interopRequireDefault(_jquery),ContentLoader=function(e){function t(e,n){_classCallCheck(this,t);var r=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,n));return r.state={content:null,request:null},r}return _inherits(t,e),_createClass(t,[{key:"requestContent",value:function(e){var t=this;this.state.request&&this.state.request.abort();var n=_utils.MessageUtils.getContentURL(e.flow,e.message),r=_jquery2["default"].get(n);this.setState({content:null,request:r}),r.done(function(e){t.setState({content:e})}).fail(function(e,n,r){"abort"!==n&&t.setState({content:"AJAX Error: "+n+"\r\n"+r})}).always(function(){t.setState({request:null})})}},{key:"componentWillMount",value:function(){this.requestContent(this.props)}},{key:"componentWillReceiveProps",value:function(e){e.message!==this.props.message&&this.requestContent(e)}},{key:"componentWillUnmount",value:function(){this.state.request&&this.state.request.abort()}},{key:"render",value:function(){return this.state.content?_react2["default"].cloneElement(this.props.children,{content:this.state.content}):_react2["default"].createElement("div",{className:"text-center",__self:this},_react2["default"].createElement("i",{className:"fa fa-spinner fa-spin",__self:this}))}}]),t}(_react.Component);ContentLoader.propTypes={flow:_react.PropTypes.object.isRequired,message:_react.PropTypes.object.isRequired},exports["default"]=ContentLoader;
},{"../../flow/utils.js":54,"jquery":"jquery","react":"react"}],5:[function(require,module,exports){
@@ -17,7 +17,7 @@
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function ContentEmpty(e){var t=e.flow,n=e.message;return _react2["default"].createElement("div",{className:"alert alert-info",__self:this},"No ",t.request===n?"request":"response"," content.")}function ContentMissing(e){var t=e.flow,n=e.message;return _react2["default"].createElement("div",{className:"alert alert-info",__self:this},t.request===n?"Request":"Response"," content missing.")}function ContentTooLarge(e){var t=e.message,n=e.onClick;return _react2["default"].createElement("div",{className:"alert alert-warning",__self:this},_react2["default"].createElement("button",{onClick:n,className:"btn btn-xs btn-warning pull-right",__self:this},"Display anyway"),(0,_utils.formatSize)(t.contentLength)," content size.")}Object.defineProperty(exports,"__esModule",{value:!0}),exports.ContentEmpty=ContentEmpty,exports.ContentMissing=ContentMissing,exports.ContentTooLarge=ContentTooLarge;var _react=require("react"),_react2=_interopRequireDefault(_react),_utils=require("../../utils.js");
},{"../../utils.js":55,"react":"react"}],7:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function ViewSelector(e){var t=this,r=e.active,a=e.message,n=e.onSelectView;return _react2["default"].createElement("div",{className:"view-selector btn-group btn-group-xs",__self:this},_ContentViews2["default"].map(function(e){return _react2["default"].createElement("button",{key:e.name,onClick:function(){return n(e)},className:(0,_classnames2["default"])("btn btn-default",{active:e===r}),__self:t},e===_ContentViews.ViewAuto?"auto: "+_ContentViews.ViewAuto.findView(a).name.toLowerCase().replace("view",""):e.name.toLowerCase().replace("view",""))}))}Object.defineProperty(exports,"__esModule",{value:!0}),exports["default"]=ViewSelector;var _react=require("react"),_react2=_interopRequireDefault(_react),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_ContentViews=require("./ContentViews"),_ContentViews2=_interopRequireDefault(_ContentViews);ViewSelector.propTypes={active:_react.PropTypes.func.isRequired,message:_react.PropTypes.object.isRequired,onSelectView:_react.PropTypes.func.isRequired};
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function ViewSelector(e){var t=this,r=e.active,a=e.message,n=e.onSelectView;return _react2["default"].createElement("div",{className:"view-selector btn-group btn-group-xs",__self:this},_ContentViews2["default"].map(function(e){return _react2["default"].createElement("button",{key:e.name,onClick:function(){return n(e.name)},className:(0,_classnames2["default"])("btn btn-default",{active:e===r}),__self:t},e===_ContentViews.ViewAuto?"auto: "+_ContentViews.ViewAuto.findView(a).name.toLowerCase().replace("view",""):e.name.toLowerCase().replace("view",""))}))}Object.defineProperty(exports,"__esModule",{value:!0}),exports["default"]=ViewSelector;var _react=require("react"),_react2=_interopRequireDefault(_react),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_ContentViews=require("./ContentViews"),_ContentViews2=_interopRequireDefault(_ContentViews);ViewSelector.propTypes={active:_react.PropTypes.func.isRequired,message:_react.PropTypes.object.isRequired,onSelectView:_react.PropTypes.func.isRequired};
},{"./ContentViews":5,"classnames":"classnames","react":"react"}],8:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_eventLog=require("../ducks/eventLog"),_ToggleButton=require("./common/ToggleButton"),_ToggleButton2=_interopRequireDefault(_ToggleButton),_EventList=require("./EventLog/EventList"),_EventList2=_interopRequireDefault(_EventList),EventLog=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,r));return n.state={height:n.props.defaultHeight},n.onDragStart=n.onDragStart.bind(n),n.onDragMove=n.onDragMove.bind(n),n.onDragStop=n.onDragStop.bind(n),n}return _inherits(t,e),_createClass(t,[{key:"onDragStart",value:function(e){e.preventDefault(),this.dragStart=this.state.height+e.pageY,window.addEventListener("mousemove",this.onDragMove),window.addEventListener("mouseup",this.onDragStop),window.addEventListener("dragend",this.onDragStop)}},{key:"onDragMove",value:function(e){e.preventDefault(),this.setState({height:this.dragStart-e.pageY})}},{key:"onDragStop",value:function(e){e.preventDefault(),window.removeEventListener("mousemove",this.onDragMove)}},{key:"render",value:function(){var e=this,t=this.state.height,r=this.props,n=r.filters,o=r.events,a=r.toggleFilter,i=r.close;return _react2["default"].createElement("div",{className:"eventlog",style:{height:t},__self:this},_react2["default"].createElement("div",{onMouseDown:this.onDragStart,__self:this},"Eventlog",_react2["default"].createElement("div",{className:"pull-right",__self:this},["debug","info","web"].map(function(t){return _react2["default"].createElement(_ToggleButton2["default"],{key:t,text:t,checked:n[t],onToggle:function(){return a(t)},__self:e})}),_react2["default"].createElement("i",{onClick:i,className:"fa fa-close",__self:this}))),_react2["default"].createElement(_EventList2["default"],{events:o,__self:this}))}}]),t}(_react.Component);EventLog.propTypes={filters:_react.PropTypes.object.isRequired,events:_react.PropTypes.array.isRequired,toggleFilter:_react.PropTypes.func.isRequired,close:_react.PropTypes.func.isRequired,defaultHeight:_react.PropTypes.number},EventLog.defaultProps={defaultHeight:200},exports["default"]=(0,_reactRedux.connect)(function(e){return{filters:e.eventLog.filters,events:e.eventLog.view.data}},{close:_eventLog.toggleVisibility,toggleFilter:_eventLog.toggleFilter})(EventLog);
@@ -38,9 +38,9 @@
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function FlowTableHead(e){var r=this,t=e.sortColumn,a=e.sortDesc,s=e.updateSort,o=a?"sort-desc":"sort-asc";return _react2["default"].createElement("tr",{__self:this},_FlowColumns2["default"].map(function(e){return _react2["default"].createElement("th",{className:(0,_classnames2["default"])(e.headerClass,t===e.name&&o),key:e.name,onClick:function(){return s(e.name,e.name===t&&!a)},__self:r},e.headerName)}))}Object.defineProperty(exports,"__esModule",{value:!0});var _react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_FlowColumns=require("./FlowColumns"),_FlowColumns2=_interopRequireDefault(_FlowColumns),_main=require("../../ducks/views/main");FlowTableHead.propTypes={updateSort:_react.PropTypes.func.isRequired,sortDesc:_react2["default"].PropTypes.bool.isRequired,sortColumn:_react2["default"].PropTypes.string},exports["default"]=(0,_reactRedux.connect)(function(e){return{sortDesc:e.flows.views.main.sort.desc,sortColumn:e.flows.views.main.sort.column}},{updateSort:_main.updateSort})(FlowTableHead);
},{"../../ducks/views/main":51,"./FlowColumns":11,"classnames":"classnames","react":"react","react-redux":"react-redux"}],14:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},_createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,r,o){return r&&e(t.prototype,r),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_Nav=require("./FlowView/Nav"),_Nav2=_interopRequireDefault(_Nav),_Messages=require("./FlowView/Messages"),_Details=require("./FlowView/Details"),_Details2=_interopRequireDefault(_Details),_Prompt=require("./Prompt"),_Prompt2=_interopRequireDefault(_Prompt),FlowView=function(e){function t(e,r){_classCallCheck(this,t);var o=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,r));return o.state={prompt:!1},o.closePrompt=o.closePrompt.bind(o),o.selectTab=o.selectTab.bind(o),o}return _inherits(t,e),_createClass(t,[{key:"getTabs",value:function(){var e=this;return["request","response","error"].filter(function(t){return e.props.flow[t]}).concat(["details"])}},{key:"nextTab",value:function(e){var t=this.getTabs();this.selectTab(t[(t.indexOf(this.props.tab)+e+t.length)%t.length])}},{key:"selectTab",value:function(e){this.props.updateLocation("/flows/"+this.props.flow.id+"/"+e)}},{key:"closePrompt",value:function(e){this.setState({prompt:!1}),e&&this.tabComponent&&this.tabComponent.edit(e)}},{key:"promptEdit",value:function(){var e=void 0;switch(this.props.tab){case"request":e=["method","url",{text:"http version",key:"v"},"header"];break;case"response":e=[{text:"http version",key:"v"},"code","message","header"];break;case"details":return;default:throw"Unknown tab for edit: "+this.props.tab}this.setState({prompt:{options:e,done:this.closePrompt}})}},{key:"render",value:function(){var e=this,r=this.getTabs(),o=this.props,s=o.flow,a=o.tab,n=o.updateFlow;r.indexOf(a)<0&&(a="response"===a&&s.error?"error":"error"===a&&s.response?"response":r[0]);var i=t.allTabs[_lodash2["default"].capitalize(a)];return _react2["default"].createElement("div",{className:"flow-detail",onScroll:this.adjustHead,__self:this},_react2["default"].createElement(_Nav2["default"],{flow:s,tabs:r,active:a,onSelectTab:this.selectTab,__self:this}),_react2["default"].createElement(i,{ref:function(t){return e.tabComponent=t},flow:s,updateFlow:n,__self:this}),this.state.prompt&&_react2["default"].createElement(_Prompt2["default"],_extends({},this.state.prompt,{__self:this})))}}]),t}(_react.Component);FlowView.allTabs={Request:_Messages.Request,Response:_Messages.Response,Error:_Messages.ErrorView,Details:_Details2["default"]},exports["default"]=FlowView;
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,r,o){return r&&e(t.prototype,r),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_Nav=require("./FlowView/Nav"),_Nav2=_interopRequireDefault(_Nav),_Messages=require("./FlowView/Messages"),_Details=require("./FlowView/Details"),_Details2=_interopRequireDefault(_Details),_Prompt=require("./Prompt"),_Prompt2=_interopRequireDefault(_Prompt),_ui=require("../ducks/ui"),FlowView=function(e){function t(e,r){_classCallCheck(this,t);var o=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,r));return o.onPromptFinish=o.onPromptFinish.bind(o),o}return _inherits(t,e),_createClass(t,[{key:"onPromptFinish",value:function(e){this.props.setPrompt(!1),e&&this.tabComponent&&this.tabComponent.edit(e)}},{key:"getPromptOptions",value:function(){switch(this.props.tab){case"request":return["method","url",{text:"http version",key:"v"},"header"];case"response":return[{text:"http version",key:"v"},"code","message","header"];case"details":return;default:throw"Unknown tab for edit: "+this.props.tab}}},{key:"render",value:function(){var e=this,r=this.props,o=r.flow,s=r.tab,n=r.updateFlow,a=["request","response","error"].filter(function(e){return o[e]}).concat(["details"]);a.indexOf(s)<0&&(s="response"===s&&o.error?"error":"error"===s&&o.response?"response":a[0]);var i=t.allTabs[_lodash2["default"].capitalize(s)];return _react2["default"].createElement("div",{className:"flow-detail",onScroll:this.adjustHead,__self:this},_react2["default"].createElement(_Nav2["default"],{flow:o,tabs:a,active:s,onSelectTab:this.props.selectTab,__self:this}),_react2["default"].createElement(i,{ref:function(t){return e.tabComponent=t},flow:o,updateFlow:n,__self:this}),this.props.promptOpen&&_react2["default"].createElement(_Prompt2["default"],{options:this.getPromptOptions(),done:this.onPromptFinish,__self:this}))}}]),t}(_react.Component);FlowView.allTabs={Request:_Messages.Request,Response:_Messages.Response,Error:_Messages.ErrorView,Details:_Details2["default"]},exports["default"]=FlowView,exports["default"]=(0,_reactRedux.connect)(function(e){return{promptOpen:e.ui.promptOpen}},{setPrompt:_ui.setPrompt,selectTab:_ui.selectTab})(FlowView);
-},{"./FlowView/Details":15,"./FlowView/Messages":17,"./FlowView/Nav":18,"./Prompt":29,"lodash":"lodash","react":"react"}],15:[function(require,module,exports){
+},{"../ducks/ui":47,"./FlowView/Details":15,"./FlowView/Messages":17,"./FlowView/Nav":18,"./Prompt":29,"lodash":"lodash","react":"react","react-redux":"react-redux"}],15:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function TimeStamp(e){var t=e.t,a=e.deltaTo,r=e.title;return t?_react2["default"].createElement("tr",{__self:this},_react2["default"].createElement("td",{__self:this},r,":"),_react2["default"].createElement("td",{__self:this},(0,_utils.formatTimeStamp)(t),a&&_react2["default"].createElement("span",{className:"text-muted",__self:this},"(",(0,_utils.formatTimeDelta)(1e3*(t-a)),")"))):_react2["default"].createElement("tr",{__self:this})}function ConnectionInfo(e){var t=e.conn;return _react2["default"].createElement("table",{className:"connection-table",__self:this},_react2["default"].createElement("tbody",{__self:this},_react2["default"].createElement("tr",{key:"address",__self:this},_react2["default"].createElement("td",{__self:this},"Address:"),_react2["default"].createElement("td",{__self:this},t.address.address.join(":"))),t.sni&&_react2["default"].createElement("tr",{key:"sni",__self:this},_react2["default"].createElement("td",{__self:this},_react2["default"].createElement("abbr",{title:"TLS Server Name Indication",__self:this},"TLS SNI:")),_react2["default"].createElement("td",{__self:this},t.sni))))}function CertificateInfo(e){var t=e.flow;return _react2["default"].createElement("div",{__self:this},t.client_conn.cert&&[_react2["default"].createElement("h4",{key:"name",__self:this},"Client Certificate"),_react2["default"].createElement("pre",{key:"value",style:{maxHeight:100},__self:this},t.client_conn.cert)],t.server_conn.cert&&[_react2["default"].createElement("h4",{key:"name",__self:this},"Server Certificate"),_react2["default"].createElement("pre",{key:"value",style:{maxHeight:100},__self:this},t.server_conn.cert)])}function Timing(e){var t=this,a=e.flow,r=a.server_conn,n=a.client_conn,l=a.request,s=a.response,i=[{title:"Server conn. initiated",t:r.timestamp_start,deltaTo:l.timestamp_start},{title:"Server conn. TCP handshake",t:r.timestamp_tcp_setup,deltaTo:l.timestamp_start},{title:"Server conn. SSL handshake",t:r.timestamp_ssl_setup,deltaTo:l.timestamp_start},{title:"Client conn. established",t:n.timestamp_start,deltaTo:l.timestamp_start},{title:"Client conn. SSL handshake",t:n.timestamp_ssl_setup,deltaTo:l.timestamp_start},{title:"First request byte",t:l.timestamp_start},{title:"Request complete",t:l.timestamp_end,deltaTo:l.timestamp_start},s&&{title:"First response byte",t:s.timestamp_start,deltaTo:l.timestamp_start},s&&{title:"Response complete",t:s.timestamp_end,deltaTo:l.timestamp_start}];return _react2["default"].createElement("div",{__self:this},_react2["default"].createElement("h4",{__self:this},"Timing"),_react2["default"].createElement("table",{className:"timing-table",__self:this},_react2["default"].createElement("tbody",{__self:this},i.filter(function(e){return e}).sort(function(e,t){return e.t-t.t}).map(function(e){return _react2["default"].createElement(TimeStamp,_extends({key:e.title},e,{__self:t}))}))))}function Details(e){var t=e.flow;return _react2["default"].createElement("section",{__self:this},_react2["default"].createElement("h4",{__self:this},"Client Connection"),_react2["default"].createElement(ConnectionInfo,{conn:t.client_conn,__self:this}),_react2["default"].createElement("h4",{__self:this},"Server Connection"),_react2["default"].createElement(ConnectionInfo,{conn:t.server_conn,__self:this}),_react2["default"].createElement(CertificateInfo,{flow:t,__self:this}),_react2["default"].createElement(Timing,{flow:t,__self:this}))}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var a=arguments[t];for(var r in a)Object.prototype.hasOwnProperty.call(a,r)&&(e[r]=a[r])}return e};exports.TimeStamp=TimeStamp,exports.ConnectionInfo=ConnectionInfo,exports.CertificateInfo=CertificateInfo,exports.Timing=Timing,exports["default"]=Details;var _react=require("react"),_react2=_interopRequireDefault(_react),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_utils=require("../../utils.js");
},{"../../utils.js":55,"lodash":"lodash","react":"react"}],16:[function(require,module,exports){
@@ -56,7 +56,7 @@
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function Footer(e){var t=e.settings;return _react2["default"].createElement("footer",{__self:this},t.mode&&"regular"!=t.mode&&_react2["default"].createElement("span",{className:"label label-success",__self:this},t.mode," mode"),t.intercept&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"Intercept: ",t.intercept),t.showhost&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"showhost"),t.no_upstream_cert&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"no-upstream-cert"),t.rawtcp&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"raw-tcp"),!t.http2&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"no-http2"),t.anticache&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"anticache"),t.anticomp&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"anticomp"),t.stickyauth&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"stickyauth: ",t.stickyauth),t.stickycookie&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"stickycookie: ",t.stickycookie),t.stream&&_react2["default"].createElement("span",{className:"label label-success",__self:this},"stream: ",(0,_utils.formatSize)(t.stream)))}Object.defineProperty(exports,"__esModule",{value:!0});var _react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_utils=require("../utils.js");Footer.propTypes={settings:_react2["default"].PropTypes.object.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{settings:e.settings.settings}})(Footer);
},{"../utils.js":55,"react":"react","react-redux":"react-redux"}],20:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,r=Array(e.length);t<e.length;t++)r[t]=e[t];return r}return Array.from(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_MainMenu=require("./Header/MainMenu"),_MainMenu2=_interopRequireDefault(_MainMenu),_ViewMenu=require("./Header/ViewMenu"),_ViewMenu2=_interopRequireDefault(_ViewMenu),_OptionMenu=require("./Header/OptionMenu"),_OptionMenu2=_interopRequireDefault(_OptionMenu),_FileMenu=require("./Header/FileMenu"),_FileMenu2=_interopRequireDefault(_FileMenu),_FlowMenu=require("./Header/FlowMenu"),_FlowMenu2=_interopRequireDefault(_FlowMenu),_ui=require("../ducks/ui.js"),Header=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,Object.getPrototypeOf(t).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"handleClick",value:function(e,t){t.preventDefault(),this.props.setActiveMenu(e.title)}},{key:"render",value:function(){var e=this,r=this.props,n=r.updateLocation,u=r.query,a=r.selectedFlow,i=r.activeMenu,l=[].concat(_toConsumableArray(t.entries));a&&l.push(_FlowMenu2["default"]);var o=_.find(l,function(e){return e.title==i});return _react2["default"].createElement("header",{__self:this},_react2["default"].createElement("nav",{className:"nav-tabs nav-tabs-lg",__self:this},_react2["default"].createElement(_FileMenu2["default"],{__self:this}),l.map(function(t){return _react2["default"].createElement("a",{key:t.title,href:"#",className:(0,_classnames2["default"])({active:t===o}),onClick:function(r){return e.handleClick(t,r)},__self:e},t.title)})),_react2["default"].createElement("div",{className:"menu",__self:this},_react2["default"].createElement(o,{ref:"active",updateLocation:n,query:u,__self:this})))}}]),t}(_react.Component);Header.entries=[_MainMenu2["default"],_ViewMenu2["default"],_OptionMenu2["default"]],exports["default"]=(0,_reactRedux.connect)(function(e){return{selectedFlow:e.flows.views.main.selected[0],activeMenu:e.ui.activeMenu}},{setActiveMenu:_ui.setActiveMenu},null,{withRef:!0})(Header);
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,r=Array(e.length);t<e.length;t++)r[t]=e[t];return r}return Array.from(e)}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_MainMenu=require("./Header/MainMenu"),_MainMenu2=_interopRequireDefault(_MainMenu),_ViewMenu=require("./Header/ViewMenu"),_ViewMenu2=_interopRequireDefault(_ViewMenu),_OptionMenu=require("./Header/OptionMenu"),_OptionMenu2=_interopRequireDefault(_OptionMenu),_FileMenu=require("./Header/FileMenu"),_FileMenu2=_interopRequireDefault(_FileMenu),_FlowMenu=require("./Header/FlowMenu"),_FlowMenu2=_interopRequireDefault(_FlowMenu),_ui=require("../ducks/ui.js"),Header=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,Object.getPrototypeOf(t).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"handleClick",value:function(e,t){t.preventDefault(),this.props.setActiveMenu(e.title)}},{key:"render",value:function(){var e=this,r=this.props,n=r.query,u=r.selectedFlow,a=r.activeMenu,i=[].concat(_toConsumableArray(t.entries));u&&i.push(_FlowMenu2["default"]);var l=_.find(i,function(e){return e.title==a});return _react2["default"].createElement("header",{__self:this},_react2["default"].createElement("nav",{className:"nav-tabs nav-tabs-lg",__self:this},_react2["default"].createElement(_FileMenu2["default"],{__self:this}),i.map(function(t){return _react2["default"].createElement("a",{key:t.title,href:"#",className:(0,_classnames2["default"])({active:t===l}),onClick:function(r){return e.handleClick(t,r)},__self:e},t.title)})),_react2["default"].createElement("div",{className:"menu",__self:this},_react2["default"].createElement(l,{ref:"active",query:n,__self:this})))}}]),t}(_react.Component);Header.entries=[_MainMenu2["default"],_ViewMenu2["default"],_OptionMenu2["default"]],exports["default"]=(0,_reactRedux.connect)(function(e){return{selectedFlow:e.flows.views.main.selected[0],activeMenu:e.ui.activeMenu}},{setActiveMenu:_ui.setActiveMenu},null,{withRef:!0})(Header);
},{"../ducks/ui.js":47,"./Header/FileMenu":21,"./Header/FlowMenu":24,"./Header/MainMenu":25,"./Header/OptionMenu":26,"./Header/ViewMenu":27,"classnames":"classnames","react":"react","react-redux":"react-redux"}],21:[function(require,module,exports){
"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&(t[l]=e[l]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var l=0;l<t.length;l++){var n=t[l];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,l,n){return l&&e(t.prototype,l),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_flows=require("../../ducks/flows"),flowsActions=_interopRequireWildcard(_flows),FileMenu=function(e){function t(e,l){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,l));return n.state={show:!1},n.close=n.close.bind(n),n.onFileClick=n.onFileClick.bind(n),n.onNewClick=n.onNewClick.bind(n),n.onOpenClick=n.onOpenClick.bind(n),n.onOpenFile=n.onOpenFile.bind(n),n.onSaveClick=n.onSaveClick.bind(n),n}return _inherits(t,e),_createClass(t,[{key:"close",value:function(){this.setState({show:!1}),document.removeEventListener("click",this.close)}},{key:"onFileClick",value:function(e){e.preventDefault(),this.state.show||(document.addEventListener("click",this.close),this.setState({show:!0}))}},{key:"onNewClick",value:function(e){e.preventDefault(),confirm("Delete all flows?")&&this.props.clearFlows()}},{key:"onOpenClick",value:function(e){e.preventDefault(),this.fileInput.click()}},{key:"onOpenFile",value:function(e){e.preventDefault(),e.target.files.length>0&&(this.props.loadFlows(e.target.files[0]),this.fileInput.value="")}},{key:"onSaveClick",value:function(e){e.preventDefault(),this.props.saveFlows()}},{key:"render",value:function(){var e=this;return _react2["default"].createElement("div",{className:(0,_classnames2["default"])("dropdown pull-left",{open:this.state.show}),__self:this},_react2["default"].createElement("a",{href:"#",className:"special",onClick:this.onFileClick,__self:this},"mitmproxy"),_react2["default"].createElement("ul",{className:"dropdown-menu",role:"menu",__self:this},_react2["default"].createElement("li",{__self:this},_react2["default"].createElement("a",{href:"#",onClick:this.onNewClick,__self:this},_react2["default"].createElement("i",{className:"fa fa-fw fa-file",__self:this}),"New")),_react2["default"].createElement("li",{__self:this},_react2["default"].createElement("a",{href:"#",onClick:this.onOpenClick,__self:this},_react2["default"].createElement("i",{className:"fa fa-fw fa-folder-open",__self:this}),"Open..."),_react2["default"].createElement("input",{ref:function(t){return e.fileInput=t},className:"hidden",type:"file",onChange:this.onOpenFile,__self:this})),_react2["default"].createElement("li",{__self:this},_react2["default"].createElement("a",{href:"#",onClick:this.onSaveClick,__self:this},_react2["default"].createElement("i",{className:"fa fa-fw fa-floppy-o",__self:this}),"Save...")),_react2["default"].createElement("li",{role:"presentation",className:"divider",__self:this}),_react2["default"].createElement("li",{__self:this},_react2["default"].createElement("a",{href:"http://mitm.it/",target:"_blank",__self:this},_react2["default"].createElement("i",{className:"fa fa-fw fa-external-link",__self:this}),"Install Certificates..."))))}}]),t}(_react.Component);exports["default"]=(0,_reactRedux.connect)(null,{clearFlows:flowsActions.clear,loadFlows:flowsActions.upload,saveFlows:flowsActions.download})(FileMenu);
@@ -65,31 +65,31 @@
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_utils=require("../../utils"),FilterDocs=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,r));return n.state={doc:t.doc},n}return _inherits(t,e),_createClass(t,[{key:"componentWillMount",value:function(){var e=this;t.xhr||(t.xhr=(0,_utils.fetchApi)("/filter-help").then(function(e){return e.json()}),t.xhr["catch"](function(){t.xhr=null})),this.state.doc||t.xhr.then(function(r){t.doc=r,e.setState({doc:r})})}},{key:"render",value:function(){var e=this,t=this.state.doc;return t?_react2["default"].createElement("table",{className:"table table-condensed",__self:this},_react2["default"].createElement("tbody",{__self:this},t.commands.map(function(t){return _react2["default"].createElement("tr",{key:t[1],__self:e},_react2["default"].createElement("td",{__self:e},t[0].replace(" "," ")),_react2["default"].createElement("td",{__self:e},t[1]))}),_react2["default"].createElement("tr",{key:"docs-link",__self:this},_react2["default"].createElement("td",{colSpan:"2",__self:this},_react2["default"].createElement("a",{href:"http://docs.mitmproxy.org/en/stable/features/filters.html",target:"_blank",__self:this},_react2["default"].createElement("i",{className:"fa fa-external-link",__self:this}),"&nbsp mitmproxy docs"))))):_react2["default"].createElement("i",{className:"fa fa-spinner fa-spin",__self:this})}}]),t}(_react.Component);FilterDocs.xhr=null,FilterDocs.doc=null,exports["default"]=FilterDocs;
},{"../../utils":55,"react":"react"}],23:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_utils=require("../../utils.js"),_filt=require("../../filt/filt"),_filt2=_interopRequireDefault(_filt),_FilterDocs=require("./FilterDocs"),_FilterDocs2=_interopRequireDefault(_FilterDocs),FilterInput=function(e){function t(e,n){_classCallCheck(this,t);var o=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,n));return o.state={value:o.props.value,focus:!1,mousefocus:!1},o.onChange=o.onChange.bind(o),o.onFocus=o.onFocus.bind(o),o.onBlur=o.onBlur.bind(o),o.onKeyDown=o.onKeyDown.bind(o),o.onMouseEnter=o.onMouseEnter.bind(o),o.onMouseLeave=o.onMouseLeave.bind(o),o}return _inherits(t,e),_createClass(t,[{key:"componentWillReceiveProps",value:function(e){this.setState({value:e.value})}},{key:"isValid",value:function(e){try{var t=null==e?this.state.value:e;return t&&_filt2["default"].parse(t),!0}catch(n){return!1}}},{key:"getDesc",value:function(){if(!this.state.value)return _react2["default"].createElement(_FilterDocs2["default"],{__self:this});try{return _filt2["default"].parse(this.state.value).desc}catch(e){return""+e}}},{key:"onChange",value:function(e){var t=e.target.value;this.setState({value:t}),this.isValid(t)&&this.props.onChange(t)}},{key:"onFocus",value:function(){this.setState({focus:!0})}},{key:"onBlur",value:function(){this.setState({focus:!1})}},{key:"onMouseEnter",value:function(){this.setState({mousefocus:!0})}},{key:"onMouseLeave",value:function(){this.setState({mousefocus:!1})}},{key:"onKeyDown",value:function(e){e.keyCode!==_utils.Key.ESC&&e.keyCode!==_utils.Key.ENTER||(this.blur(),this.setState({mousefocus:!1})),e.stopPropagation()}},{key:"blur",value:function(){_reactDom2["default"].findDOMNode(this.refs.input).blur(),this.context.returnFocus()}},{key:"select",value:function(){_reactDom2["default"].findDOMNode(this.refs.input).select()}},{key:"render",value:function(){var e=this.props,t=e.type,n=e.color,o=e.placeholder,r=this.state,s=r.value,a=r.focus,u=r.mousefocus;return _react2["default"].createElement("div",{className:(0,_classnames2["default"])("filter-input input-group",{"has-error":!this.isValid()}),__self:this},_react2["default"].createElement("span",{className:"input-group-addon",__self:this},_react2["default"].createElement("i",{className:"fa fa-fw fa-"+t,style:{color:n},__self:this})),_react2["default"].createElement("input",{type:"text",ref:"input",placeholder:o,className:"form-control",value:s,onChange:this.onChange,onFocus:this.onFocus,onBlur:this.onBlur,onKeyDown:this.onKeyDown,__self:this}),(a||u)&&_react2["default"].createElement("div",{className:"popover bottom",onMouseEnter:this.onMouseEnter,onMouseLeave:this.onMouseLeave,__self:this},_react2["default"].createElement("div",{className:"arrow",__self:this}),_react2["default"].createElement("div",{className:"popover-content",__self:this},this.getDesc())))}}]),t}(_react.Component);FilterInput.contextTypes={returnFocus:_react2["default"].PropTypes.func},exports["default"]=FilterInput;
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_utils=require("../../utils.js"),_filt=require("../../filt/filt"),_filt2=_interopRequireDefault(_filt),_FilterDocs=require("./FilterDocs"),_FilterDocs2=_interopRequireDefault(_FilterDocs),FilterInput=function(e){function t(e,n){_classCallCheck(this,t);var o=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,n));return o.state={value:o.props.value,focus:!1,mousefocus:!1},o.onChange=o.onChange.bind(o),o.onFocus=o.onFocus.bind(o),o.onBlur=o.onBlur.bind(o),o.onKeyDown=o.onKeyDown.bind(o),o.onMouseEnter=o.onMouseEnter.bind(o),o.onMouseLeave=o.onMouseLeave.bind(o),o}return _inherits(t,e),_createClass(t,[{key:"componentWillReceiveProps",value:function(e){this.setState({value:e.value})}},{key:"isValid",value:function(e){try{var t=null==e?this.state.value:e;return t&&_filt2["default"].parse(t),!0}catch(n){return!1}}},{key:"getDesc",value:function(){if(!this.state.value)return _react2["default"].createElement(_FilterDocs2["default"],{__self:this});try{return _filt2["default"].parse(this.state.value).desc}catch(e){return""+e}}},{key:"onChange",value:function(e){var t=e.target.value;this.setState({value:t}),this.isValid(t)&&this.props.onChange(t)}},{key:"onFocus",value:function(){this.setState({focus:!0})}},{key:"onBlur",value:function(){this.setState({focus:!1})}},{key:"onMouseEnter",value:function(){this.setState({mousefocus:!0})}},{key:"onMouseLeave",value:function(){this.setState({mousefocus:!1})}},{key:"onKeyDown",value:function(e){e.keyCode!==_utils.Key.ESC&&e.keyCode!==_utils.Key.ENTER||(this.blur(),this.setState({mousefocus:!1})),e.stopPropagation()}},{key:"blur",value:function(){_reactDom2["default"].findDOMNode(this.refs.input).blur()}},{key:"select",value:function(){_reactDom2["default"].findDOMNode(this.refs.input).select()}},{key:"render",value:function(){var e=this.props,t=e.type,n=e.color,o=e.placeholder,r=this.state,s=r.value,a=r.focus,u=r.mousefocus;return _react2["default"].createElement("div",{className:(0,_classnames2["default"])("filter-input input-group",{"has-error":!this.isValid()}),__self:this},_react2["default"].createElement("span",{className:"input-group-addon",__self:this},_react2["default"].createElement("i",{className:"fa fa-fw fa-"+t,style:{color:n},__self:this})),_react2["default"].createElement("input",{type:"text",ref:"input",placeholder:o,className:"form-control",value:s,onChange:this.onChange,onFocus:this.onFocus,onBlur:this.onBlur,onKeyDown:this.onKeyDown,__self:this}),(a||u)&&_react2["default"].createElement("div",{className:"popover bottom",onMouseEnter:this.onMouseEnter,onMouseLeave:this.onMouseLeave,__self:this},_react2["default"].createElement("div",{className:"arrow",__self:this}),_react2["default"].createElement("div",{className:"popover-content",__self:this},this.getDesc())))}}]),t}(_react.Component);exports["default"]=FilterInput;
},{"../../filt/filt":53,"../../utils.js":55,"./FilterDocs":22,"classnames":"classnames","react":"react","react-dom":"react-dom"}],24:[function(require,module,exports){
"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&(t[l]=e[l]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function FlowMenu(e){var t=e.flow,l=e.acceptFlow,o=e.replayFlow,r=e.duplicateFlow,n=e.removeFlow,a=e.revertFlow;return _react2["default"].createElement("div",{__self:this},_react2["default"].createElement("div",{className:"menu-row",__self:this},_react2["default"].createElement(_Button2["default"],{disabled:!t.intercepted,title:"[a]ccept intercepted flow",text:"Accept",icon:"fa-play",onClick:function(){return l(t)},__self:this}),_react2["default"].createElement(_Button2["default"],{title:"[r]eplay flow",text:"Replay",icon:"fa-repeat",onClick:function(){return o(t)},__self:this}),_react2["default"].createElement(_Button2["default"],{title:"[D]uplicate flow",text:"Duplicate",icon:"fa-copy",onClick:function(){return r(t)},__self:this}),_react2["default"].createElement(_Button2["default"],{title:"[d]elete flow",text:"Delete",icon:"fa-trash",onClick:function(){return n(t)},__self:this}),_react2["default"].createElement(_Button2["default"],{disabled:!t.modified,title:"revert changes to flow [V]",text:"Revert",icon:"fa-history",onClick:function(){return a(t)},__self:this}),_react2["default"].createElement(_Button2["default"],{title:"download",text:"Download",icon:"fa-download",onClick:function(){return window.location=_utils.MessageUtils.getContentURL(t,t.response)},__self:this})),_react2["default"].createElement("div",{className:"clearfix",__self:this}))}Object.defineProperty(exports,"__esModule",{value:!0});var _react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_Button=require("../common/Button"),_Button2=_interopRequireDefault(_Button),_utils=require("../../flow/utils.js"),_flows=require("../../ducks/flows"),flowsActions=_interopRequireWildcard(_flows);FlowMenu.title="Flow",FlowMenu.propTypes={flow:_react.PropTypes.object.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{flow:e.flows.list.byId[e.flows.views.main.selected[0]]}},{acceptFlow:flowsActions.accept,replayFlow:flowsActions.replay,duplicateFlow:flowsActions.duplicate,removeFlow:flowsActions.remove,revertFlow:flowsActions.revert})(FlowMenu);
},{"../../ducks/flows":43,"../../flow/utils.js":54,"../common/Button":34,"react":"react","react-redux":"react-redux"}],25:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _defineProperty(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_FilterInput=require("./FilterInput"),_FilterInput2=_interopRequireDefault(_FilterInput),_actions=require("../../actions.js"),_settings=require("../../ducks/settings"),MainMenu=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,r));return n.onSearchChange=n.onSearchChange.bind(n),n.onHighlightChange=n.onHighlightChange.bind(n),n}return _inherits(t,e),_createClass(t,[{key:"onSearchChange",value:function(e){this.props.updateLocation(void 0,_defineProperty({},_actions.Query.SEARCH,e))}},{key:"onHighlightChange",value:function(e){this.props.updateLocation(void 0,_defineProperty({},_actions.Query.HIGHLIGHT,e))}},{key:"render",value:function(){var e=this.props,t=e.query,r=e.settings,n=e.updateSettings;return _react2["default"].createElement("div",{__self:this},_react2["default"].createElement("div",{className:"menu-row",__self:this},_react2["default"].createElement(_FilterInput2["default"],{ref:"search",placeholder:"Search",type:"search",color:"black",value:t[_actions.Query.SEARCH]||"",onChange:this.onSearchChange,__self:this}),_react2["default"].createElement(_FilterInput2["default"],{ref:"highlight",placeholder:"Highlight",type:"tag",color:"hsl(48, 100%, 50%)",value:t[_actions.Query.HIGHLIGHT]||"",onChange:this.onHighlightChange,__self:this}),_react2["default"].createElement(_FilterInput2["default"],{ref:"intercept",placeholder:"Intercept",type:"pause",color:"hsl(208, 56%, 53%)",value:r.intercept||"",onChange:function(e){return n({intercept:e})},__self:this})),_react2["default"].createElement("div",{className:"clearfix",__self:this}))}}]),t}(_react.Component);MainMenu.title="Start",MainMenu.route="flows",MainMenu.propTypes={query:_react.PropTypes.object.isRequired,settings:_react.PropTypes.object.isRequired,updateLocation:_react.PropTypes.func.isRequired,updateSettings:_react.PropTypes.func.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{settings:e.settings.settings}},{updateSettings:_settings.update},null,{withRef:!0})(MainMenu);
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _defineProperty(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_FilterInput=require("./FilterInput"),_FilterInput2=_interopRequireDefault(_FilterInput),_actions=require("../../actions.js"),_settings=require("../../ducks/settings"),_ui=require("../../ducks/ui"),MainMenu=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,r));return n.onSearchChange=n.onSearchChange.bind(n),n.onHighlightChange=n.onHighlightChange.bind(n),n}return _inherits(t,e),_createClass(t,[{key:"componentWillReceiveProps",value:function(e){this.refs[e.selectedInput]&&this.refs[e.selectedInput].select(),this.props.setSelectedInput(void 0)}},{key:"onSearchChange",value:function(e){this.props.updateQuery(_defineProperty({},_actions.Query.SEARCH,e))}},{key:"onHighlightChange",value:function(e){this.props.updateQuery(_defineProperty({},_actions.Query.HIGHLIGHT,e))}},{key:"render",value:function(){var e=this.props,t=e.query,r=e.settings,n=e.updateSettings;return _react2["default"].createElement("div",{__self:this},_react2["default"].createElement("div",{className:"menu-row",__self:this},_react2["default"].createElement(_FilterInput2["default"],{ref:"search",placeholder:"Search",type:"search",color:"black",value:t[_actions.Query.SEARCH]||"",onChange:this.onSearchChange,__self:this}),_react2["default"].createElement(_FilterInput2["default"],{ref:"highlight",placeholder:"Highlight",type:"tag",color:"hsl(48, 100%, 50%)",value:t[_actions.Query.HIGHLIGHT]||"",onChange:this.onHighlightChange,__self:this}),_react2["default"].createElement(_FilterInput2["default"],{ref:"intercept",placeholder:"Intercept",type:"pause",color:"hsl(208, 56%, 53%)",value:r.intercept||"",onChange:function(e){return n({intercept:e})},__self:this})),_react2["default"].createElement("div",{className:"clearfix",__self:this}))}}]),t}(_react.Component);MainMenu.title="Start",MainMenu.route="flows",MainMenu.propTypes={query:_react.PropTypes.object.isRequired,settings:_react.PropTypes.object.isRequired,updateSettings:_react.PropTypes.func.isRequired,updateQuery:_react.PropTypes.func.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{settings:e.settings.settings,selectedInput:e.ui.selectedInput}},{updateSettings:_settings.update,updateQuery:_ui.updateQuery,setSelectedInput:_ui.setSelectedInput},null,{withRef:!0})(MainMenu);
-},{"../../actions.js":1,"../../ducks/settings":46,"./FilterInput":23,"react":"react","react-redux":"react-redux"}],26:[function(require,module,exports){
+},{"../../actions.js":1,"../../ducks/settings":46,"../../ducks/ui":47,"./FilterInput":23,"react":"react","react-redux":"react-redux"}],26:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function OptionMenu(e){var t=e.settings,n=e.onSettingsChange;return _react2["default"].createElement("div",{__self:this},_react2["default"].createElement("div",{className:"menu-row",__self:this},_react2["default"].createElement(_ToggleButton2["default"],{text:"showhost",checked:t.showhost,onToggle:function(){return n({showhost:!t.showhost})},__self:this}),_react2["default"].createElement(_ToggleButton2["default"],{text:"no_upstream_cert",checked:t.no_upstream_cert,onToggle:function(){return n({no_upstream_cert:!t.no_upstream_cert})},__self:this}),_react2["default"].createElement(_ToggleButton2["default"],{text:"rawtcp",checked:t.rawtcp,onToggle:function(){return n({rawtcp:!t.rawtcp})},__self:this}),_react2["default"].createElement(_ToggleButton2["default"],{text:"http2",checked:t.http2,onToggle:function(){return n({http2:!t.http2})},__self:this}),_react2["default"].createElement(_ToggleButton2["default"],{text:"anticache",checked:t.anticache,onToggle:function(){return n({anticache:!t.anticache})},__self:this}),_react2["default"].createElement(_ToggleButton2["default"],{text:"anticomp",checked:t.anticomp,onToggle:function(){return n({anticomp:!t.anticomp})},__self:this}),_react2["default"].createElement(_ToggleInputButton2["default"],{name:"stickyauth",placeholder:"Sticky auth filter",checked:!!t.stickyauth,txt:t.stickyauth||"",onToggleChanged:function(e){return n({stickyauth:t.stickyauth?null:e})},__self:this}),_react2["default"].createElement(_ToggleInputButton2["default"],{name:"stickycookie",placeholder:"Sticky cookie filter",checked:!!t.stickycookie,txt:t.stickycookie||"",onToggleChanged:function(e){return n({stickycookie:t.stickycookie?null:e})},__self:this}),_react2["default"].createElement(_ToggleInputButton2["default"],{name:"stream",placeholder:"stream...",checked:!!t.stream,txt:t.stream||"",inputType:"number",onToggleChanged:function(e){return n({stream:t.stream?null:e})},__self:this})),_react2["default"].createElement("div",{className:"clearfix",__self:this}))}Object.defineProperty(exports,"__esModule",{value:!0});var _react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_ToggleButton=require("../common/ToggleButton"),_ToggleButton2=_interopRequireDefault(_ToggleButton),_ToggleInputButton=require("../common/ToggleInputButton"),_ToggleInputButton2=_interopRequireDefault(_ToggleInputButton),_settings=require("../../ducks/settings");OptionMenu.title="Options",OptionMenu.propTypes={settings:_react.PropTypes.object.isRequired,onSettingsChange:_react.PropTypes.func.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{settings:e.settings.settings}},{onSettingsChange:_settings.update})(OptionMenu);
},{"../../ducks/settings":46,"../common/ToggleButton":36,"../common/ToggleInputButton":37,"react":"react","react-redux":"react-redux"}],27:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function ViewMenu(e){var t=e.eventLogVisible,r=e.toggleEventLog;return _react2["default"].createElement("div",{__self:this},_react2["default"].createElement("div",{className:"menu-row",__self:this},_react2["default"].createElement(_ToggleButton2["default"],{text:"Show Event Log",checked:t,onToggle:r,__self:this})),_react2["default"].createElement("div",{className:"clearfix",__self:this}))}Object.defineProperty(exports,"__esModule",{value:!0});var _react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_ToggleButton=require("../common/ToggleButton"),_ToggleButton2=_interopRequireDefault(_ToggleButton),_eventLog=require("../../ducks/eventLog");ViewMenu.title="View",ViewMenu.route="flows",ViewMenu.propTypes={eventLogVisible:_react.PropTypes.bool.isRequired,toggleEventLog:_react.PropTypes.func.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{eventLogVisible:e.eventLog.visible}},{toggleEventLog:_eventLog.toggleVisibility})(ViewMenu);
},{"../../ducks/eventLog":42,"../common/ToggleButton":36,"react":"react","react-redux":"react-redux"}],28:[function(require,module,exports){
-"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var l in e)Object.prototype.hasOwnProperty.call(e,l)&&(t[l]=e[l]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var l=0;l<t.length;l++){var i=t[l];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,l,i){return l&&e(t.prototype,l),i&&e(t,i),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_actions=require("../actions.js"),_utils=require("../utils.js"),_Splitter=require("./common/Splitter"),_Splitter2=_interopRequireDefault(_Splitter),_FlowTable=require("./FlowTable"),_FlowTable2=_interopRequireDefault(_FlowTable),_FlowView=require("./FlowView"),_FlowView2=_interopRequireDefault(_FlowView),_flows=require("../ducks/flows"),flowsActions=_interopRequireWildcard(_flows),_main=require("../ducks/views/main"),MainView=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,Object.getPrototypeOf(t).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"componentWillReceiveProps",value:function(e){e.routeParams.flowId!==(e.selectedFlow||{}).id&&this.props.selectFlow(e.routeParams.flowId),e.location.query[_actions.Query.SEARCH]!==e.filter&&this.props.updateFilter(e.location.query[_actions.Query.SEARCH],!1),e.location.query[_actions.Query.HIGHLIGHT]!==e.highlight&&this.props.updateHighlight(e.location.query[_actions.Query.HIGHLIGHT],!1)}},{key:"selectFlow",value:function(e){e?this.props.updateLocation("/flows/"+e.id+"/"+(this.props.routeParams.detailTab||"request")):this.props.updateLocation("/flows")}},{key:"selectFlowRelative",value:function(e){var t=this.props,l=t.flows,i=t.routeParams,s=t.selectedFlow,r=0;i.flowId?r=Math.min(Math.max(0,l.indexOf(s)+e),l.length-1):e<0&&(r=l.length-1),this.selectFlow(l[r])}},{key:"onMainKeyDown",value:function(e){var t=this.props.selectedFlow;if(!e.ctrlKey){switch(e.keyCode){case _utils.Key.K:case _utils.Key.UP:this.selectFlowRelative(-1);break;case _utils.Key.J:case _utils.Key.DOWN:this.selectFlowRelative(1);break;case _utils.Key.SPACE:case _utils.Key.PAGE_DOWN:this.selectFlowRelative(10);break;case _utils.Key.PAGE_UP:this.selectFlowRelative(-10);break;case _utils.Key.END:this.selectFlowRelative(1e10);break;case _utils.Key.HOME:this.selectFlowRelative(-1e10);break;case _utils.Key.ESC:this.selectFlow(null);break;case _utils.Key.H:case _utils.Key.LEFT:this.refs.flowDetails&&this.refs.flowDetails.nextTab(-1);break;case _utils.Key.L:case _utils.Key.TAB:case _utils.Key.RIGHT:this.refs.flowDetails&&this.refs.flowDetails.nextTab(1);break;case _utils.Key.C:e.shiftKey&&this.props.clearFlows();break;case _utils.Key.D:t&&(e.shiftKey?this.props.duplicateFlow(t):this.props.removeFlow(t));break;case _utils.Key.A:e.shiftKey?this.props.acceptAllFlows():t&&t.intercepted&&this.props.acceptFlow(t);break;case _utils.Key.R:!e.shiftKey&&t&&this.props.replayFlow(t);break;case _utils.Key.V:e.shiftKey&&t&&t.modified&&this.props.revertFlow(t);break;case _utils.Key.E:this.refs.flowDetails&&this.refs.flowDetails.promptEdit();break;case _utils.Key.SHIFT:break;default:return void console.debug("keydown",e.keyCode)}e.preventDefault()}}},{key:"render",value:function(){var e=this,t=this.props,l=t.flows,i=t.selectedFlow,s=t.highlight;return _react2["default"].createElement("div",{className:"main-view",__self:this},_react2["default"].createElement(_FlowTable2["default"],{ref:"flowTable",flows:l,selected:i,highlight:s,onSelect:function(t){return e.selectFlow(t)},__self:this}),i&&[_react2["default"].createElement(_Splitter2["default"],{key:"splitter",__self:this}),_react2["default"].createElement(_FlowView2["default"],{key:"flowDetails",ref:"flowDetails",tab:this.props.routeParams.detailTab,query:this.props.query,updateLocation:this.props.updateLocation,updateFlow:function(t){return e.props.updateFlow(i,t)},flow:i,__self:this})])}}]),t}(_react.Component);MainView.propTypes={highlight:_react.PropTypes.string,sort:_react.PropTypes.object},exports["default"]=(0,_reactRedux.connect)(function(e){return{flows:e.flows.views.main.view.data,filter:e.flows.views.main.filter,highlight:e.flows.views.main.highlight,selectedFlow:e.flows.list.byId[e.flows.views.main.selected[0]]}},{selectFlow:_main.select,updateFilter:_main.updateFilter,updateHighlight:_main.updateHighlight,updateFlow:flowsActions.update,clearFlows:flowsActions.clear,duplicateFlow:flowsActions.duplicate,removeFlow:flowsActions.remove,acceptAllFlows:flowsActions.acceptAll,acceptFlow:flowsActions.accept,replayFlow:flowsActions.replay,revertFlow:flowsActions.revert},void 0,{withRef:!0})(MainView);
+"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var i=t[r];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,r,i){return r&&e(t.prototype,r),i&&e(t,i),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactRedux=require("react-redux"),_actions=require("../actions.js"),_utils=require("../utils.js"),_Splitter=require("./common/Splitter"),_Splitter2=_interopRequireDefault(_Splitter),_FlowTable=require("./FlowTable"),_FlowTable2=_interopRequireDefault(_FlowTable),_FlowView=require("./FlowView"),_FlowView2=_interopRequireDefault(_FlowView),_flows=require("../ducks/flows"),flowsActions=_interopRequireWildcard(_flows),_main=require("../ducks/views/main"),MainView=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,Object.getPrototypeOf(t).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"componentWillReceiveProps",value:function(e){e.location.query[_actions.Query.SEARCH]!==e.filter&&this.props.updateFilter(e.location.query[_actions.Query.SEARCH],!1),e.location.query[_actions.Query.HIGHLIGHT]!==e.highlight&&this.props.updateHighlight(e.location.query[_actions.Query.HIGHLIGHT],!1)}},{key:"render",value:function(){var e=this,t=this.props,r=t.flows,i=t.selectedFlow,o=t.highlight;return _react2["default"].createElement("div",{className:"main-view",__self:this},_react2["default"].createElement(_FlowTable2["default"],{ref:"flowTable",flows:r,selected:i,highlight:o,onSelect:function(t){return e.props.selectFlow(t.id)},__self:this}),i&&[_react2["default"].createElement(_Splitter2["default"],{key:"splitter",__self:this}),_react2["default"].createElement(_FlowView2["default"],{key:"flowDetails",ref:"flowDetails",tab:this.props.routeParams.detailTab,query:this.props.query,updateFlow:function(t){return e.props.updateFlow(i,t)},flow:i,__self:this})])}}]),t}(_react.Component);MainView.propTypes={highlight:_react.PropTypes.string,sort:_react.PropTypes.object},exports["default"]=(0,_reactRedux.connect)(function(e){return{flows:e.flows.views.main.view.data,filter:e.flows.views.main.filter,highlight:e.flows.views.main.highlight,selectedFlow:e.flows.list.byId[e.flows.views.main.selected[0]]}},{selectFlow:_main.select,updateFilter:_main.updateFilter,updateHighlight:_main.updateHighlight,updateFlow:flowsActions.update},void 0,{withRef:!0})(MainView);
},{"../actions.js":1,"../ducks/flows":43,"../ducks/views/main":51,"../utils.js":55,"./FlowTable":10,"./FlowView":14,"./common/Splitter":35,"react":"react","react-redux":"react-redux"}],29:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function Prompt(e,t){function r(e){return _lodash2["default"].map(u,"key").includes(e)}function o(e){e.stopPropagation(),e.preventDefault();var r=u.find(function(t){return _utils.Key[t.key.toUpperCase()]===e.keyCode});(r||e.keyCode===_utils.Key.ESC||e.keyCode===_utils.Key.ENTER)&&(n(r.key||!1),t.returnFocus())}for(var a=this,s=e.prompt,n=e.done,i=e.options,u=[],l=0;l<i.length;l++){var p=i[l];if(_lodash2["default"].isString(p)){for(var c=p;c.length>0&&r(c[0]);)c=c.substr(1);p={text:p,key:c[0]}}if(!p.text||!p.key||r(p.key))throw"invalid options";u.push(p)}return _react2["default"].createElement("div",{tabIndex:"0",onKeyDown:o,className:"prompt-dialog",__self:this},_react2["default"].createElement("div",{className:"prompt-content",__self:this},s||_react2["default"].createElement("strong",{__self:this},"Select: "),u.map(function(e){function t(t){n(e.key),t.stopPropagation()}var r=e.text.indexOf(e.key);return _react2["default"].createElement("span",{key:e.key,className:"option",onClick:t,__self:a},r!==-1?e.text.substring(0,r):e.text+"(",_react2["default"].createElement("strong",{className:"text-primary",__self:a},e.key),r!==-1?e.text.substring(r+1):")")})))}Object.defineProperty(exports,"__esModule",{value:!0}),exports["default"]=Prompt;var _react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_utils=require("../utils.js");Prompt.contextTypes={returnFocus:_react.PropTypes.func},Prompt.propTypes={options:_react.PropTypes.array.isRequired,done:_react.PropTypes.func.isRequired,prompt:_react.PropTypes.string};
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function Prompt(e){function t(e){return _lodash2["default"].map(i,"key").includes(e)}function r(e){e.stopPropagation(),e.preventDefault();var t=i.find(function(t){return _utils.Key[t.key.toUpperCase()]===e.keyCode});(t||e.keyCode===_utils.Key.ESC||e.keyCode===_utils.Key.ENTER)&&s(t.key||!1)}for(var a=this,o=e.prompt,s=e.done,n=e.options,i=[],u=0;u<n.length;u++){var l=n[u];if(_lodash2["default"].isString(l)){for(var p=l;p.length>0&&t(p[0]);)p=p.substr(1);l={text:l,key:p[0]}}if(!l.text||!l.key||t(l.key))throw"invalid options";i.push(l)}return _react2["default"].createElement("div",{tabIndex:"0",onKeyDown:r,className:"prompt-dialog",__self:this},_react2["default"].createElement("div",{className:"prompt-content",__self:this},o||_react2["default"].createElement("strong",{__self:this},"Select: "),i.map(function(e){function t(t){s(e.key),t.stopPropagation()}var r=e.text.indexOf(e.key);return _react2["default"].createElement("span",{key:e.key,className:"option",onClick:t,__self:a},r!==-1?e.text.substring(0,r):e.text+"(",_react2["default"].createElement("strong",{className:"text-primary",__self:a},e.key),r!==-1?e.text.substring(r+1):")")})))}Object.defineProperty(exports,"__esModule",{value:!0}),exports["default"]=Prompt;var _react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_utils=require("../utils.js");Prompt.propTypes={options:_react.PropTypes.array.isRequired,done:_react.PropTypes.func.isRequired,prompt:_react.PropTypes.string};
},{"../utils.js":55,"lodash":"lodash","react":"react","react-dom":"react-dom"}],30:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_reactRedux=require("react-redux"),_app=require("../ducks/app"),_Header=require("./Header"),_Header2=_interopRequireDefault(_Header),_EventLog=require("./EventLog"),_EventLog2=_interopRequireDefault(_EventLog),_Footer=require("./Footer"),_Footer2=_interopRequireDefault(_Footer),_utils=require("../utils.js"),ProxyAppMain=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e,r));return n.focus=n.focus.bind(n),n.onKeyDown=n.onKeyDown.bind(n),n.updateLocation=n.updateLocation.bind(n),n}return _inherits(t,e),_createClass(t,[{key:"componentWillMount",value:function(){this.props.appInit()}},{key:"componentDidMount",value:function(){this.focus()}},{key:"componentWillUnmount",value:function(){this.props.appDestruct()}},{key:"getChildContext",value:function(){return{returnFocus:this.focus}}},{key:"focus",value:function(){document.activeElement.blur(),window.getSelection().removeAllRanges(),_reactDom2["default"].findDOMNode(this).focus()}},{key:"onKeyDown",value:function(e){var t=this,r=null;switch(e.keyCode){case _utils.Key.I:r="intercept";break;case _utils.Key.L:r="search";break;case _utils.Key.H:r="highlight";break;default:var n=this.refs.view;return this.refs.view.refs.wrappedInstance&&(n=this.refs.view.refs.wrappedInstance),void(n.onMainKeyDown&&n.onMainKeyDown(e))}r&&!function(){var e=t.refs.header.refs.wrappedInstance||t.refs.header;e.setState({active:_Header2["default"].entries[0]},function(){var t=e.refs.active.refs.wrappedInstance||e.refs.active;t.refs[r].select()})}(),e.preventDefault()}},{key:"updateLocation",value:function(e,t){void 0===e&&(e=this.props.location.pathname);var r=this.props.location.query,n=!0,o=!1,a=void 0;try{for(var i,u=Object.keys(t||{})[Symbol.iterator]();!(n=(i=u.next()).done);n=!0){var s=i.value;r[s]=t[s]||void 0}}catch(c){o=!0,a=c}finally{try{!n&&u["return"]&&u["return"]()}finally{if(o)throw a}}this.context.router.replace({pathname:e,query:r})}},{key:"getQuery",value:function(){return _lodash2["default"].clone(this.props.location.query)}},{key:"render",value:function(){var e=this.props,t=e.showEventLog,r=e.location,n=e.children,o=this.getQuery();return _react2["default"].createElement("div",{id:"container",tabIndex:"0",onKeyDown:this.onKeyDown,__self:this},_react2["default"].createElement(_Header2["default"],{ref:"header",updateLocation:this.updateLocation,query:o,__self:this}),_react2["default"].cloneElement(n,{ref:"view",location:r,query:o,updateLocation:this.updateLocation}),t&&_react2["default"].createElement(_EventLog2["default"],{key:"eventlog",__self:this}),_react2["default"].createElement(_Footer2["default"],{__self:this}))}}]),t}(_react.Component);ProxyAppMain.childContextTypes={returnFocus:_react.PropTypes.func.isRequired},ProxyAppMain.contextTypes={router:_react.PropTypes.object.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{showEventLog:e.eventLog.visible,settings:e.settings.settings}},{appInit:_app.init,appDestruct:_app.destruct})(ProxyAppMain);
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,r,o){return r&&e(t.prototype,r),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),_reactRedux=require("react-redux"),_app=require("../ducks/app"),_ui=require("../ducks/ui"),_Header=require("./Header"),_Header2=_interopRequireDefault(_Header),_EventLog=require("./EventLog"),_EventLog2=_interopRequireDefault(_EventLog),_Footer=require("./Footer"),_Footer2=_interopRequireDefault(_Footer),_utils=require("../utils.js"),ProxyAppMain=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,Object.getPrototypeOf(t).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"componentWillMount",value:function(){this.props.appInit(this.context.router),window.addEventListener("keydown",this.props.onKeyDown)}},{key:"componentWillUnmount",value:function(){this.props.appDestruct(this.context.router),window.removeEventListener("keydown",this.props.onKeyDown)}},{key:"componentWillReceiveProps",value:function(e){e.query===this.props.query&&e.selectedFlowId===this.props.selectedFlowId&&e.panel===this.props.panel||(e.selectedFlowId?this.context.router.replace({pathname:"/flows/"+e.selectedFlowId+"/"+e.panel,query:e.query}):this.context.router.replace({pathname:"/flows",query:e.query}))}},{key:"render",value:function(){var e=this.props,t=e.showEventLog,r=e.location,o=e.children,n=e.query;return _react2["default"].createElement("div",{id:"container",tabIndex:"0",__self:this},_react2["default"].createElement(_Header2["default"],{ref:"header",query:n,__self:this}),_react2["default"].cloneElement(o,{ref:"view",location:r,query:n}),t&&_react2["default"].createElement(_EventLog2["default"],{key:"eventlog",__self:this}),_react2["default"].createElement(_Footer2["default"],{__self:this}))}}]),t}(_react.Component);ProxyAppMain.contextTypes={router:_react.PropTypes.object.isRequired},exports["default"]=(0,_reactRedux.connect)(function(e){return{showEventLog:e.eventLog.visible,query:e.ui.query,panel:e.ui.panel,selectedFlowId:e.flows.views.main.selected[0]}},{appInit:_app.init,appDestruct:_app.destruct,onKeyDown:_ui.onKeyDown})(ProxyAppMain);
-},{"../ducks/app":41,"../utils.js":55,"./EventLog":8,"./Footer":19,"./Header":20,"lodash":"lodash","react":"react","react-dom":"react-dom","react-redux":"react-redux"}],31:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},_createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,r,o){return r&&e(t.prototype,r),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_ValidateEditor=require("./ValueEditor/ValidateEditor"),_ValidateEditor2=_interopRequireDefault(_ValidateEditor),ValueEditor=function(e){function t(e){_classCallCheck(this,t);var r=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e));return r.focus=r.focus.bind(r),r}return _inherits(t,e),_createClass(t,[{key:"render",value:function(){var e=this,t=this.props.inline?"span":"div";return _react2["default"].createElement(_ValidateEditor2["default"],_extends({},this.props,{onStop:function(){return e.context.returnFocus()},tag:t,__self:this}))}},{key:"focus",value:function(){_reactDom2["default"].findDOMNode(this).focus()}}]),t}(_react.Component);ValueEditor.contextTypes={returnFocus:_react.PropTypes.func},ValueEditor.propTypes={content:_react.PropTypes.string.isRequired,onDone:_react.PropTypes.func.isRequired,inline:_react.PropTypes.bool},exports["default"]=ValueEditor;
+},{"../ducks/app":41,"../ducks/ui":47,"../utils.js":55,"./EventLog":8,"./Footer":19,"./Header":20,"lodash":"lodash","react":"react","react-dom":"react-dom","react-redux":"react-redux"}],31:[function(require,module,exports){
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},_createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,r,o){return r&&e(t.prototype,r),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_ValidateEditor=require("./ValueEditor/ValidateEditor"),_ValidateEditor2=_interopRequireDefault(_ValidateEditor),ValueEditor=function(e){function t(){return _classCallCheck(this,t),_possibleConstructorReturn(this,Object.getPrototypeOf(t).apply(this,arguments))}return _inherits(t,e),_createClass(t,[{key:"render",value:function(){var e=this.props.inline?"span":"div";return _react2["default"].createElement(_ValidateEditor2["default"],_extends({},this.props,{tag:e,__self:this}))}},{key:"focus",value:function(){_reactDom2["default"].findDOMNode(this).focus()}}]),t}(_react.Component);ValueEditor.propTypes={content:_react.PropTypes.string.isRequired,onDone:_react.PropTypes.func.isRequired,inline:_react.PropTypes.bool},exports["default"]=ValueEditor;
},{"./ValueEditor/ValidateEditor":33,"react":"react","react-dom":"react-dom"}],32:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},_createClass=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_utils=require("../../utils.js"),EditorBase=function(e){function t(e){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,Object.getPrototypeOf(t).call(this,e));return n.state={editable:!1},n.onPaste=n.onPaste.bind(n),n.onMouseDown=n.onMouseDown.bind(n),n.onMouseUp=n.onMouseUp.bind(n),n.onFocus=n.onFocus.bind(n),n.onClick=n.onClick.bind(n),n.stop=n.stop.bind(n),n.onBlur=n.onBlur.bind(n),n.reset=n.reset.bind(n),n.onKeyDown=n.onKeyDown.bind(n),n.onInput=n.onInput.bind(n),n}return _inherits(t,e),_createClass(t,[{key:"stop",value:function(){_reactDom2["default"].findDOMNode(this).blur(),this.props.onStop()}},{key:"render",value:function(){return _react2["default"].createElement(this.props.tag,_extends({},this.props,{tabIndex:"0",className:"inline-input "+this.props.className,contentEditable:this.state.editable||void 0,onFocus:this.onFocus,onMouseDown:this.onMouseDown,onClick:this.onClick,onBlur:this.onBlur,onKeyDown:this.onKeyDown,onInput:this.onInput,onPaste:this.onPaste,dangerouslySetInnerHTML:{__html:this.props.contentToHtml(this.props.content)},__self:this}))}},{key:"onPaste",value:function(e){e.preventDefault();var t=e.clipboardData.getData("text/plain");document.execCommand("insertHTML",!1,t)}},{key:"onMouseDown",value:function(e){this._mouseDown=!0,window.addEventListener("mouseup",this.onMouseUp),this.props.onMouseDown(e)}},{key:"onMouseUp",value:function(){this._mouseDown&&(this._mouseDown=!1,window.removeEventListener("mouseup",this.onMouseUp))}},{key:"onClick",value:function(e){this.onMouseUp(),this.onFocus(e)}},{key:"onFocus",value:function(e){var t=this;if(!(this._mouseDown||this._ignore_events||this.state.editable)){var n=window.getSelection(),o=void 0;if(n.rangeCount>0)o=n.getRangeAt(0);else if(document.caretPositionFromPoint&&e.clientX&&e.clientY){var s=document.caretPositionFromPoint(e.clientX,e.clientY);o=document.createRange(),o.setStart(s.offsetNode,s.offset)}else document.caretRangeFromPoint&&e.clientX&&e.clientY?o=document.caretRangeFromPoint(e.clientX,e.clientY):(o=document.createRange(),o.selectNodeContents(_reactDom2["default"].findDOMNode(this)));this._ignore_events=!0,this.setState({editable:!0},function(){var e=_reactDom2["default"].findDOMNode(t);e.blur(),e.focus(),t._ignore_events=!1})}}},{key:"onBlur",value:function(e){this._ignore_events||(window.getSelection().removeAllRanges(),this.setState({editable:!1}),this.props.onDone(this.props.nodeToContent(_reactDom2["default"].findDOMNode(this))),this.props.onBlur(e))}},{key:"reset",value:function(){_reactDom2["default"].findDOMNode(this).innerHTML=this.props.contentToHtml(this.props.content)}},{key:"onKeyDown",value:function(e){switch(e.stopPropagation(),e.keyCode){case _utils.Key.ESC:e.preventDefault(),this.reset(),this.stop();break;case _utils.Key.ENTER:this.props.submitOnEnter&&!e.shiftKey&&(e.preventDefault(),this.stop())}}},{key:"onInput",value:function(){this.props.onInput(this.props.nodeToContent(_reactDom2["default"].findDOMNode(this)))}}]),t}(_react.Component);EditorBase.propTypes={content:_react.PropTypes.string.isRequired,onDone:_react.PropTypes.func.isRequired,contentToHtml:_react.PropTypes.func,nodeToContent:_react.PropTypes.func,onStop:_react.PropTypes.func,submitOnEnter:_react.PropTypes.bool,className:_react.PropTypes.string,tag:_react.PropTypes.string},EditorBase.defaultProps={contentToHtml:function(e){return _.escape(e)},nodeToContent:function(e){return e.textContent},submitOnEnter:!0,className:"",tag:"div",onStop:_.noop,onMouseDown:_.noop,onBlur:_.noop,onInput:_.noop},exports["default"]=EditorBase;
@@ -137,9 +137,9 @@
"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t["default"]=e,t}function reducer(){var e=arguments.length<=0||void 0===arguments[0]?defaultState:arguments[0],t=arguments[1];switch(t.type){case RECEIVE:return _extends({},e,{settings:t.settings});case UPDATE:return _extends({},e,{settings:_extends({},e.settings,t.settings)});default:return e}}function handleWsMsg(e){switch(e.cmd){case websocketActions.CMD_UPDATE:return updateSettings(e.data);default:return console.error("unknown settings update",e),{type:UNKNOWN_CMD,msg:e}}}function update(e){return _utils.fetchApi.put("/settings",e),{type:REQUEST_UPDATE}}function fetchData(){return msgQueueActions.fetchData(MSG_TYPE)}function receiveData(e){return{type:RECEIVE,settings:e}}function updateSettings(e){return{type:UPDATE,settings:e}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.UNKNOWN_CMD=exports.REQUEST_UPDATE=exports.UPDATE=exports.RECEIVE=exports.DATA_URL=exports.MSG_TYPE=void 0;var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var s in r)Object.prototype.hasOwnProperty.call(r,s)&&(e[s]=r[s])}return e};exports["default"]=reducer,exports.handleWsMsg=handleWsMsg,exports.update=update,exports.fetchData=fetchData,exports.receiveData=receiveData,exports.updateSettings=updateSettings;var _utils=require("../utils"),_websocket=require("./websocket"),websocketActions=_interopRequireWildcard(_websocket),_msgQueue=require("./msgQueue"),msgQueueActions=_interopRequireWildcard(_msgQueue),MSG_TYPE=exports.MSG_TYPE="UPDATE_SETTINGS",DATA_URL=exports.DATA_URL="/settings",RECEIVE=exports.RECEIVE="RECEIVE",UPDATE=exports.UPDATE="UPDATE",REQUEST_UPDATE=exports.REQUEST_UPDATE="REQUEST_UPDATE",UNKNOWN_CMD=exports.UNKNOWN_CMD="SETTINGS_UNKNOWN_CMD",defaultState={settings:{}};
},{"../utils":55,"./msgQueue":45,"./websocket":52}],47:[function(require,module,exports){
-"use strict";function reducer(){var e=arguments.length<=0||void 0===arguments[0]?defaultState:arguments[0],t=arguments[1];switch(t.type){case SET_ACTIVE_MENU:return _extends({},e,{activeMenu:t.activeMenu});case _main.SELECT:var r=t.flowId&&!t.currentSelection,n=!t.flowId&&t.currentSelection;return r?_extends({},e,{activeMenu:"Flow"}):n&&"Flow"===e.activeMenu?_extends({},e,{activeMenu:"Start"}):e;default:return e}}function setActiveMenu(e){return{type:SET_ACTIVE_MENU,activeMenu:e}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.SET_ACTIVE_MENU=void 0;var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e};exports["default"]=reducer,exports.setActiveMenu=setActiveMenu;var _main=require("./views/main"),SET_ACTIVE_MENU=exports.SET_ACTIVE_MENU="SET_ACTIVE_MENU",defaultState={activeMenu:"Start"};
+"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&(t[s]=e[s]);return t["default"]=e,t}function reducer(){var e=arguments.length<=0||void 0===arguments[0]?defaultState:arguments[0],t=arguments[1];switch(t.type){case SET_ACTIVE_MENU:return _extends({},e,{activeMenu:t.activeMenu});case _main.SELECT:return t.flowId&&!t.currentSelection?_extends({},e,{displayLarge:!1,activeMenu:"Flow"}):t.flowId||"Flow"!==e.activeMenu?_extends({},e,{displayLarge:!1}):_extends({},e,{displayLarge:!1,activeMenu:"Start"});case SET_CONTENT_VIEW:return _extends({},e,{contentView:t.contentView});case SET_SELECTED_INPUT:return _extends({},e,{selectedInput:t.input});case UPDATE_QUERY:return _extends({},e,{query:_extends({},e.query,t.query)});case SELECT_TAB:return _extends({},e,{panel:t.panel});case SELECT_TAB_RELATIVE:if(!t.flow||null===t.shift)return _extends({},e,{panel:"request"});var s=["request","response","error"].filter(function(e){return t.flow[e]}).concat(["details"]);return _extends({},e,{panel:s[(s.indexOf(e.panel)+t.shift+s.length)%s.length]});case SET_PROMPT:return _extends({},e,{promptOpen:t.open});case SET_DISPLAY_LARGE:return _extends({},e,{displayLarge:t.displayLarge});default:return e}}function setActiveMenu(e){return{type:SET_ACTIVE_MENU,activeMenu:e}}function setContentView(e){return{type:SET_CONTENT_VIEW,contentView:e}}function setSelectedInput(e){return{type:SET_SELECTED_INPUT,input:e}}function updateQuery(e){return{type:UPDATE_QUERY,query:e}}function selectTab(e){return{type:SELECT_TAB,panel:e}}function selectTabRelative(e){return function(t,s){var r=s().flows.list.byId[s().flows.views.main.selected[0]];t({type:SELECT_TAB_RELATIVE,shift:e,flow:r})}}function setPrompt(e){return{type:SET_PROMPT,open:e}}function setDisplayLarge(e){return{type:SET_DISPLAY_LARGE,displayLarge:e}}function onKeyDown(e){if(e.ctrlKey)return function(){};var t=e.keyCode,s=e.shiftKey;return e.preventDefault(),function(e,r){switch(t){case _utils.Key.I:e(setSelectedInput("intercept"));break;case _utils.Key.L:e(setSelectedInput("search"));break;case _utils.Key.H:e(setSelectedInput("highlight"));break;case _utils.Key.K:case _utils.Key.UP:e((0,_main.selectRelative)(-1));break;case _utils.Key.J:case _utils.Key.DOWN:e((0,_main.selectRelative)(1));break;case _utils.Key.SPACE:case _utils.Key.PAGE_DOWN:e((0,_main.selectRelative)(10));break;case _utils.Key.PAGE_UP:e((0,_main.selectRelative)(-10));break;case _utils.Key.END:e((0,_main.selectRelative)(1e10));break;case _utils.Key.HOME:e((0,_main.selectRelative)(-1e10));break;case _utils.Key.ESC:e((0,_main.selectRelative)(null)),e(selectTabRelative(null));break;case _utils.Key.H:case _utils.Key.LEFT:e(selectTabRelative(-1));break;case _utils.Key.L:case _utils.Key.TAB:case _utils.Key.RIGHT:e(selectTabRelative(1));break;case _utils.Key.C:s&&e(flowsActions.clear());break;case _utils.Key.D:var n=r().flows.list.byId[r().flows.views.main.selected[0]];if(!n)return;e(s?flowsActions.duplicate(n):flowsActions.remove(n));break;case _utils.Key.A:var a=r().flows.list.byId[r().flows.views.main.selected[0]];s?e(flowsActions.acceptAll()):a&&a.intercepted&&e(flowsActions.accept(a));break;case _utils.Key.R:var i=r().flows.list.byId[r().flows.views.main.selected[0]];!s&&i&&e(flowsActions.replay(i));break;case _utils.Key.V:var l=r().flows.list.byId[r().flows.views.main.selected[0]];!s&&l&&l.modified&&e(flowsActions.revert(l));break;case _utils.Key.E:e(setPrompt(!0));break;default:return function(){}}}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.SET_DISPLAY_LARGE=exports.SET_PROMPT=exports.SELECT_TAB_RELATIVE=exports.SELECT_TAB=exports.UPDATE_QUERY=exports.SET_SELECTED_INPUT=exports.SET_CONTENT_VIEW=exports.SET_ACTIVE_MENU=void 0;var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var s=arguments[t];for(var r in s)Object.prototype.hasOwnProperty.call(s,r)&&(e[r]=s[r])}return e};exports["default"]=reducer,exports.setActiveMenu=setActiveMenu,exports.setContentView=setContentView,exports.setSelectedInput=setSelectedInput,exports.updateQuery=updateQuery,exports.selectTab=selectTab,exports.selectTabRelative=selectTabRelative,exports.setPrompt=setPrompt,exports.setDisplayLarge=setDisplayLarge,exports.onKeyDown=onKeyDown;var _main=require("./views/main"),_utils=require("../utils.js"),_flows=require("../ducks/flows"),flowsActions=_interopRequireWildcard(_flows),SET_ACTIVE_MENU=exports.SET_ACTIVE_MENU="UI_SET_ACTIVE_MENU",SET_CONTENT_VIEW=exports.SET_CONTENT_VIEW="UI_SET_CONTENT_VIEW",SET_SELECTED_INPUT=exports.SET_SELECTED_INPUT="UI_SET_SELECTED_INPUT",UPDATE_QUERY=exports.UPDATE_QUERY="UI_UPDATE_QUERY",SELECT_TAB=exports.SELECT_TAB="UI_SELECT_TAB",SELECT_TAB_RELATIVE=exports.SELECT_TAB_RELATIVE="UI_SELECT_TAB_RELATIVE",SET_PROMPT=exports.SET_PROMPT="UI_SET_PROMPT",SET_DISPLAY_LARGE=exports.SET_DISPLAY_LARGE="UI_SET_DISPLAY_LARGE",defaultState={activeMenu:"Start",selectedInput:null,displayLarge:!1,promptOpen:!1,contentView:"ViewAuto",query:{},panel:"request"};
-},{"./views/main":51}],48:[function(require,module,exports){
+},{"../ducks/flows":43,"../utils.js":55,"./views/main":51}],48:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _defineProperty(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function _toConsumableArray(e){if(Array.isArray(e)){for(var t=0,r=Array(e.length);t<e.length;t++)r[t]=e[t];return r}return Array.from(e)}function reduce(){var e=arguments.length<=0||void 0===arguments[0]?defaultState:arguments[0],t=arguments[1];switch(t.type){case ADD:return _extends({},e,{data:[].concat(_toConsumableArray(e.data),[t.item]),byId:_extends({},e.byId,_defineProperty({},t.item.id,t.item)),indexOf:_extends({},e.indexOf,_defineProperty({},t.item.id,e.data.length))});case UPDATE:var r=e.indexOf[t.id];if(null==r)return e;var n=[].concat(_toConsumableArray(e.data));return n[r]=t.item,_extends({},e,{data:n,byId:_extends({},e.byId,_defineProperty({},t.id,t.item))});case REMOVE:var a=e.indexOf[t.id];if(null==a)return e;var d=[].concat(_toConsumableArray(e.data)),i=_extends({},e.indexOf,_defineProperty({},t.id,null));d.splice(a,1);for(var o=d.length-1;o>=a;o--)i[d[o].id]=o;return _extends({},e,{data:d,indexOf:i,byId:_extends({},e.byId,_defineProperty({},t.id,null))});case RECEIVE:return _extends({},e,{data:t.list,byId:_lodash2["default"].fromPairs(t.list.map(function(e){return[e.id,e]})),indexOf:_lodash2["default"].fromPairs(t.list.map(function(e,t){return[e.id,t]}))});default:return e}}function add(e){return{type:ADD,item:e}}function update(e,t){return{type:UPDATE,id:e,item:t}}function remove(e){return{type:REMOVE,id:e}}function receive(e){return{type:RECEIVE,list:e}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RECEIVE=exports.REMOVE=exports.UPDATE=exports.ADD=void 0;var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var n in r)Object.prototype.hasOwnProperty.call(r,n)&&(e[n]=r[n])}return e};exports["default"]=reduce,exports.add=add,exports.update=update,exports.remove=remove,exports.receive=receive;var _lodash=require("lodash"),_lodash2=_interopRequireDefault(_lodash),ADD=exports.ADD="LIST_ADD",UPDATE=exports.UPDATE="LIST_UPDATE",REMOVE=exports.REMOVE="LIST_REMOVE",RECEIVE=exports.RECEIVE="LIST_RECEIVE",defaultState={data:[],byId:{},indexOf:{}};
},{"lodash":"lodash"}],49:[function(require,module,exports){
@@ -149,7 +149,7 @@
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var r={};if(null!=e)for(var t in e)Object.prototype.hasOwnProperty.call(e,t)&&(r[t]=e[t]);return r["default"]=e,r}function add(e){return{type:ADD,item:e}}function update(e,r){return{type:UPDATE,id:e,item:r}}function remove(e){return{type:REMOVE,id:e}}function receive(e){return{type:RECEIVE,list:e}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RECEIVE=exports.REMOVE=exports.UPDATE=exports.ADD=void 0,exports.add=add,exports.update=update,exports.remove=remove,exports.receive=receive;var _redux=require("redux"),_view=require("./utils/view"),viewActions=_interopRequireWildcard(_view),_main=require("./views/main.js"),_main2=_interopRequireDefault(_main),ADD=exports.ADD="FLOW_VIEWS_ADD",UPDATE=exports.UPDATE="FLOW_VIEWS_UPDATE",REMOVE=exports.REMOVE="FLOW_VIEWS_REMOVE",RECEIVE=exports.RECEIVE="FLOW_VIEWS_RECEIVE";exports["default"]=(0,_redux.combineReducers)({main:_main2["default"]});
},{"./utils/view":49,"./views/main.js":51,"redux":"redux"}],51:[function(require,module,exports){
-"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function reduce(){var e=arguments.length<=0||void 0===arguments[0]?defaultState:arguments[0],t=arguments[1];switch(t.type){case UPDATE_HIGHLIGHT:return _extends({},e,{highlight:t.highlight});case SELECT:return _extends({},e,{selected:[t.id]});case UPDATE_FILTER:return _extends({},e,{filter:t.filter,view:(0,viewActions["default"])(e.view,viewActions.updateFilter(t.list,makeFilter(t.filter),makeSort(e.sort)))});case UPDATE_SORT:var i={column:t.column,desc:t.desc};return _extends({},e,{sort:i,view:(0,viewActions["default"])(e.view,viewActions.updateSort(makeSort(i)))});case viewsActions.ADD:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.add(t.item,makeFilter(e.filter),makeSort(e.sort)))});case viewsActions.UPDATE:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.update(t.id,t.item,makeFilter(e.filter),makeSort(e.sort)))});case viewsActions.REMOVE:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.remove(t.id))});case viewsActions.RECEIVE:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.receive(t.list,makeFilter(e.filter),makeSort(e.sort)))});default:return _extends({},e,{view:(0,viewActions["default"])(e.view,t)})}}function updateFilter(e){return function(t,i){t({type:UPDATE_FILTER,filter:e,list:i().flows.list})}}function updateHighlight(e){return{type:UPDATE_HIGHLIGHT,highlight:e}}function updateSort(e,t){return{type:UPDATE_SORT,column:e,desc:t}}function select(e){return function(t,i){t({type:SELECT,currentSelection:i().flows.views.main.selected[0],id:e})}}function makeFilter(e){if(e)return _filt2["default"].parse(e)}function makeSort(e){var t=e.column,i=e.desc,r=sortKeyFuns[t];if(r)return function(e,t){var n=r(e),s=r(t);return n>s?i?-1:1:n<s?i?1:-1:0}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.SELECT=exports.UPDATE_HIGHLIGHT=exports.UPDATE_SORT=exports.UPDATE_FILTER=void 0;var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var i=arguments[t];for(var r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r])}return e};exports["default"]=reduce,exports.updateFilter=updateFilter,exports.updateHighlight=updateHighlight,exports.updateSort=updateSort,exports.select=select;var _filt=require("../../filt/filt"),_filt2=_interopRequireDefault(_filt),_utils=require("../../flow/utils"),_view=require("../utils/view"),viewActions=_interopRequireWildcard(_view),_views=require("../views"),viewsActions=_interopRequireWildcard(_views),UPDATE_FILTER=exports.UPDATE_FILTER="FLOW_VIEWS_MAIN_UPDATE_FILTER",UPDATE_SORT=exports.UPDATE_SORT="FLOW_VIEWS_MAIN_UPDATE_SORT",UPDATE_HIGHLIGHT=exports.UPDATE_HIGHLIGHT="FLOW_VIEWS_MAIN_UPDATE_HIGHLIGHT",SELECT=exports.SELECT="FLOW_VIEWS_MAIN_SELECT",sortKeyFuns={TLSColumn:function(e){return e.request.scheme},PathColumn:function(e){return _utils.RequestUtils.pretty_url(e.request)},MethodColumn:function(e){return e.request.method},StatusColumn:function(e){return e.response&&e.response.status_code},TimeColumn:function(e){return e.response&&e.response.timestamp_end-e.request.timestamp_start},SizeColumn:function(e){var t=e.request.contentLength;return e.response&&(t+=e.response.contentLength||0),t}},defaultState={highlight:null,selected:[],filter:null,sort:{column:null,desc:!1},view:void 0};
+"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&(t[i]=e[i]);return t["default"]=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function reduce(){var e=arguments.length<=0||void 0===arguments[0]?defaultState:arguments[0],t=arguments[1];switch(t.type){case UPDATE_HIGHLIGHT:return _extends({},e,{highlight:t.highlight});case SELECT:return _extends({},e,{selected:[t.id]});case SELECT_RELATIVE:if(null===t.shift)return _extends({},e,{selected:[]});var i=e.selected[0],r=0;return!i&&t.shift<0?r=e.view.data.length-1:i&&(r=e.view.indexOf[i]+t.shift,r=r<0?0:r,r=r>e.view.data.length-1?e.view.data.length-1:r),_extends({},e,{selected:[e.view.data[r].id]});case UPDATE_FILTER:return _extends({},e,{filter:t.filter,view:(0,viewActions["default"])(e.view,viewActions.updateFilter(t.list,makeFilter(t.filter),makeSort(e.sort)))});case UPDATE_SORT:var n={column:t.column,desc:t.desc};return _extends({},e,{sort:n,view:(0,viewActions["default"])(e.view,viewActions.updateSort(makeSort(n)))});case viewsActions.ADD:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.add(t.item,makeFilter(e.filter),makeSort(e.sort)))});case viewsActions.UPDATE:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.update(t.id,t.item,makeFilter(e.filter),makeSort(e.sort)))});case viewsActions.REMOVE:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.remove(t.id))});case viewsActions.RECEIVE:return _extends({},e,{view:(0,viewActions["default"])(e.view,viewActions.receive(t.list,makeFilter(e.filter),makeSort(e.sort)))});default:return _extends({},e,{view:(0,viewActions["default"])(e.view,t)})}}function updateFilter(e){return function(t,i){t({type:UPDATE_FILTER,filter:e,list:i().flows.list})}}function updateHighlight(e){return{type:UPDATE_HIGHLIGHT,highlight:e}}function updateSort(e,t){return{type:UPDATE_SORT,column:e,desc:t}}function select(e){return function(t,i){t({type:SELECT,currentSelection:i().flows.views.main.selected[0],id:e})}}function selectRelative(e){return function(t,i){t({type:SELECT_RELATIVE,currentSelection:i().flows.views.main.selected[0],shift:e})}}function makeFilter(e){if(e)return _filt2["default"].parse(e)}function makeSort(e){var t=e.column,i=e.desc,r=sortKeyFuns[t];if(r)return function(e,t){var n=r(e),s=r(t);return n>s?i?-1:1:n<s?i?1:-1:0}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.SELECT_RELATIVE=exports.SELECT=exports.UPDATE_HIGHLIGHT=exports.UPDATE_SORT=exports.UPDATE_FILTER=void 0;var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var i=arguments[t];for(var r in i)Object.prototype.hasOwnProperty.call(i,r)&&(e[r]=i[r])}return e};exports["default"]=reduce,exports.updateFilter=updateFilter,exports.updateHighlight=updateHighlight,exports.updateSort=updateSort,exports.select=select,exports.selectRelative=selectRelative;var _filt=require("../../filt/filt"),_filt2=_interopRequireDefault(_filt),_utils=require("../../flow/utils"),_view=require("../utils/view"),viewActions=_interopRequireWildcard(_view),_views=require("../views"),viewsActions=_interopRequireWildcard(_views),UPDATE_FILTER=exports.UPDATE_FILTER="FLOW_VIEWS_MAIN_UPDATE_FILTER",UPDATE_SORT=exports.UPDATE_SORT="FLOW_VIEWS_MAIN_UPDATE_SORT",UPDATE_HIGHLIGHT=exports.UPDATE_HIGHLIGHT="FLOW_VIEWS_MAIN_UPDATE_HIGHLIGHT",SELECT=exports.SELECT="FLOW_VIEWS_MAIN_SELECT",SELECT_RELATIVE=exports.SELECT_RELATIVE="SELECT_RELATIVE",sortKeyFuns={TLSColumn:function(e){return e.request.scheme},PathColumn:function(e){return _utils.RequestUtils.pretty_url(e.request)},MethodColumn:function(e){return e.request.method},StatusColumn:function(e){return e.response&&e.response.status_code},TimeColumn:function(e){return e.response&&e.response.timestamp_end-e.request.timestamp_start},SizeColumn:function(e){var t=e.request.contentLength;return e.response&&(t+=e.response.contentLength||0),t}},defaultState={highlight:null,selected:[],filter:null,sort:{column:null,desc:!1},view:void 0};
},{"../../filt/filt":53,"../../flow/utils":54,"../utils/view":49,"../views":50}],52:[function(require,module,exports){
"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t["default"]=e,t}function _defineProperty(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function reduce(){var e,t=arguments.length<=0||void 0===arguments[0]?defaultState:arguments[0],n=arguments[1];switch(n.type){case CONNECT:return _extends({},t,_defineProperty({},SYM_SOCKET,n.socket));case CONNECTED:return _extends({},t,{connected:!0});case DISCONNECT:return _extends({},t,{connected:!1});case DISCONNECTED:return _extends({},t,(e={},_defineProperty(e,SYM_SOCKET,null),_defineProperty(e,"connected",!1),e));default:return t}}function connect(){return function(e){var t=new WebSocket(location.origin.replace("http","ws")+"/updates");t.addEventListener("open",function(){return e(onConnect())}),t.addEventListener("close",function(){return e(onDisconnect())}),t.addEventListener("message",function(t){return e(onMessage(JSON.parse(t.data)))}),t.addEventListener("error",function(t){return e(onError(t))}),e({type:CONNECT,socket:t})}}function disconnect(){return function(e,t){t().settings[SYM_SOCKET].close(),e({type:DISCONNECT})}}function onConnect(){return function(e){e({type:CONNECTED}),e(settingsActions.fetchData()),e(flowsActions.fetchData()),e(eventLogActions.fetchData())}}function onMessage(e){return msgQueueActions.handleWsMsg(e)}function onDisconnect(){return function(e){e(eventLogActions.add("WebSocket connection closed.")),e({type:DISCONNECTED})}}function onError(e){return function(t){t(eventLogActions.add("WebSocket connection error.")),t({type:ERROR,error:e})}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.MESSAGE=exports.ERROR=exports.DISCONNECTED=exports.DISCONNECT=exports.CONNECTED=exports.CONNECT=exports.SYM_SOCKET=exports.CMD_RESET=exports.CMD_REMOVE=exports.CMD_UPDATE=exports.CMD_ADD=void 0;var _extends=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e};exports["default"]=reduce,exports.connect=connect,exports.disconnect=disconnect,exports.onConnect=onConnect,exports.onMessage=onMessage,exports.onDisconnect=onDisconnect,exports.onError=onError;var _actions=require("../actions.js"),_dispatcher=require("../dispatcher.js"),_msgQueue=require("./msgQueue"),msgQueueActions=_interopRequireWildcard(_msgQueue),_eventLog=require("./eventLog"),eventLogActions=_interopRequireWildcard(_eventLog),_flows=require("./flows"),flowsActions=_interopRequireWildcard(_flows),_settings=require("./settings"),settingsActions=_interopRequireWildcard(_settings),CMD_ADD=exports.CMD_ADD="add",CMD_UPDATE=exports.CMD_UPDATE="update",CMD_REMOVE=exports.CMD_REMOVE="remove",CMD_RESET=exports.CMD_RESET="reset",SYM_SOCKET=exports.SYM_SOCKET=Symbol("WEBSOCKET_SYM_SOCKET"),CONNECT=exports.CONNECT="WEBSOCKET_CONNECT",CONNECTED=exports.CONNECTED="WEBSOCKET_CONNECTED",DISCONNECT=exports.DISCONNECT="WEBSOCKET_DISCONNECT",DISCONNECTED=exports.DISCONNECTED="WEBSOCKET_DISCONNECTED",ERROR=exports.ERROR="WEBSOCKET_ERROR",MESSAGE=exports.MESSAGE="WEBSOCKET_MESSAGE",defaultState={connected:!1,socket:null};
diff --git a/web/src/js/__tests__/ducks/ui.js b/web/src/js/__tests__/ducks/ui.js
index 2388a9ad..289192d9 100644
--- a/web/src/js/__tests__/ducks/ui.js
+++ b/web/src/js/__tests__/ducks/ui.js
@@ -1,36 +1,86 @@
-jest.unmock("../../ducks/ui");
-// @todo fix it ( this is why I don't like to add tests until our architecture is stable :P )
-jest.unmock("../../ducks/views/main");
-
-import reducer, { setActiveMenu } from '../../ducks/ui';
-import { SELECT } from '../../ducks/views/main';
-
-describe("ui reducer", () => {
- it("should return the initial state", () => {
- expect(reducer(undefined, {})).toEqual({ activeMenu: 'Start'})
- }),
- it("should return the state for view", () => {
- expect(reducer(undefined, setActiveMenu('View'))).toEqual({ activeMenu: 'View'})
- }),
- it("should change the state to Start when deselecting a flow and we a currently at the flow tab", () => {
- expect(reducer({activeMenu: 'Flow'},
- { type: SELECT,
- currentSelection: '1',
- flowId : undefined
- })).toEqual({ activeMenu: 'Start'})
- }),
- it("should change the state to Flow when we selected a flow and no flow was selected before", () => {
- expect(reducer({activeMenu: 'Start'},
- { type: SELECT,
- currentSelection: undefined,
- flowId : '1'
- })).toEqual({ activeMenu: 'Flow'})
- }),
- it("should not change the state to Flow when OPTIONS tab is selected and we selected a flow and a flow as selected before", () => {
- expect(reducer({activeMenu: 'Options'},
- { type: SELECT,
- currentSelection: '1',
- flowId : '2'
- })).toEqual({ activeMenu: 'Options'})
+jest.unmock('lodash')
+jest.unmock('redux')
+jest.unmock('redux-thunk')
+jest.unmock('../../ducks/ui')
+jest.unmock('../../ducks/views/main')
+
+import _ from 'lodash'
+import thunk from 'redux-thunk'
+import { applyMiddleware, createStore, combineReducers } from 'redux'
+import reducer, { setActiveMenu, selectTabRelative } from '../../ducks/ui'
+import { SELECT } from '../../ducks/views/main'
+
+describe('ui reducer', () => {
+ it('should return the initial state', () => {
+ expect(reducer(undefined, {}).activeMenu).toEqual('Start')
})
-});
+
+ it('should return the state for view', () => {
+ expect(reducer(undefined, setActiveMenu('View')).activeMenu).toEqual('View')
+ })
+
+ it('should change the state to Start when deselecting a flow and we a currently at the flow tab', () => {
+ expect(reducer({ activeMenu: 'Flow' }, {
+ type: SELECT,
+ currentSelection: 1,
+ flowId : undefined,
+ }).activeMenu).toEqual('Start')
+ })
+
+ it('should change the state to Flow when we selected a flow and no flow was selected before', () => {
+ expect(reducer({ activeMenu: 'Start' }, {
+ type: SELECT,
+ currentSelection: undefined,
+ flowId : 1,
+ }).activeMenu).toEqual('Flow')
+ })
+
+ it('should not change the state to Flow when OPTIONS tab is selected and we selected a flow and a flow as selected before', () => {
+ expect(reducer({activeMenu: 'Options'}, {
+ type: SELECT,
+ currentSelection: 1,
+ flowId : '2',
+ }).activeMenu).toEqual('Options')
+ })
+
+ describe('select tab relative', () => {
+
+ it('should select tab according to flow properties', () => {
+ const store = createTestStore(makeState([{ id: 1 }], 1))
+ store.dispatch(selectTabRelative(1))
+ expect(store.getState().ui.panel).toEqual('details')
+ })
+
+ it('should select last tab when first tab is selected', () => {
+ const store = createTestStore(makeState([{ id: 1, request: true, response: true, error: true }], 1))
+ store.dispatch(selectTabRelative(-1))
+ expect(store.getState().ui.panel).toEqual('details')
+ })
+
+ })
+})
+
+function createTestStore(state) {
+ return createStore(
+ combineReducers({ ui: reducer, flows: (state = {}) => state }),
+ state,
+ applyMiddleware(thunk)
+ )
+}
+
+function makeState(flows, selected) {
+ return {
+ flows: {
+ list: {
+ data: flows,
+ byId: _.fromPairs(flows.map(flow => [flow.id, flow])),
+ indexOf: _.fromPairs(flows.map((flow, index) => [flow.id, index])),
+ },
+ views: {
+ main: {
+ selected: [selected],
+ },
+ },
+ },
+ }
+}
diff --git a/web/src/js/__tests__/ducks/views/main.js b/web/src/js/__tests__/ducks/views/main.js
new file mode 100644
index 00000000..0edbf68f
--- /dev/null
+++ b/web/src/js/__tests__/ducks/views/main.js
@@ -0,0 +1,82 @@
+jest.unmock('../../../ducks/views/main');
+jest.unmock('../../../ducks/utils/view');
+jest.unmock('redux-thunk')
+jest.unmock('redux')
+
+import reduce, { selectRelative } from '../../../ducks/views/main';
+import thunk from 'redux-thunk'
+import { applyMiddleware, createStore, combineReducers } from 'redux'
+
+describe('main reduce', () => {
+
+ describe('select previous', () => {
+
+ it('should not changed when first flow is selected', () => {
+ const flows = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]
+ const store = createTestStore(makeState(flows, 1))
+ store.dispatch(selectRelative(-1))
+ expect(store.getState().flows.views.main.selected).toEqual([1])
+ })
+
+ it('should select last flow if no flow is selected', () => {
+ const flows = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]
+ const store = createTestStore(makeState(flows))
+ store.dispatch(selectRelative(-1))
+ expect(store.getState().flows.views.main.selected).toEqual([4])
+ })
+
+ })
+
+ describe('select next', () => {
+
+ it('should not change when last flow is selected', () => {
+ const flows = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]
+ const store = createTestStore(makeState(flows, 4))
+ store.dispatch(selectRelative(1))
+ expect(store.getState().flows.views.main.selected).toEqual([4])
+ })
+
+ it('should select first flow if no flow is selected', () => {
+ const flows = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }]
+ const store = createTestStore(makeState(flows, 1))
+ store.dispatch(selectRelative(1))
+ expect(store.getState().flows.views.main.selected).toEqual([2])
+ })
+
+ })
+})
+
+function createTestStore(defaultState) {
+ return createStore(
+ (state = defaultState, action) => ({
+ flows: {
+ ...state.flows,
+ views: {
+ main: reduce(state.flows.views.main, action)
+ }
+ }
+ }),
+ defaultState,
+ applyMiddleware(thunk)
+ )
+}
+
+function makeState(flows, selected) {
+ const list = {
+ data: flows,
+ byId: _.fromPairs(flows.map(flow => [flow.id, flow])),
+ indexOf: _.fromPairs(flows.map((flow, index) => [flow.id, index])),
+ }
+
+ return {
+ flows: {
+ list,
+ views: {
+ main: {
+ selected: [selected],
+ view: list,
+ }
+ }
+ }
+ }
+}
diff --git a/web/src/js/components/ContentView.jsx b/web/src/js/components/ContentView.jsx
index 1533684e..6a982a5d 100644
--- a/web/src/js/components/ContentView.jsx
+++ b/web/src/js/components/ContentView.jsx
@@ -1,78 +1,66 @@
import React, { Component, PropTypes } from 'react'
+import { connect } from 'react-redux'
import { MessageUtils } from '../flow/utils.js'
-import { ViewAuto, ViewImage } from './ContentView/ContentViews'
+import * as ContentViews from './ContentView/ContentViews'
import * as MetaViews from './ContentView/MetaViews'
import ContentLoader from './ContentView/ContentLoader'
import ViewSelector from './ContentView/ViewSelector'
+import { setContentView, setDisplayLarge } from '../ducks/ui'
-export default class ContentView extends Component {
-
- static propTypes = {
- // It may seem a bit weird at the first glance:
- // Every view takes the flow and the message as props, e.g.
- // <Auto flow={flow} message={flow.request}/>
- flow: React.PropTypes.object.isRequired,
- message: React.PropTypes.object.isRequired,
- }
-
- constructor(props, context) {
- super(props, context)
+ContentView.propTypes = {
+ // It may seem a bit weird at the first glance:
+ // Every view takes the flow and the message as props, e.g.
+ // <Auto flow={flow} message={flow.request}/>
+ flow: React.PropTypes.object.isRequired,
+ message: React.PropTypes.object.isRequired,
+}
- this.state = { displayLarge: false, View: ViewAuto }
- this.selectView = this.selectView.bind(this)
- }
+ContentView.isContentTooLarge = msg => msg.contentLength > 1024 * 1024 * (ContentViews.ViewImage.matches(msg) ? 10 : 0.2)
- selectView(View) {
- this.setState({ View })
- }
+function ContentView(props) {
+ const { flow, message, contentView, selectView, displayLarge, setDisplayLarge } = props
- displayLarge() {
- this.setState({ displayLarge: true })
+ if (message.contentLength === 0) {
+ return <MetaViews.ContentEmpty {...props}/>
}
- componentWillReceiveProps(nextProps) {
- if (nextProps.message !== this.props.message) {
- this.setState({ displayLarge: false, View: ViewAuto })
- }
+ if (message.contentLength === null) {
+ return <MetaViews.ContentMissing {...props}/>
}
- isContentTooLarge(msg) {
- return msg.contentLength > 1024 * 1024 * (ViewImage.matches(msg) ? 10 : 0.2)
+ if (!displayLarge && ContentView.isContentTooLarge(message)) {
+ return <MetaViews.ContentTooLarge {...props} onClick={() => setDisplayLarge(true)}/>
}
- render() {
- const { flow, message } = this.props
- const { displayLarge, View } = this.state
+ const View = ContentViews[contentView]
- if (message.contentLength === 0) {
- return <MetaViews.ContentEmpty {...this.props}/>
- }
-
- if (message.contentLength === null) {
- return <MetaViews.ContentMissing {...this.props}/>
- }
-
- if (!displayLarge && this.isContentTooLarge(message)) {
- return <MetaViews.ContentTooLarge {...this.props} onClick={this.displayLarge}/>
- }
-
- return (
- <div>
- {View.textView ? (
- <ContentLoader flow={flow} message={message}>
- <this.state.View content="" />
- </ContentLoader>
- ) : (
- <View flow={flow} message={message} />
- )}
- <div className="view-options text-center">
- <ViewSelector onSelectView={this.selectView} active={View} message={message}/>
- &nbsp;
- <a className="btn btn-default btn-xs" href={MessageUtils.getContentURL(flow, message)}>
- <i className="fa fa-download"/>
- </a>
- </div>
+ return (
+ <div>
+ {View.textView ? (
+ <ContentLoader flow={flow} message={message}>
+ <View content="" />
+ </ContentLoader>
+ ) : (
+ <View flow={flow} message={message} />
+ )}
+ <div className="view-options text-center">
+ <ViewSelector onSelectView={selectView} active={View} message={message}/>
+ &nbsp;
+ <a className="btn btn-default btn-xs" href={MessageUtils.getContentURL(flow, message)}>
+ <i className="fa fa-download"/>
+ </a>
</div>
- )
- }
+ </div>
+ )
}
+
+export default connect(
+ state => ({
+ contentView: state.ui.contentView,
+ displayLarge: state.ui.displayLarge,
+ }),
+ {
+ selectView: setContentView,
+ setDisplayLarge,
+ }
+)(ContentView)
diff --git a/web/src/js/components/ContentView/MetaViews.jsx b/web/src/js/components/ContentView/MetaViews.jsx
index 83720a13..2d064b54 100644
--- a/web/src/js/components/ContentView/MetaViews.jsx
+++ b/web/src/js/components/ContentView/MetaViews.jsx
@@ -1,5 +1,5 @@
import React from 'react'
-import {formatSize} from '../../utils.js'
+import { formatSize } from '../../utils.js'
export function ContentEmpty({ flow, message }) {
return (
diff --git a/web/src/js/components/ContentView/ViewSelector.jsx b/web/src/js/components/ContentView/ViewSelector.jsx
index df3a5b83..9b151a5b 100644
--- a/web/src/js/components/ContentView/ViewSelector.jsx
+++ b/web/src/js/components/ContentView/ViewSelector.jsx
@@ -14,7 +14,7 @@ export default function ViewSelector({ active, message, onSelectView }) {
{views.map(View => (
<button
key={View.name}
- onClick={() => onSelectView(View)}
+ onClick={() => onSelectView(View.name)}
className={classnames('btn btn-default', { active: View === active })}>
{View === ViewAuto ? (
`auto: ${ViewAuto.findView(message).name.toLowerCase().replace('view', '')}`
diff --git a/web/src/js/components/FlowView.jsx b/web/src/js/components/FlowView.jsx
index 0ef6e5cd..5ba472a5 100644
--- a/web/src/js/components/FlowView.jsx
+++ b/web/src/js/components/FlowView.jsx
@@ -1,4 +1,5 @@
import React, { Component } from 'react'
+import { connect } from 'react-redux'
import _ from 'lodash'
import Nav from './FlowView/Nav'
@@ -6,47 +7,29 @@ import { Request, Response, ErrorView as Error } from './FlowView/Messages'
import Details from './FlowView/Details'
import Prompt from './Prompt'
+import { setPrompt, selectTab } from '../ducks/ui'
+
export default class FlowView extends Component {
static allTabs = { Request, Response, Error, Details }
constructor(props, context) {
super(props, context)
-
- this.state = { prompt: false }
-
- this.closePrompt = this.closePrompt.bind(this)
- this.selectTab = this.selectTab.bind(this)
- }
-
- getTabs() {
- return ['request', 'response', 'error'].filter(k => this.props.flow[k]).concat(['details'])
- }
-
- nextTab(increment) {
- const tabs = this.getTabs()
- // JS modulo operator doesn't correct negative numbers, make sure that we are positive.
- this.selectTab(tabs[(tabs.indexOf(this.props.tab) + increment + tabs.length) % tabs.length])
+ this.onPromptFinish = this.onPromptFinish.bind(this)
}
- selectTab(panel) {
- this.props.updateLocation(`/flows/${this.props.flow.id}/${panel}`)
- }
-
- closePrompt(edit) {
- this.setState({ prompt: false })
+ onPromptFinish(edit) {
+ this.props.setPrompt(false)
if (edit && this.tabComponent) {
this.tabComponent.edit(edit)
}
}
- promptEdit() {
- let options
-
+ getPromptOptions() {
switch (this.props.tab) {
case 'request':
- options = [
+ return [
'method',
'url',
{ text: 'http version', key: 'v' },
@@ -55,7 +38,7 @@ export default class FlowView extends Component {
break
case 'response':
- options = [
+ return [
{ text: 'http version', key: 'v' },
'code',
'message',
@@ -69,13 +52,11 @@ export default class FlowView extends Component {
default:
throw 'Unknown tab for edit: ' + this.props.tab
}
-
- this.setState({ prompt: { options, done: this.closePrompt } })
}
render() {
- const tabs = this.getTabs()
let { flow, tab: active, updateFlow } = this.props
+ const tabs = ['request', 'response', 'error'].filter(k => flow[k]).concat(['details'])
if (tabs.indexOf(active) < 0) {
if (active === 'response' && flow.error) {
@@ -95,13 +76,23 @@ export default class FlowView extends Component {
flow={flow}
tabs={tabs}
active={active}
- onSelectTab={this.selectTab}
+ onSelectTab={this.props.selectTab}
/>
<Tab ref={ tab => this.tabComponent = tab } flow={flow} updateFlow={updateFlow} />
- {this.state.prompt && (
- <Prompt {...this.state.prompt}/>
+ {this.props.promptOpen && (
+ <Prompt options={this.getPromptOptions()} done={this.onPromptFinish} />
)}
</div>
)
}
}
+
+export default connect(
+ state => ({
+ promptOpen: state.ui.promptOpen,
+ }),
+ {
+ setPrompt,
+ selectTab,
+ }
+)(FlowView)
diff --git a/web/src/js/components/Header.jsx b/web/src/js/components/Header.jsx
index b6ef1cc7..7f1fa69f 100644
--- a/web/src/js/components/Header.jsx
+++ b/web/src/js/components/Header.jsx
@@ -17,7 +17,7 @@ class Header extends Component {
}
render() {
- const { updateLocation, query, selectedFlow, activeMenu} = this.props
+ const { query, selectedFlow, activeMenu} = this.props
let entries = [...Header.entries]
if(selectedFlow)
@@ -41,7 +41,6 @@ class Header extends Component {
<div className="menu">
<Active
ref="active"
- updateLocation={updateLocation}
query={query}
/>
</div>
diff --git a/web/src/js/components/Header/FilterInput.jsx b/web/src/js/components/Header/FilterInput.jsx
index 5b49b788..e421f1a4 100644
--- a/web/src/js/components/Header/FilterInput.jsx
+++ b/web/src/js/components/Header/FilterInput.jsx
@@ -7,10 +7,6 @@ import FilterDocs from './FilterDocs'
export default class FilterInput extends Component {
- static contextTypes = {
- returnFocus: React.PropTypes.func,
- }
-
constructor(props, context) {
super(props, context)
@@ -91,7 +87,6 @@ export default class FilterInput extends Component {
blur() {
ReactDOM.findDOMNode(this.refs.input).blur()
- this.context.returnFocus()
}
select() {
diff --git a/web/src/js/components/Header/MainMenu.jsx b/web/src/js/components/Header/MainMenu.jsx
index 48fea5a2..27a4be60 100644
--- a/web/src/js/components/Header/MainMenu.jsx
+++ b/web/src/js/components/Header/MainMenu.jsx
@@ -3,6 +3,7 @@ import { connect } from 'react-redux'
import FilterInput from './FilterInput'
import { Query } from '../../actions.js'
import { update as updateSettings } from '../../ducks/settings'
+import { updateQuery, setSelectedInput } from '../../ducks/ui'
class MainMenu extends Component {
@@ -12,8 +13,8 @@ class MainMenu extends Component {
static propTypes = {
query: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired,
- updateLocation: PropTypes.func.isRequired,
updateSettings: PropTypes.func.isRequired,
+ updateQuery: PropTypes.func.isRequired,
}
constructor(props, context) {
@@ -22,12 +23,19 @@ class MainMenu extends Component {
this.onHighlightChange = this.onHighlightChange.bind(this)
}
+ componentWillReceiveProps(nextProps) {
+ if(this.refs[nextProps.selectedInput]) {
+ this.refs[nextProps.selectedInput].select()
+ }
+ this.props.setSelectedInput(undefined)
+ }
+
onSearchChange(val) {
- this.props.updateLocation(undefined, { [Query.SEARCH]: val })
+ this.props.updateQuery({ [Query.SEARCH]: val })
}
onHighlightChange(val) {
- this.props.updateLocation(undefined, { [Query.HIGHLIGHT]: val })
+ this.props.updateQuery({ [Query.HIGHLIGHT]: val })
}
render() {
@@ -70,9 +78,12 @@ class MainMenu extends Component {
export default connect(
state => ({
settings: state.settings.settings,
+ selectedInput: state.ui.selectedInput
}),
{
updateSettings,
+ updateQuery,
+ setSelectedInput
},
null,
{
diff --git a/web/src/js/components/MainView.jsx b/web/src/js/components/MainView.jsx
index 93f7b299..756fa22e 100644
--- a/web/src/js/components/MainView.jsx
+++ b/web/src/js/components/MainView.jsx
@@ -20,10 +20,6 @@ class MainView extends Component {
* @todo replace with mapStateToProps
*/
componentWillReceiveProps(nextProps) {
- // Update redux store with route changes
- if (nextProps.routeParams.flowId !== (nextProps.selectedFlow || {}).id) {
- this.props.selectFlow(nextProps.routeParams.flowId)
- }
if (nextProps.location.query[Query.SEARCH] !== nextProps.filter) {
this.props.updateFilter(nextProps.location.query[Query.SEARCH], false)
}
@@ -32,127 +28,6 @@ class MainView extends Component {
}
}
- /**
- * @todo move to actions
- */
- selectFlow(flow) {
- if (flow) {
- this.props.updateLocation(`/flows/${flow.id}/${this.props.routeParams.detailTab || 'request'}`)
- } else {
- this.props.updateLocation('/flows')
- }
- }
-
- /**
- * @todo move to actions
- */
- selectFlowRelative(shift) {
- const { flows, routeParams, selectedFlow } = this.props
- let index = 0
- if (!routeParams.flowId) {
- if (shift < 0) {
- index = flows.length - 1
- }
- } else {
- index = Math.min(
- Math.max(0, flows.indexOf(selectedFlow) + shift),
- flows.length - 1
- )
- }
- this.selectFlow(flows[index])
- }
-
- /**
- * @todo move to actions
- */
- onMainKeyDown(e) {
- var flow = this.props.selectedFlow
- if (e.ctrlKey) {
- return
- }
- switch (e.keyCode) {
- case Key.K:
- case Key.UP:
- this.selectFlowRelative(-1)
- break
- case Key.J:
- case Key.DOWN:
- this.selectFlowRelative(+1)
- break
- case Key.SPACE:
- case Key.PAGE_DOWN:
- this.selectFlowRelative(+10)
- break
- case Key.PAGE_UP:
- this.selectFlowRelative(-10)
- break
- case Key.END:
- this.selectFlowRelative(+1e10)
- break
- case Key.HOME:
- this.selectFlowRelative(-1e10)
- break
- case Key.ESC:
- this.selectFlow(null)
- break
- case Key.H:
- case Key.LEFT:
- if (this.refs.flowDetails) {
- this.refs.flowDetails.nextTab(-1)
- }
- break
- case Key.L:
- case Key.TAB:
- case Key.RIGHT:
- if (this.refs.flowDetails) {
- this.refs.flowDetails.nextTab(+1)
- }
- break
- case Key.C:
- if (e.shiftKey) {
- this.props.clearFlows()
- }
- break
- case Key.D:
- if (flow) {
- if (e.shiftKey) {
- this.props.duplicateFlow(flow)
- } else {
- this.props.removeFlow(flow)
- }
- }
- break
- case Key.A:
- if (e.shiftKey) {
- this.props.acceptAllFlows()
- } else if (flow && flow.intercepted) {
- this.props.acceptFlow(flow)
- }
- break
- case Key.R:
- if (!e.shiftKey && flow) {
- this.props.replayFlow(flow)
- }
- break
- case Key.V:
- if (e.shiftKey && flow && flow.modified) {
- this.props.revertFlow(flow)
- }
- break
- case Key.E:
- if (this.refs.flowDetails) {
- this.refs.flowDetails.promptEdit()
- }
- break
- case Key.SHIFT:
- break
- default:
- console.debug('keydown', e.keyCode)
- return
- }
- e.preventDefault()
- }
-
render() {
const { flows, selectedFlow, highlight } = this.props
return (
@@ -162,7 +37,7 @@ class MainView extends Component {
flows={flows}
selected={selectedFlow}
highlight={highlight}
- onSelect={flow => this.selectFlow(flow)}
+ onSelect={flow => this.props.selectFlow(flow.id)}
/>
{selectedFlow && [
<Splitter key="splitter"/>,
@@ -171,7 +46,6 @@ class MainView extends Component {
ref="flowDetails"
tab={this.props.routeParams.detailTab}
query={this.props.query}
- updateLocation={this.props.updateLocation}
updateFlow={data => this.props.updateFlow(selectedFlow, data)}
flow={selectedFlow}
/>
@@ -193,14 +67,9 @@ export default connect(
updateFilter,
updateHighlight,
updateFlow: flowsActions.update,
- clearFlows: flowsActions.clear,
- duplicateFlow: flowsActions.duplicate,
- removeFlow: flowsActions.remove,
- acceptAllFlows: flowsActions.acceptAll,
- acceptFlow: flowsActions.accept,
- replayFlow: flowsActions.replay,
- revertFlow: flowsActions.revert,
},
undefined,
- { withRef: true }
+ {
+ withRef: true
+ }
)(MainView)
diff --git a/web/src/js/components/Prompt.jsx b/web/src/js/components/Prompt.jsx
index e6564896..1c20b1a9 100755
--- a/web/src/js/components/Prompt.jsx
+++ b/web/src/js/components/Prompt.jsx
@@ -4,23 +4,15 @@ import _ from 'lodash'
import {Key} from '../utils.js'
-Prompt.contextTypes = {
- returnFocus: PropTypes.func
-}
-
Prompt.propTypes = {
options: PropTypes.array.isRequired,
done: PropTypes.func.isRequired,
prompt: PropTypes.string,
}
-export default function Prompt({ prompt, done, options }, context) {
+export default function Prompt({ prompt, done, options }) {
const opts = []
- function keyTaken(k) {
- return _.map(opts, 'key').includes(k)
- }
-
for (let i = 0; i < options.length; i++) {
let opt = options[i]
if (_.isString(opt)) {
@@ -35,7 +27,11 @@ export default function Prompt({ prompt, done, options }, context) {
}
opts.push(opt)
}
-
+
+ function keyTaken(k) {
+ return _.map(opts, 'key').includes(k)
+ }
+
function onKeyDown(event) {
event.stopPropagation()
event.preventDefault()
@@ -44,7 +40,6 @@ export default function Prompt({ prompt, done, options }, context) {
return
}
done(key.key || false)
- context.returnFocus()
}
return (
diff --git a/web/src/js/components/ProxyApp.jsx b/web/src/js/components/ProxyApp.jsx
index 1ac979bc..f0e33330 100644
--- a/web/src/js/components/ProxyApp.jsx
+++ b/web/src/js/components/ProxyApp.jsx
@@ -4,6 +4,7 @@ import _ from 'lodash'
import { connect } from 'react-redux'
import { init as appInit, destruct as appDestruct } from '../ducks/app'
+import { onKeyDown } from '../ducks/ui'
import Header from './Header'
import EventLog from './EventLog'
import Footer from './Footer'
@@ -11,124 +12,39 @@ import { Key } from '../utils.js'
class ProxyAppMain extends Component {
- static childContextTypes = {
- returnFocus: PropTypes.func.isRequired,
- }
-
static contextTypes = {
router: PropTypes.object.isRequired,
}
- constructor(props, context) {
- super(props, context)
-
- this.focus = this.focus.bind(this)
- this.onKeyDown = this.onKeyDown.bind(this)
- this.updateLocation = this.updateLocation.bind(this)
- }
-
componentWillMount() {
- this.props.appInit()
- }
-
- /**
- * @todo listen to window's key events
- */
- componentDidMount() {
- this.focus()
+ this.props.appInit(this.context.router)
+ window.addEventListener('keydown', this.props.onKeyDown);
}
componentWillUnmount() {
- this.props.appDestruct()
- }
-
- /**
- * @todo use props
- */
- getChildContext() {
- return { returnFocus: this.focus }
- }
-
- /**
- * @todo remove it
- */
- focus() {
- document.activeElement.blur()
- window.getSelection().removeAllRanges()
- ReactDOM.findDOMNode(this).focus()
- }
-
- /**
- * @todo move to actions
- * @todo bind on window
- */
- onKeyDown(e) {
- let name = null
-
- switch (e.keyCode) {
- case Key.I:
- name = 'intercept'
- break
- case Key.L:
- name = 'search'
- break
- case Key.H:
- name = 'highlight'
- break
- default:
- let main = this.refs.view
- if (this.refs.view.refs.wrappedInstance) {
- main = this.refs.view.refs.wrappedInstance
- }
- if (main.onMainKeyDown) {
- main.onMainKeyDown(e)
- }
- return // don't prevent default then
- }
-
- if (name) {
- const headerComponent = this.refs.header.refs.wrappedInstance || this.refs.header
- headerComponent.setState({ active: Header.entries[0] }, () => {
- const active = headerComponent.refs.active.refs.wrappedInstance || headerComponent.refs.active
- active.refs[name].select()
- })
- }
-
- e.preventDefault()
+ this.props.appDestruct(this.context.router)
+ window.removeEventListener('keydown', this.props.onKeyDown);
}
- /**
- * @todo move to actions
- */
- updateLocation(pathname, queryUpdate) {
- if (pathname === undefined) {
- pathname = this.props.location.pathname
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.query === this.props.query && nextProps.selectedFlowId === this.props.selectedFlowId && nextProps.panel === this.props.panel) {
+ return
}
- const query = this.props.location.query
- for (const key of Object.keys(queryUpdate || {})) {
- query[key] = queryUpdate[key] || undefined
+ if (nextProps.selectedFlowId) {
+ this.context.router.replace({ pathname: `/flows/${nextProps.selectedFlowId}/${nextProps.panel}`, query: nextProps.query })
+ } else {
+ this.context.router.replace({ pathname: '/flows', query: nextProps.query })
}
- this.context.router.replace({ pathname, query })
- }
-
- /**
- * @todo pass in with props
- */
- getQuery() {
- // 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.props.location.query)
}
render() {
- const { showEventLog, location, children } = this.props
- const query = this.getQuery()
+ const { showEventLog, location, children, query } = this.props
return (
- <div id="container" tabIndex="0" onKeyDown={this.onKeyDown}>
- <Header ref="header" updateLocation={this.updateLocation} query={query} />
+ <div id="container" tabIndex="0">
+ <Header ref="header" query={query} />
{React.cloneElement(
children,
- { ref: 'view', location, query, updateLocation: this.updateLocation }
+ { ref: 'view', location, query }
)}
{showEventLog && (
<EventLog key="eventlog"/>
@@ -142,10 +58,13 @@ class ProxyAppMain extends Component {
export default connect(
state => ({
showEventLog: state.eventLog.visible,
- settings: state.settings.settings,
+ query: state.ui.query,
+ panel: state.ui.panel,
+ selectedFlowId: state.flows.views.main.selected[0]
}),
{
appInit,
appDestruct,
+ onKeyDown
}
)(ProxyAppMain)
diff --git a/web/src/js/components/ValueEditor.jsx b/web/src/js/components/ValueEditor.jsx
index 0316924f..5f1bf2dc 100755
--- a/web/src/js/components/ValueEditor.jsx
+++ b/web/src/js/components/ValueEditor.jsx
@@ -4,27 +4,17 @@ import ValidateEditor from './ValueEditor/ValidateEditor'
export default class ValueEditor extends Component {
- static contextTypes = {
- returnFocus: PropTypes.func,
- }
-
static propTypes = {
content: PropTypes.string.isRequired,
onDone: PropTypes.func.isRequired,
inline: PropTypes.bool,
}
- constructor(props) {
- super(props)
- this.focus = this.focus.bind(this)
- }
-
render() {
- var tag = this.props.inline ? "span" : 'div'
+ var tag = this.props.inline ? 'span' : 'div'
return (
<ValidateEditor
{...this.props}
- onStop={() => this.context.returnFocus()}
tag={tag}
/>
)
diff --git a/web/src/js/ducks/ui.js b/web/src/js/ducks/ui.js
index 4de460aa..15334f88 100644
--- a/web/src/js/ducks/ui.js
+++ b/web/src/js/ducks/ui.js
@@ -1,42 +1,262 @@
-import {SELECT} from "./views/main"
-export const SET_ACTIVE_MENU = 'SET_ACTIVE_MENU';
+import { SELECT as SELECT_FLOW, selectRelative as selectFlowRelative } from './views/main'
+import { Key } from '../utils.js'
+import * as flowsActions from '../ducks/flows'
+export const SET_ACTIVE_MENU = 'UI_SET_ACTIVE_MENU'
+export const SET_CONTENT_VIEW = 'UI_SET_CONTENT_VIEW'
+export const SET_SELECTED_INPUT = 'UI_SET_SELECTED_INPUT'
+export const UPDATE_QUERY = 'UI_UPDATE_QUERY'
+export const SELECT_TAB = 'UI_SELECT_TAB'
+export const SELECT_TAB_RELATIVE = 'UI_SELECT_TAB_RELATIVE'
+export const SET_PROMPT = 'UI_SET_PROMPT'
+export const SET_DISPLAY_LARGE = 'UI_SET_DISPLAY_LARGE'
const defaultState = {
activeMenu: 'Start',
+ selectedInput: null,
+ displayLarge: false,
+ promptOpen: false,
+ contentView: 'ViewAuto',
+ query: {},
+ panel: 'request'
}
+
export default function reducer(state = defaultState, action) {
switch (action.type) {
+
case SET_ACTIVE_MENU:
return {
...state,
- activeMenu: action.activeMenu
+ activeMenu: action.activeMenu,
}
- case SELECT:
- let isNewSelect = (action.id && !action.currentSelection)
- let isDeselect = (!action.id && action.currentSelection)
- if(isNewSelect) {
+
+ case SELECT_FLOW:
+ if (action.flowId && !action.currentSelection) {
return {
...state,
- activeMenu: "Flow"
+ displayLarge: false,
+ activeMenu: 'Flow',
}
}
- if(isDeselect && state.activeMenu === "Flow") {
+
+ if (!action.flowId && state.activeMenu === 'Flow') {
return {
...state,
- activeMenu: "Start"
+ displayLarge: false,
+ activeMenu: 'Start',
}
}
- return state
+
+ return {
+ ...state,
+ displayLarge: false,
+ }
+
+ case SET_CONTENT_VIEW:
+ return {
+ ...state,
+ contentView: action.contentView,
+ }
+
+ case SET_SELECTED_INPUT:
+ return {
+ ...state,
+ selectedInput: action.input
+ }
+
+ case UPDATE_QUERY:
+ return {
+ ...state,
+ query: { ...state.query, ...action.query }
+ }
+
+ case SELECT_TAB:
+ return {
+ ...state,
+ panel: action.panel
+ }
+
+ case SELECT_TAB_RELATIVE:
+ if (!action.flow || action.shift === null) {
+ return {
+ ...state,
+ panel: 'request'
+ }
+ }
+ const tabs = ['request', 'response', 'error'].filter(k => action.flow[k]).concat(['details'])
+ return {
+ ...state,
+ panel: tabs[(tabs.indexOf(state.panel) + action.shift + tabs.length) % tabs.length]
+ }
+
+ case SET_PROMPT:
+ return {
+ ...state,
+ promptOpen: action.open,
+ }
+
+ case SET_DISPLAY_LARGE:
+ return {
+ ...state,
+ displayLarge: action.displayLarge,
+ }
+
default:
return state
}
}
export function setActiveMenu(activeMenu) {
- return {
- type: SET_ACTIVE_MENU,
- activeMenu
+ return { type: SET_ACTIVE_MENU, activeMenu }
+}
+
+export function setContentView(contentView) {
+ return { type: SET_CONTENT_VIEW, contentView }
+}
+
+export function setSelectedInput(input) {
+ return { type: SET_SELECTED_INPUT, input }
+}
+
+export function updateQuery(query) {
+ return { type: UPDATE_QUERY, query }
+}
+
+export function selectTab(panel) {
+ return { type: SELECT_TAB, panel }
+}
+
+export function selectTabRelative(shift) {
+ return (dispatch, getState) => {
+ let flow = getState().flows.list.byId[getState().flows.views.main.selected[0]]
+ dispatch({ type: SELECT_TAB_RELATIVE, shift, flow })
}
}
+export function setPrompt(open) {
+ return { type: SET_PROMPT, open }
+}
+
+export function setDisplayLarge(displayLarge) {
+ return { type: SET_DISPLAY_LARGE, displayLarge }
+}
+
+export function onKeyDown(e) {
+ if(e.ctrlKey) {
+ return () => {}
+ }
+ var key = e.keyCode
+ var shiftKey = e.shiftKey
+ e.preventDefault()
+ return (dispatch, getState) => {
+ switch (key) {
+
+ case Key.I:
+ dispatch(setSelectedInput('intercept'))
+ break
+
+ case Key.L:
+ dispatch(setSelectedInput('search'))
+ break
+
+ case Key.H:
+ dispatch(setSelectedInput('highlight'))
+ break
+
+ case Key.K:
+ case Key.UP:
+ dispatch(selectFlowRelative(-1))
+ break
+
+ case Key.J:
+ case Key.DOWN:
+ dispatch(selectFlowRelative(+1))
+ break
+
+ case Key.SPACE:
+ case Key.PAGE_DOWN:
+ dispatch(selectFlowRelative(+10))
+ break
+
+ case Key.PAGE_UP:
+ dispatch(selectFlowRelative(-10))
+ break
+
+ case Key.END:
+ dispatch(selectFlowRelative(+1e10))
+ break
+
+ case Key.HOME:
+ dispatch(selectFlowRelative(-1e10))
+ break
+
+ case Key.ESC:
+ dispatch(selectFlowRelative(null))
+ dispatch(selectTabRelative(null))
+ break
+
+ case Key.H:
+ case Key.LEFT:
+ dispatch(selectTabRelative(-1))
+ break
+
+ case Key.L:
+ case Key.TAB:
+ case Key.RIGHT:
+ dispatch(selectTabRelative(+1))
+ break
+
+ case Key.C:
+ if (shiftKey) {
+ dispatch(flowsActions.clear())
+ }
+ break
+
+ case Key.D: {
+ const flow = getState().flows.list.byId[getState().flows.views.main.selected[0]]
+ if (!flow) {
+ return
+ }
+ if (shiftKey) {
+ dispatch(flowsActions.duplicate(flow))
+ } else {
+ dispatch(flowsActions.remove(flow))
+ }
+ break
+ }
+
+ case Key.A: {
+ const flow = getState().flows.list.byId[getState().flows.views.main.selected[0]]
+ if (shiftKey) {
+ dispatch(flowsActions.acceptAll())
+ } else if (flow && flow.intercepted) {
+ dispatch(flowsActions.accept(flow))
+ }
+ break
+ }
+
+ case Key.R: {
+ const flow = getState().flows.list.byId[getState().flows.views.main.selected[0]]
+ if (!shiftKey && flow) {
+ dispatch(flowsActions.replay(flow))
+ }
+ break
+ }
+
+ case Key.V: {
+ const flow = getState().flows.list.byId[getState().flows.views.main.selected[0]]
+ if (!shiftKey && flow && flow.modified) {
+ dispatch(flowsActions.revert(flow))
+ }
+ break
+ }
+
+ case Key.E:
+ dispatch(setPrompt(true))
+ break
+
+ default:
+ return () => {}
+ }
+ }
+}
diff --git a/web/src/js/ducks/views/main.js b/web/src/js/ducks/views/main.js
index f4968de4..db9de619 100755
--- a/web/src/js/ducks/views/main.js
+++ b/web/src/js/ducks/views/main.js
@@ -7,6 +7,7 @@ export const UPDATE_FILTER = 'FLOW_VIEWS_MAIN_UPDATE_FILTER'
export const UPDATE_SORT = 'FLOW_VIEWS_MAIN_UPDATE_SORT'
export const UPDATE_HIGHLIGHT = 'FLOW_VIEWS_MAIN_UPDATE_HIGHLIGHT'
export const SELECT = 'FLOW_VIEWS_MAIN_SELECT'
+export const SELECT_RELATIVE = 'SELECT_RELATIVE'
const sortKeyFuns = {
@@ -52,6 +53,27 @@ export default function reduce(state = defaultState, action) {
selected: [action.id]
}
+ case SELECT_RELATIVE:
+ if(action.shift === null) {
+ return {
+ ...state,
+ selected: []
+ }
+ }
+ let id = state.selected[0]
+ let index = 0
+ if(!id && action.shift < 0) {
+ index = state.view.data.length - 1
+ } else if(id) {
+ index = state.view.indexOf[id] + action.shift
+ index = index < 0 ? 0 : index
+ index = index > state.view.data.length - 1 ? state.view.data.length - 1 : index
+ }
+ return {
+ ...state,
+ selected: [state.view.data[index].id]
+ }
+
case UPDATE_FILTER:
return {
...state,
@@ -171,6 +193,15 @@ export function select(id) {
}
/**
+ * @public
+ */
+export function selectRelative(shift) {
+ return (dispatch, getState) => {
+ dispatch({ type: SELECT_RELATIVE, currentSelection: getState().flows.views.main.selected[0], shift })
+ }
+}
+
+/**
* @private
*/
function makeFilter(filter) {