From 571c817f2176008c460c736580c0b35385808a2e Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 25 Jun 2016 00:36:39 +0800 Subject: [web] add msgQueue --- mitmproxy/web/static/app.js | 87 ++++++++++++++++--------------- web/src/js/ducks/eventLog.js | 39 +++----------- web/src/js/ducks/flows.js | 46 ++++------------- web/src/js/ducks/index.js | 10 ++-- web/src/js/ducks/msgQueue.js | 113 +++++++++++++++++++++++++++++++++++++++++ web/src/js/ducks/settings.js | 86 +++++++++++++++---------------- web/src/js/ducks/utils/list.js | 85 ++++++++++++++++++------------- web/src/js/ducks/utils/view.js | 6 +-- web/src/js/ducks/websocket.js | 39 +++----------- 9 files changed, 278 insertions(+), 233 deletions(-) create mode 100644 web/src/js/ducks/msgQueue.js diff --git a/mitmproxy/web/static/app.js b/mitmproxy/web/static/app.js index 7a8f3838..7f7726d4 100644 --- a/mitmproxy/web/static/app.js +++ b/mitmproxy/web/static/app.js @@ -1,22 +1,22 @@ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o1048576*(_ContentViews.ViewImage.matches(e)?10:.2)}},{key:"render",value:function(){var e=this.props,t=e.flow,r=e.message,n=this.state,o=n.displayLarge,a=n.View;return 0===r.contentLength?_react2["default"].createElement(ContentErrors.ContentEmpty,this.props):null===r.contentLength?_react2["default"].createElement(ContentErrors.ContentMissing,this.props):!o&&this.isContentTooLarge(r)?_react2["default"].createElement(ContentErrors.ContentTooLarge,_extends({},this.props,{onClick:this.displayLarge})):_react2["default"].createElement("div",null,a.textView?_react2["default"].createElement(_ContentLoader2["default"],{flow:t,message:r},_react2["default"].createElement(this.state.View,{content:""})):_react2["default"].createElement(a,{flow:t,message:r}),_react2["default"].createElement("div",{className:"view-options text-center"},_react2["default"].createElement(_ViewSelector2["default"],{onSelectView:this.selectView,active:a,message:r})," ",_react2["default"].createElement("a",{className:"btn btn-default btn-xs",href:_utils.MessageUtils.getContentURL(t,r)},_react2["default"].createElement("i",{className:"fa fa-download"}))))}}]),t}(_react.Component);ContentView.propTypes={flow:_react2["default"].PropTypes.object.isRequired,message:_react2["default"].PropTypes.object.isRequired},exports["default"]=ContentView; -},{"../flow/utils.js":53,"./ContentView/ContentErrors":4,"./ContentView/ContentLoader":5,"./ContentView/ContentViews":6,"./ContentView/ViewSelector":7,"react":"react"}],4:[function(require,module,exports){ +},{"../flow/utils.js":54,"./ContentView/ContentErrors":4,"./ContentView/ContentLoader":5,"./ContentView/ContentViews":6,"./ContentView/ViewSelector":7,"react":"react"}],4:[function(require,module,exports){ "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"},"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"},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"},_react2["default"].createElement("button",{onClick:n,className:"btn btn-xs btn-warning pull-right"},"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),_ContentViews=require("./ContentViews"),_utils=require("../../utils.js"); -},{"../../utils.js":54,"./ContentViews":6,"react":"react"}],5:[function(require,module,exports){ +},{"../../utils.js":55,"./ContentViews":6,"react":"react"}],5:[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;nn-i?l.scrollTop=n-i:u>c+s&&(l.scrollTop=u-s)}}},{key:"componentWillReceiveProps",value:function(e){e.selected&&e.selected!==this.props.selected&&(this.shouldScrollIntoView=!0)}},{key:"onViewportUpdate",value:function(){var e=_reactDom2["default"].findDOMNode(this),t=e.scrollTop,o=(0,_VirtualScroll.calcVScroll)({viewportTop:t,viewportHeight:e.offsetHeight,itemCount:this.props.flows.length,rowHeight:this.props.rowHeight});this.state.viewportTop===t&&(0,_shallowequal2["default"])(this.state.vScroll,o)||this.setState({vScroll:o,viewportTop:t})}},{key:"render",value:function(){var e=this,t=this.state,o=t.vScroll,r=t.viewportTop,l=this.props,a=l.flows,i=l.selected,n=l.highlight,u=n?_filt2["default"].parse(n):function(){return!1};return _react2["default"].createElement("div",{className:"flow-table",onScroll:this.onViewportUpdate},_react2["default"].createElement("table",null,_react2["default"].createElement("thead",{ref:"head",style:{transform:"translateY("+r+"px)"}},_react2["default"].createElement(_FlowTableHead2["default"],null)),_react2["default"].createElement("tbody",null,_react2["default"].createElement("tr",{style:{height:o.paddingTop}}),a.slice(o.start,o.end).map(function(t){return _react2["default"].createElement(_FlowRow2["default"],{key:t.id,flow:t,selected:t===i,highlighted:u(t),onSelect:e.props.onSelect})}),_react2["default"].createElement("tr",{style:{height:o.paddingBottom}}))))}}]),t}(_react2["default"].Component);FlowTable.propTypes={onSelect:_react.PropTypes.func.isRequired,flows:_react.PropTypes.array.isRequired,rowHeight:_react.PropTypes.number,highlight:_react.PropTypes.string,selected:_react.PropTypes.object},FlowTable.defaultProps={rowHeight:32},exports["default"]=(0,_AutoScroll2["default"])(FlowTable); -},{"../filt/filt":52,"./FlowTable/FlowRow":12,"./FlowTable/FlowTableHead":13,"./helpers/AutoScroll":38,"./helpers/VirtualScroll":39,"react":"react","react-dom":"react-dom","shallowequal":"shallowequal"}],11:[function(require,module,exports){ +},{"../filt/filt":53,"./FlowTable/FlowRow":12,"./FlowTable/FlowTableHead":13,"./helpers/AutoScroll":38,"./helpers/VirtualScroll":39,"react":"react","react-dom":"react-dom","shallowequal":"shallowequal"}],11:[function(require,module,exports){ "use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function TLSColumn(e){var t=e.flow;return _react2["default"].createElement("td",{className:(0,_classnames2["default"])("col-tls","https"===t.request.scheme?"col-tls-https":"col-tls-http")})}function IconColumn(e){var t=e.flow;return _react2["default"].createElement("td",{className:"col-icon"},_react2["default"].createElement("div",{className:(0,_classnames2["default"])("resource-icon",IconColumn.getIcon(t))}))}function PathColumn(e){var t=e.flow;return _react2["default"].createElement("td",{className:"col-path"},t.request.is_replay&&_react2["default"].createElement("i",{className:"fa fa-fw fa-repeat pull-right"}),t.intercepted&&_react2["default"].createElement("i",{className:"fa fa-fw fa-pause pull-right"}),_utils.RequestUtils.pretty_url(t.request))}function MethodColumn(e){var t=e.flow;return _react2["default"].createElement("td",{className:"col-method"},t.request.method)}function StatusColumn(e){var t=e.flow;return _react2["default"].createElement("td",{className:"col-status"},t.response&&t.response.status_code)}function SizeColumn(e){var t=e.flow;return _react2["default"].createElement("td",{className:"col-size"},(0,_utils2.formatSize)(SizeColumn.getTotalSize(t)))}function TimeColumn(e){var t=e.flow;return _react2["default"].createElement("td",{className:"col-time"},t.response?(0,_utils2.formatTimeDelta)(1e3*(t.response.timestamp_end-t.request.timestamp_start)):"...")}Object.defineProperty(exports,"__esModule",{value:!0}),exports.TLSColumn=TLSColumn,exports.IconColumn=IconColumn,exports.PathColumn=PathColumn,exports.MethodColumn=MethodColumn,exports.StatusColumn=StatusColumn,exports.SizeColumn=SizeColumn,exports.TimeColumn=TimeColumn;var _react=require("react"),_react2=_interopRequireDefault(_react),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_utils=require("../../flow/utils.js"),_utils2=require("../../utils.js");TLSColumn.headerClass="col-tls",TLSColumn.headerName="",IconColumn.headerClass="col-icon",IconColumn.headerName="",IconColumn.getIcon=function(e){if(!e.response)return"resource-icon-plain";var t=_utils.ResponseUtils.getContentType(e.response)||"";return 304===e.response.status_code?"resource-icon-not-modified":300<=e.response.status_code&&e.response.status_code<400?"resource-icon-redirect":t.indexOf("image")>=0?"resource-icon-image":t.indexOf("javascript")>=0?"resource-icon-js":t.indexOf("css")>=0?"resource-icon-css":t.indexOf("html")>=0?"resource-icon-document":"resource-icon-plain"},PathColumn.headerClass="col-path",PathColumn.headerName="Path",MethodColumn.headerClass="col-method",MethodColumn.headerName="Method",StatusColumn.headerClass="col-status",StatusColumn.headerName="Status",SizeColumn.getTotalSize=function(e){var t=e.request.contentLength;return e.response&&(t+=e.response.contentLength||0),t},SizeColumn.headerClass="col-size",SizeColumn.headerName="Size",TimeColumn.headerClass="col-time",TimeColumn.headerName="Time",exports["default"]=[TLSColumn,IconColumn,PathColumn,MethodColumn,StatusColumn,SizeColumn,TimeColumn]; -},{"../../flow/utils.js":53,"../../utils.js":54,"classnames":"classnames","react":"react"}],12:[function(require,module,exports){ +},{"../../flow/utils.js":54,"../../utils.js":55,"classnames":"classnames","react":"react"}],12:[function(require,module,exports){ "use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function FlowRow(e){var t=e.flow,r=e.selected,l=e.highlighted,o=e.onSelect,s=(0,_classnames2["default"])({selected:r,highlighted:l,intercepted:t.intercepted,"has-request":t.request,"has-response":t.response});return _react2["default"].createElement("tr",{className:s,onClick:function(){return o(t)}},_FlowColumns2["default"].map(function(e){return _react2["default"].createElement(e,{key:e.name,flow:t})}))}Object.defineProperty(exports,"__esModule",{value:!0}),exports["default"]=FlowRow;var _react=require("react"),_react2=_interopRequireDefault(_react),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_FlowColumns=require("./FlowColumns"),_FlowColumns2=_interopRequireDefault(_FlowColumns);FlowRow.propTypes={onSelect:_react.PropTypes.func.isRequired,flow:_react.PropTypes.object.isRequired,highlighted:_react.PropTypes.bool,selected:_react.PropTypes.bool}; },{"./FlowColumns":11,"classnames":"classnames","react":"react"}],13:[function(require,module,exports){ "use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{"default":e}}function FlowTableHead(e){var r=e.sortColumn,t=e.sortDesc,a=e.onSort,s=t?"sort-desc":"sort-asc";return _react2["default"].createElement("tr",null,_FlowColumns2["default"].map(function(e){return _react2["default"].createElement("th",{className:(0,_classnames2["default"])(e.headerClass,r===e.name&&s),key:e.name,onClick:function(){return a(e.name,e.name!==r?!1:!t)}},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={onSort:_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.sorter.desc,sortColumn:e.flows.views.main.sorter.column}},{onSort:_main.updateSorter})(FlowTableHead); -},{"../../ducks/views/main":50,"./FlowColumns":11,"classnames":"classnames","react":"react","react-redux":"react-redux"}],14:[function(require,module,exports){ +},{"../../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 _createClass=function(){function e(e,t){for(var r=0;r0&&(r.preventDefault(),this.refs[e-1+"-value"].focus())}},{key:"render",value:function(){var e=this,t=this.props.message;return _react2["default"].createElement("table",{className:"header-table"},_react2["default"].createElement("tbody",null,t.headers.map(function(t,r){return _react2["default"].createElement("tr",{key:r},_react2["default"].createElement("td",{className:"header-name"},_react2["default"].createElement(HeaderEditor,{ref:r+"-key",content:t[0],onDone:function(t){return e.onChange(r,0,t)},onRemove:function(t){return e.onRemove(r,0,t)},onTab:function(t){return e.onTab(r,0,t)}}),":"),_react2["default"].createElement("td",{className:"header-value"},_react2["default"].createElement(HeaderEditor,{ref:r+"-value",content:t[1],onDone:function(t){return e.onChange(r,1,t)},onRemove:function(t){return e.onRemove(r,1,t)},onTab:function(t){return e.onTab(r,1,t)}})))})))}}]),t}(_react.Component);Headers.propTypes={onChange:_react.PropTypes.func.isRequired,message:_react.PropTypes.object.isRequired},exports["default"]=Headers; -},{"../../utils.js":54,"../ValueEditor":31,"react":"react","react-dom":"react-dom"}],17:[function(require,module,exports){ +},{"../../utils.js":55,"../ValueEditor":31,"react":"react","react-dom":"react-dom"}],17:[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)}function Error(e){var t=e.flow;return _react2["default"].createElement("section",null,_react2["default"].createElement("div",{className:"alert alert-warning"},t.error.msg,_react2["default"].createElement("div",null,_react2["default"].createElement("small",null,(0,_utils2.formatTimeStamp)(t.error.timestamp)))))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.Response=exports.Request=void 0;var _createClass=function(){function e(e,t){for(var r=0;r0&&(flowActions.upload(e.target.files[0]),this.fileInput.value="")}},{key:"onSaveClick",value:function(e){e.preventDefault(),flowActions.download()}},{key:"render",value:function(){var e=this;return _react2["default"].createElement("div",{className:(0,_classnames2["default"])("dropdown pull-left",{open:this.state.show})},_react2["default"].createElement("a",{href:"#",className:"special",onClick:this.onFileClick},"mitmproxy"),_react2["default"].createElement("ul",{className:"dropdown-menu",role:"menu"},_react2["default"].createElement("li",null,_react2["default"].createElement("a",{href:"#",onClick:this.onNewClick},_react2["default"].createElement("i",{className:"fa fa-fw fa-file"}),"New")),_react2["default"].createElement("li",null,_react2["default"].createElement("a",{href:"#",onClick:this.onOpenClick},_react2["default"].createElement("i",{className:"fa fa-fw fa-folder-open"}),"Open..."),_react2["default"].createElement("input",{ref:function(t){return e.fileInput=t},className:"hidden",type:"file",onChange:this.onOpenFile})),_react2["default"].createElement("li",null,_react2["default"].createElement("a",{href:"#",onClick:this.onSaveClick},_react2["default"].createElement("i",{className:"fa fa-fw fa-floppy-o"}),"Save...")),_react2["default"].createElement("li",{role:"presentation",className:"divider"}),_react2["default"].createElement("li",null,_react2["default"].createElement("a",{href:"http://mitm.it/",target:"_blank"},_react2["default"].createElement("i",{className:"fa fa-fw fa-external-link"}),"Install Certificates..."))))}}]),t}(_react.Component);exports["default"]=FileMenu; },{"../../ducks/flows":43,"classnames":"classnames","react":"react"}],22:[function(require,module,exports){ @@ -67,34 +67,34 @@ },{"jquery":"jquery","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;ne&&(a=i.length-1),this.selectFlow(i[a])}},{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&&_actions.FlowActions.clear();break;case _utils.Key.D:t&&(e.shiftKey?_actions.FlowActions.duplicate(t):_actions.FlowActions["delete"](t));break;case _utils.Key.A:e.shiftKey?_actions.FlowActions.accept_all():t&&t.intercepted&&_actions.FlowActions.accept(t);break;case _utils.Key.R:!e.shiftKey&&t&&_actions.FlowActions.replay(t);break;case _utils.Key.V:e.shiftKey&&t&&t.modified&&_actions.FlowActions.revert(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,i=t.flows,l=t.selectedFlow,s=t.highlight;return _react2["default"].createElement("div",{className:"main-view"},_react2["default"].createElement(_FlowTable2["default"],{ref:"flowTable",flows:i,selected:l,highlight:s,onSelect:function(t){return e.selectFlow(t)}}),l&&[_react2["default"].createElement(_Splitter2["default"],{key:"splitter"}),_react2["default"].createElement(_FlowView2["default"],{key:"flowDetails",ref:"flowDetails",tab:this.props.routeParams.detailTab,query:this.props.query,updateLocation:this.props.updateLocation,flow:l})])}}]),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.data[e.flows.views.main.selected[0]]}},{selectFlow:_main.selectFlow,updateFilter:_main.updateFilter,updateHighlight:_main.updateHighlight},void 0,{withRef:!0})(MainView); -},{"../actions.js":1,"../ducks/views/main":50,"../utils.js":54,"./FlowTable":10,"./FlowView":14,"./common/Splitter":35,"react":"react","react-redux":"react-redux"}],29:[function(require,module,exports){ +},{"../actions.js":1,"../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(i,"key").includes(e)}function o(e){e.stopPropagation(),e.preventDefault();var r=i.find(function(t){return _utils.Key[t.key.toUpperCase()]===e.keyCode});(r||e.keyCode===_utils.Key.ESC||e.keyCode===_utils.Key.ENTER)&&(n(k||!1),t.returnFocus())}for(var a=e.prompt,n=e.done,u=e.options,i=[],s=0;s0&&r(p[0]);)p=p.substr(1);l={text:l,key:p[0]}}if(!l.text||!l.key||r(l.key))throw"invalid options";i.push(l)}return _react2["default"].createElement("div",{tabIndex:"0",onKeyDown:o,onClick:onClick,className:"prompt-dialog"},_react2["default"].createElement("div",{className:"prompt-content"},a||_react2["default"].createElement("strong",null,"Select: "),i.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},-1!==r?e.text.substring(0,r):e.text+"(",prefix,_react2["default"].createElement("strong",{className:"text-primary"},e.key),-1!==r?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}; -},{"../utils.js":54,"lodash":"lodash","react":"react","react-dom":"react-dom"}],30:[function(require,module,exports){ +},{"../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;r0)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; -},{"../../utils.js":54,"react":"react","react-dom":"react-dom"}],33:[function(require,module,exports){ +},{"../../utils.js":55,"react":"react","react-dom":"react-dom"}],33:[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=n;d--)o[a[d].id]=d;return{data:a,indexOf:o}}function sortedRemove(e,t){var r=e.indexOf[t],n=[].concat(_toConsumableArray(e.data)),a=_extends({},e.indexOf,_defineProperty({},t,null));n.splice(r,1);for(var o=n.length-1;o>=r;o--)a[n[o].id]=o;return{data:n,indexOf:a}}function sortedIndex(e,t,r){for(var n=0,a=e.length;a>n;){var o=n+a>>>1;r(t,e[o])>0?n=o+1:a=o}return n}function defaultFilter(){return!0}function defaultSorter(e,t){return 0}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RECEIVE=exports.REMOVE=exports.UPDATE=exports.ADD=exports.UPDATE_SORTER=exports.UPDATE_FILTER=void 0;var _extends=Object.assign||function(e){for(var t=1;t=u;s--)o[i[s].id]=s;return _extends({},e,{data:i,indexOf:o,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=n;d--)a[o[d].id]=d;return{data:o,indexOf:a}}function sortedRemove(e,t){var r=e.indexOf[t],n=[].concat(_toConsumableArray(e.data)),o=_extends({},e.indexOf,_defineProperty({},t,null));n.splice(r,1);for(var a=n.length-1;a>=r;a--)o[n[a].id]=a;return{data:n,indexOf:o}}function sortedIndex(e,t,r){for(var n=0,o=e.length;o>n;){var a=n+o>>>1;r(t,e[a])>=0?n=a+1:o=a}return n}function defaultFilter(){return!0}function defaultSorter(e,t){return 0}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RECEIVE=exports.REMOVE=exports.UPDATE=exports.ADD=exports.UPDATE_SORTER=exports.UPDATE_FILTER=void 0;var _extends=Object.assign||function(e){for(var t=1;ts?r?-1:1:s>n?r?1:-1:0}:void 0}Object.defineProperty(exports,"__esModule",{value:!0}),exports.SELECT=exports.UPDATE_HIGHLIGHT=exports.UPDATE_SORTER=exports.UPDATE_FILTER=void 0;var _extends=Object.assign||function(e){for(var t=1;tr;)n=e.charAt(r),"\n"===n?(i.seenCR||i.line++,i.column=1,i.seenCR=!1):"\r"===n||"\u2028"===n||"\u2029"===n?(i.line++,i.column=1,i.seenCR=!0):(i.column++,i.seenCR=!1),r++;return Ot[t]=i,i}function n(e,t){var n=r(e),i=r(t);return{start:{offset:e,line:n.line,column:n.column},end:{offset:t,line:i.line,column:i.column}}}function i(e){Pt>Mt||(Mt>Pt&&(Pt=Mt,Qt=[]),Qt.push(e))}function s(e,r,n,i){function s(e){var t=1;for(e.sort(function(e,t){return e.descriptiont.description?1:0});t1?u.slice(0,-1).join(", ")+" or "+u[e.length-1]:u[0],i=t?'"'+r(t)+'"':"end of input","Expected "+n+" but "+i+" found."}return null!==r&&s(r),new t(null!==e?e:u(r,n),r,n,i)}function u(){var e,t,r,n;return Vt++,e=Mt,t=a(),t!==P?(r=l(),r!==P?(n=a(),n!==P?(Nt=e,t=X(r),e=t):(Mt=e,e=P)):(Mt=e,e=P)):(Mt=e,e=P),Vt--,e===P&&(t=P,0===Vt&&i(W)),e}function c(){var t,r;return Vt++,Z.test(e.charAt(Mt))?(t=e.charAt(Mt),Mt++):(t=P,0===Vt&&i($)),Vt--,t===P&&(r=P,0===Vt&&i(Y)),t}function o(){var t,r;return Vt++,te.test(e.charAt(Mt))?(t=e.charAt(Mt),Mt++):(t=P,0===Vt&&i(re)),Vt--,t===P&&(r=P,0===Vt&&i(ee)),t}function a(){var e,t;for(Vt++,e=[],t=c();t!==P;)e.push(t),t=c();return Vt--,e===P&&(t=P,0===Vt&&i(ne)),e}function l(){var t,r,n,s,u,c;return t=Mt,r=p(),r!==P?(n=a(),n!==P?(124===e.charCodeAt(Mt)?(s=ie,Mt++):(s=P,0===Vt&&i(se)),s!==P?(u=a(),u!==P?(c=l(),c!==P?(Nt=t,r=ue(r,c),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=p()),t}function p(){var t,r,n,s,u,o;if(t=Mt,r=f(),r!==P?(n=a(),n!==P?(38===e.charCodeAt(Mt)?(s=ce,Mt++):(s=P,0===Vt&&i(oe)),s!==P?(u=a(),u!==P?(o=p(),o!==P?(Nt=t,r=ae(r,o),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P){if(t=Mt,r=f(),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=p(),s!==P?(Nt=t,r=ae(r,s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;t===P&&(t=f())}return t}function f(){var t,r,n,s;return t=Mt,33===e.charCodeAt(Mt)?(r=le,Mt++):(r=P,0===Vt&&i(pe)),r!==P?(n=a(),n!==P?(s=f(),s!==P?(Nt=t,r=fe(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=h()),t}function h(){var t,r,n,s,u,c;return t=Mt,40===e.charCodeAt(Mt)?(r=he,Mt++):(r=P,0===Vt&&i(de)),r!==P?(n=a(),n!==P?(s=l(),s!==P?(u=a(),u!==P?(41===e.charCodeAt(Mt)?(c=ve,Mt++):(c=P,0===Vt&&i(ye)),c!==P?(Nt=t,r=ge(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=d()),t}function d(){var e;return e=v(),e===P&&(e=g()),e}function v(){var t,r;return t=y(),t===P&&(t=Mt,e.substr(Mt,2)===Ae?(r=Ae,Mt+=2):(r=P,0===Vt&&i(xe)),r!==P&&(Nt=t,r=Re()),t=r,t===P&&(t=Mt,e.substr(Mt,2)===me?(r=me,Mt+=2):(r=P,0===Vt&&i(qe)),r!==P&&(Nt=t,r=Ce()),t=r,t===P&&(t=Mt,e.substr(Mt,2)===we?(r=we,Mt+=2):(r=P,0===Vt&&i(Ee)),r!==P&&(Nt=t,r=be()),t=r,t===P&&(t=Mt,e.substr(Mt,2)===Fe?(r=Fe,Mt+=2):(r=P,0===Vt&&i(Ue)),r!==P&&(Nt=t,r=je()),t=r)))),t}function y(){var t,r;return t=Mt,e.substr(Mt,4)===Te?(r=Te,Mt+=4):(r=P,0===Vt&&i(_e)),r!==P&&(Nt=t,r=Se()),t=r,t===P&&(t=Mt,e.substr(Mt,5)===ke?(r=ke,Mt+=5):(r=P,0===Vt&&i(Be)),r!==P&&(Nt=t,r=Ie()),t=r),t}function g(){var t,r,n,s;if(t=Mt,e.substr(Mt,2)===ze?(r=ze,Mt+=2):(r=P,0===Vt&&i(De)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=A(),s!==P?(Nt=t,r=Ge(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===He?(r=He,Mt+=2):(r=P,0===Vt&&i(Je)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Ke(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===Le?(r=Le,Mt+=2):(r=P,0===Vt&&i(Me)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Ne(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===Oe?(r=Oe,Mt+=3):(r=P,0===Vt&&i(Pe)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Qe(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===Ve?(r=Ve,Mt+=3):(r=P,0===Vt&&i(We)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=Xe(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===Ye?(r=Ye,Mt+=2):(r=P,0===Vt&&i(Ze)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=$e(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===et?(r=et,Mt+=2):(r=P,0===Vt&&i(tt)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=rt(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===nt?(r=nt,Mt+=3):(r=P,0===Vt&&i(it)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=st(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,3)===ut?(r=ut,Mt+=3):(r=P,0===Vt&&i(ct)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=ot(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,e.substr(Mt,2)===at?(r=at,Mt+=2):(r=P,0===Vt&&i(lt)),r!==P){if(n=[],s=c(),s!==P)for(;s!==P;)n.push(s),s=c();else n=P;n!==P?(s=x(),s!==P?(Nt=t,r=pt(s),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;t===P&&(t=Mt,r=x(),r!==P&&(Nt=t,r=pt(r)),t=r)}}}}}}}}}return t}function A(){var t,r,n,s;if(Vt++,t=Mt,ht.test(e.charAt(Mt))?(r=e.charAt(Mt),Mt++):(r=P,0===Vt&&i(dt)),r===P&&(r=null),r!==P){if(n=[],vt.test(e.charAt(Mt))?(s=e.charAt(Mt),Mt++):(s=P,0===Vt&&i(yt)),s!==P)for(;s!==P;)n.push(s),vt.test(e.charAt(Mt))?(s=e.charAt(Mt),Mt++):(s=P,0===Vt&&i(yt));else n=P;n!==P?(ht.test(e.charAt(Mt))?(s=e.charAt(Mt),Mt++):(s=P,0===Vt&&i(dt)),s===P&&(s=null),s!==P?(Nt=t,r=gt(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;return Vt--,t===P&&(r=P,0===Vt&&i(ft)),t}function x(){var t,r,n,s;if(Vt++,t=Mt,34===e.charCodeAt(Mt)?(r=xt,Mt++):(r=P,0===Vt&&i(Rt)),r!==P){for(n=[],s=R();s!==P;)n.push(s),s=R();n!==P?(34===e.charCodeAt(Mt)?(s=xt,Mt++):(s=P,0===Vt&&i(Rt)),s!==P?(Nt=t,r=mt(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P){if(t=Mt,39===e.charCodeAt(Mt)?(r=qt,Mt++):(r=P,0===Vt&&i(Ct)),r!==P){for(n=[],s=m();s!==P;)n.push(s),s=m();n!==P?(39===e.charCodeAt(Mt)?(s=qt,Mt++):(s=P,0===Vt&&i(Ct)),s!==P?(Nt=t,r=mt(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)}else Mt=t,t=P;if(t===P)if(t=Mt,r=Mt,Vt++,n=o(),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P){if(n=[],s=q(),s!==P)for(;s!==P;)n.push(s),s=q();else n=P;n!==P?(Nt=t,r=mt(n),t=r):(Mt=t,t=P)}else Mt=t,t=P}return Vt--,t===P&&(r=P,0===Vt&&i(At)),t}function R(){var t,r,n;return t=Mt,r=Mt,Vt++,wt.test(e.charAt(Mt))?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(Et)),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P?(e.length>Mt?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(bt)),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=Mt,92===e.charCodeAt(Mt)?(r=Ut,Mt++):(r=P,0===Vt&&i(jt)),r!==P?(n=C(),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)),t}function m(){var t,r,n;return t=Mt,r=Mt,Vt++,Tt.test(e.charAt(Mt))?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(_t)),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P?(e.length>Mt?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(bt)),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P),t===P&&(t=Mt,92===e.charCodeAt(Mt)?(r=Ut,Mt++):(r=P,0===Vt&&i(jt)),r!==P?(n=C(),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P)),t}function q(){var t,r,n;return t=Mt,r=Mt,Vt++,n=c(),Vt--,n===P?r=void 0:(Mt=r,r=P),r!==P?(e.length>Mt?(n=e.charAt(Mt),Mt++):(n=P,0===Vt&&i(bt)),n!==P?(Nt=t,r=Ft(n),t=r):(Mt=t,t=P)):(Mt=t,t=P),t}function C(){var t,r;return St.test(e.charAt(Mt))?(t=e.charAt(Mt),Mt++):(t=P,0===Vt&&i(kt)),t===P&&(t=Mt,110===e.charCodeAt(Mt)?(r=Bt,Mt++):(r=P,0===Vt&&i(It)),r!==P&&(Nt=t,r=zt()),t=r,t===P&&(t=Mt,114===e.charCodeAt(Mt)?(r=Dt,Mt++):(r=P,0===Vt&&i(Gt)),r!==P&&(Nt=t,r=Ht()),t=r,t===P&&(t=Mt,116===e.charCodeAt(Mt)?(r=Jt,Mt++):(r=P,0===Vt&&i(Kt)),r!==P&&(Nt=t,r=Lt()),t=r))),t}function w(e,t){function r(){return e.apply(this,arguments)||t.apply(this,arguments)}return r.desc=e.desc+" or "+t.desc,r}function E(e,t){function r(){return e.apply(this,arguments)&&t.apply(this,arguments)}return r.desc=e.desc+" and "+t.desc,r}function b(e){function t(){return!e.apply(this,arguments)}return t.desc="not "+e.desc,t}function F(e){function t(){return e.apply(this,arguments)}return t.desc="("+e.desc+")",t}function U(e){return!0}function j(e){return!1}function T(e){if(e.response)for(var t=Wt.ResponseUtils.getContentType(e.response),r=Xt.length;r--;)if(Xt[r].test(t))return!0;return!1}function _(e){function t(t){return t.response&&t.response.status_code===e}return t.desc="resp. code is "+e,t}function S(e){function t(t){return t.request&&e.test(t.request.host)}return e=new RegExp(e,"i"),t.desc="domain matches "+e,t}function k(e){return!!e.error}function B(e){function t(t){return t.request&&Wt.RequestUtils.match_header(t.request,e)||t.response&&Wt.ResponseUtils.match_header(t.response,e)}return e=new RegExp(e,"i"),t.desc="header matches "+e,t}function I(e){function t(t){return t.request&&Wt.RequestUtils.match_header(t.request,e)}return e=new RegExp(e,"i"),t.desc="req. header matches "+e,t}function z(e){function t(t){return t.response&&Wt.ResponseUtils.match_header(t.response,e)}return e=new RegExp(e,"i"),t.desc="resp. header matches "+e,t}function D(e){function t(t){return t.request&&e.test(t.request.method)}return e=new RegExp(e,"i"),t.desc="method matches "+e,t}function G(e){return e.request&&!e.response}function H(e){return!!e.response}function J(e){function t(t){return t.request&&e.test(Wt.RequestUtils.getContentType(t.request))||t.response&&e.test(Wt.ResponseUtils.getContentType(t.response))}return e=new RegExp(e,"i"),t.desc="content type matches "+e,t}function K(e){function t(t){return t.request&&e.test(Wt.RequestUtils.getContentType(t.request))}return e=new RegExp(e,"i"),t.desc="req. content type matches "+e,t}function L(e){function t(t){return t.response&&e.test(Wt.ResponseUtils.getContentType(t.response))}return e=new RegExp(e,"i"),t.desc="resp. content type matches "+e,t}function M(e){function t(t){return t.request&&e.test(Wt.RequestUtils.pretty_url(t.request))}return e=new RegExp(e,"i"),t.desc="url matches "+e,t}var N,O=arguments.length>1?arguments[1]:{},P={},Q={start:u},V=u,W={type:"other",description:"filter expression"},X=function(e){return e},Y={type:"other",description:"whitespace"},Z=/^[ \t\n\r]/,$={type:"class",value:"[ \\t\\n\\r]",description:"[ \\t\\n\\r]"},ee={type:"other",description:"control character"},te=/^[|&!()~"]/,re={type:"class",value:'[|&!()~"]',description:'[|&!()~"]'},ne={type:"other",description:"optional whitespace"},ie="|",se={type:"literal",value:"|",description:'"|"'},ue=function(e,t){return w(e,t)},ce="&",oe={type:"literal",value:"&",description:'"&"'},ae=function(e,t){return E(e,t)},le="!",pe={type:"literal",value:"!",description:'"!"'},fe=function(e){return b(e)},he="(",de={type:"literal",value:"(",description:'"("'},ve=")",ye={type:"literal",value:")",description:'")"'},ge=function(e){return F(e)},Ae="~a",xe={type:"literal",value:"~a",description:'"~a"'},Re=function(){return T},me="~e",qe={type:"literal",value:"~e",description:'"~e"'},Ce=function(){return k},we="~q",Ee={type:"literal",value:"~q",description:'"~q"'},be=function(){return G},Fe="~s",Ue={type:"literal",value:"~s",description:'"~s"'},je=function(){return H},Te="true",_e={type:"literal",value:"true",description:'"true"'},Se=function(){return U},ke="false",Be={type:"literal",value:"false",description:'"false"'},Ie=function(){return j},ze="~c",De={type:"literal",value:"~c",description:'"~c"'},Ge=function(e){return _(e)},He="~d",Je={type:"literal",value:"~d",description:'"~d"'},Ke=function(e){return S(e)},Le="~h",Me={type:"literal",value:"~h",description:'"~h"'},Ne=function(e){return B(e)},Oe="~hq",Pe={type:"literal",value:"~hq",description:'"~hq"'},Qe=function(e){return I(e)},Ve="~hs",We={type:"literal",value:"~hs",description:'"~hs"'},Xe=function(e){return z(e)},Ye="~m",Ze={type:"literal",value:"~m",description:'"~m"'},$e=function(e){return D(e)},et="~t",tt={type:"literal",value:"~t",description:'"~t"'},rt=function(e){return J(e)},nt="~tq",it={type:"literal",value:"~tq",description:'"~tq"'},st=function(e){return K(e)},ut="~ts",ct={type:"literal",value:"~ts",description:'"~ts"'},ot=function(e){return L(e)},at="~u",lt={type:"literal",value:"~u",description:'"~u"'},pt=function(e){return M(e)},ft={type:"other",description:"integer"},ht=/^['"]/,dt={type:"class",value:"['\"]",description:"['\"]"},vt=/^[0-9]/,yt={type:"class",value:"[0-9]",description:"[0-9]"},gt=function(e){return parseInt(e.join(""),10)},At={type:"other",description:"string"},xt='"',Rt={type:"literal",value:'"',description:'"\\""'},mt=function(e){return e.join("")},qt="'",Ct={type:"literal",value:"'",description:'"\'"'},wt=/^["\\]/,Et={type:"class",value:'["\\\\]',description:'["\\\\]'},bt={type:"any",description:"any character"},Ft=function(e){return e},Ut="\\",jt={type:"literal",value:"\\",description:'"\\\\"'},Tt=/^['\\]/,_t={type:"class",value:"['\\\\]",description:"['\\\\]"},St=/^['"\\]/,kt={type:"class",value:"['\"\\\\]",description:"['\"\\\\]"},Bt="n",It={type:"literal",value:"n",description:'"n"'},zt=function(){return"\n"},Dt="r",Gt={type:"literal",value:"r",description:'"r"'},Ht=function(){return"\r"},Jt="t",Kt={type:"literal",value:"t",description:'"t"'},Lt=function(){return" "},Mt=0,Nt=0,Ot=[{line:1,column:1,seenCR:!1}],Pt=0,Qt=[],Vt=0;if("startRule"in O){if(!(O.startRule in Q))throw new Error("Can't start parsing from rule \""+O.startRule+'".');V=Q[O.startRule]}var Wt=require("../flow/utils.js");U.desc="true",j.desc="false";var Xt=[new RegExp("text/javascript"),new RegExp("application/x-javascript"),new RegExp("application/javascript"),new RegExp("text/css"),new RegExp("image/.*"),new RegExp("application/x-shockwave-flash")];if(T.desc="is asset",k.desc="has error",G.desc="has no response",H.desc="has response",N=V(),N!==P&&Mt===e.length)return N;throw N!==P&&Mt=i;i++)Key[String.fromCharCode(i)]=i;var formatSize=exports.formatSize=function(e){if(0===e)return"0";for(var r=["b","kb","mb","gb","tb"],t=0;te);t++);var o;return o=e%Math.pow(1024,t)===0?0:1,(e/Math.pow(1024,t)).toFixed(o)+r[t]},formatTimeDelta=exports.formatTimeDelta=function(e){for(var r=e,t=["ms","s","min","h"],o=[1e3,60,60],n=0;Math.abs(r)>=o[n]&&n=0&&"/"===e.url[0]&&(-1===e.url.indexOf("?")?e.url+="?"+xsrf:e.url+="&"+xsrf)}),(0,_jquery2["default"])(document).ajaxError(function(e,r,t,o){if("abort"!==o){var n=r.responseText;console.error(o,n,arguments),alert(n)}}),fetchApi.put=function(e,r,t){return fetchApi(e,_extends({method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(r)},t))}; },{"./actions.js":1,"jquery":"jquery","lodash":"lodash","react":"react"}]},{},[2]) diff --git a/web/src/js/ducks/eventLog.js b/web/src/js/ducks/eventLog.js index 0c875689..50b24cd6 100644 --- a/web/src/js/ducks/eventLog.js +++ b/web/src/js/ducks/eventLog.js @@ -1,12 +1,12 @@ -import { fetchApi } from '../utils' import reduceList, * as listActions from './utils/list' import reduceView, * as viewActions from './utils/view' import * as websocketActions from './websocket' +import * as msgQueueActions from './msgQueue' -export const WS_MSG_TYPE = 'UPDATE_EVENTLOG' +export const MSG_TYPE = 'UPDATE_EVENTLOG' +export const DATA_URL = '/events' export const ADD = 'EVENTLOG_ADD' -export const REQUEST = 'EVENTLOG_REQUEST' export const RECEIVE = 'EVENTLOG_RECEIVE' export const TOGGLE_VISIBILITY = 'EVENTLOG_TOGGLE_VISIBILITY' export const TOGGLE_FILTER = 'EVENTLOG_TOGGLE_FILTER' @@ -51,12 +51,6 @@ export default function reduce(state = defaultState, action) { view: reduceView(state.view, viewActions.add(item, log => state.filters[log.level])), } - case REQUEST: - return { - ...state, - list: reduceList(state.list, listActions.request()), - } - case RECEIVE: const list = reduceList(state.list, listActions.receive(action.list)) return { @@ -120,33 +114,12 @@ export function handleWsMsg(msg) { * @public websocket */ export function fetchData() { - return dispatch => { - dispatch(request()) - - return fetchApi('/events') - .then(res => res.json()) - .then(json => dispatch(receive(json.data))) - .catch(error => dispatch(fetchError(error))) - } -} - -/** - * @private - */ -export function request() { - return { type: REQUEST } + return msgQueueActions.fetchData(MSG_TYPE) } /** - * @private + * @public msgQueue */ -export function receive(list) { +export function receiveData(list) { return { type: RECEIVE, list } } - -/** - * @private - */ -export function fetchError(error) { - return { type: FETCH_ERROR, error } -} diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js index f732f536..e9ac38f6 100644 --- a/web/src/js/ducks/flows.js +++ b/web/src/js/ducks/flows.js @@ -1,14 +1,15 @@ import { fetchApi } from '../utils' import reduceList, * as listActions from './utils/list' import reduceViews, * as viewsActions from './views' +import * as msgQueueActions from './msgQueue' import * as websocketActions from './websocket' -export const WS_MSG_TYPE = 'UPDATE_FLOWS' +export const MSG_TYPE = 'UPDATE_FLOWS' +export const DATA_URL = '/flows' export const ADD = 'FLOWS_ADD' export const UPDATE = 'FLOWS_UPDATE' export const REMOVE = 'FLOWS_REMOVE' -export const REQUEST = 'FLOWS_REQUEST' export const RECEIVE = 'FLOWS_RECEIVE' export const REQUEST_ACTION = 'FLOWS_REQUEST_ACTION' export const UNKNOWN_CMD = 'FLOWS_UNKNOWN_CMD' @@ -43,12 +44,6 @@ export default function reduce(state = defaultState, action) { views: reduceViews(state.views, viewsActions.remove(action.item.id)), } - case REQUEST: - return { - ...state, - list: reduceList(state.list, listActions.request()), - } - case RECEIVE: const list = reduceList(state.list, listActions.receive(action.list)) return { @@ -177,14 +172,14 @@ export function handleWsMsg(msg) { * @public websocket */ export function fetchData() { - return dispatch => { - dispatch(request()) + return msgQueueActions.fetchData(MSG_TYPE) +} - return fetchApi('/flows') - .then(res => res.json()) - .then(json => dispatch(receive(json.data))) - .catch(error => dispatch(fetchError(error))) - } +/** + * @public msgQueue + */ +export function receiveData(list) { + return { type: RECEIVE, list } } /** @@ -207,24 +202,3 @@ export function update(id, item) { export function remove(id) { return { type: REMOVE, id } } - -/** - * @private - */ -export function request() { - return { type: REQUEST } -} - -/** - * @private - */ -export function receive(list) { - return { type: RECEIVE, list } -} - -/** - * @private - */ -export function fetchError(error) { - return { type: FETCH_ERROR, error } -} diff --git a/web/src/js/ducks/index.js b/web/src/js/ducks/index.js index ffde1a64..c2488d70 100644 --- a/web/src/js/ducks/index.js +++ b/web/src/js/ducks/index.js @@ -1,16 +1,16 @@ -import {combineReducers} from 'redux' +import { combineReducers } from 'redux' import eventLog from './eventLog' import websocket from './websocket' import flows from './flows' import settings from './settings' import ui from './ui' +import msgQueue from './msgQueue' -const rootReducer = combineReducers({ +export default combineReducers({ eventLog, websocket, flows, settings, - ui + ui, + msgQueue, }) - -export default rootReducer diff --git a/web/src/js/ducks/msgQueue.js b/web/src/js/ducks/msgQueue.js new file mode 100644 index 00000000..6d82f4c2 --- /dev/null +++ b/web/src/js/ducks/msgQueue.js @@ -0,0 +1,113 @@ +import { fetchApi } from '../utils' +import * as websocketActions from './websocket' +import * as eventLogActions from './eventLog' +import * as flowsActions from './flows' +import * as settingsActions from './settings' + +export const INIT = 'MSG_QUEUE_INIT' +export const ENQUEUE = 'MSG_QUEUE_ENQUEUE' +export const CLEAR = 'MSG_QUEUE_CLEAR' +export const FETCH_ERROR = 'MSG_QUEUE_FETCH_ERROR' + +const handlers = { + [eventLogActions.MSG_TYPE] : eventLogActions, + [flowsActions.MSG_TYPE] : flowsActions, + [settingsActions.MSG_TYPE] : settingsActions, +} + +const defaultState = {} + +export default function reduce(state = defaultState, action) { + switch (action.type) { + + case INIT: + return { + ...state, + [action.queue]: [], + } + + case ENQUEUE: + return { + ...state, + [action.queue]: [...state[action.queue], action.msg], + } + + case CLEAR: + return { + ...state, + [action.queue]: null, + } + + default: + return state + } +} + +/** + * @public websocket + */ +export function handleWsMsg(msg) { + return (dispatch, getState) => { + const handler = handlers[msg.type] + if (msg.cmd === websocketActions.CMD_RESET) { + return dispatch(fetchData(handler.MSG_TYPE)) + } + if (getState().msgQueue[handler.MSG_TYPE]) { + return dispatch({ type: ENQUEUE, queue: handler.MSG_TYPE, msg }) + } + return dispatch(handler.handleWsMsg(msg)) + } +} + +/** + * @public + */ +export function fetchData(type) { + return dispatch => { + const handler = handlers[type] + + dispatch(init(handler.MSG_TYPE)) + + fetchApi(handler.DATA_URL) + .then(res => res.json()) + .then(json => dispatch(receive(type, json))) + .catch(error => dispatch(fetchError(type, error))) + } +} + +/** + * @private + */ +export function receive(type, res) { + return (dispatch, getState) => { + const handler = handlers[type] + const queue = getState().msgQueue[handler.MSG_TYPE] || [] + + dispatch(clear(handler.MSG_TYPE)) + dispatch(handler.receiveData(res.data)) + for (const msg of queue) { + dispatch(handler.handleWsMsg(msg)) + } + } +} + +/** + * @private + */ +export function init(queue) { + return { type: INIT, queue } +} + +/** + * @private + */ +export function clear(queue) { + return { type: CLEAR, queue } +} + +/** + * @private + */ +export function fetchError(type, error) { + return { type: FETCH_ERROR, type, error } +} diff --git a/web/src/js/ducks/settings.js b/web/src/js/ducks/settings.js index bef7c0ff..c5f0a90b 100644 --- a/web/src/js/ducks/settings.js +++ b/web/src/js/ducks/settings.js @@ -1,45 +1,31 @@ -import {fetchApi} from '../utils'; +import { fetchApi } from '../utils' +import * as msgQueueActions from './msgQueue' -export const REQUEST_SETTINGS = 'REQUEST_SETTINGS' -export const RECEIVE_SETTINGS = 'RECEIVE_SETTINGS' -export const UPDATE_SETTINGS = 'UPDATE_SETTINGS' +export const MSG_TYPE = 'UPDATE_SETTINGS' +export const DATA_URL = '/settings' + +export const RECEIVE = 'RECEIVE' +export const UPDATE = 'UPDATE' +export const REQUEST_UPDATE = 'REQUEST_UPDATE' +export const UNKNOWN_CMD = 'SETTINGS_UNKNOWN_CMD' const defaultState = { settings: {}, - isFetching: false, - actionsDuringFetch: [], } export default function reducer(state = defaultState, action) { switch (action.type) { - case REQUEST_SETTINGS: + case RECEIVE: return { ...state, - isFetching: true - } - - case RECEIVE_SETTINGS: - let s = { settings: action.settings, - isFetching: false, - actionsDuringFetch: [], } - for (action of state.actionsDuringFetch) { - s = reducer(s, action) - } - return s - case UPDATE_SETTINGS: - if (state.isFetching) { - return { - ...state, - actionsDuringFetch: [...state.actionsDuringFetch, action] - } - } + case UPDATE: return { ...state, - settings: {...state.settings, ...action.settings} + settings: { ...state.settings, ...action.settings }, } default: @@ -47,31 +33,39 @@ export default function reducer(state = defaultState, action) { } } -export function handleWsMsg(event) { - /* This action creator takes all WebSocket events */ - if (event.cmd === 'update') { - return { - type: UPDATE_SETTINGS, - settings: event.data - } - } - console.error('unknown settings update', event) -} +/** + * @public msgQueue + */ +export function handleWsMsg(msg) { + switch (msg.cmd) { -export function fetchSettings() { - return dispatch => { - dispatch({type: REQUEST_SETTINGS}) + case websocketActions.CMD_UPDATE: + return { type: UPDATE, settings: msg.data } - return fetchApi('/settings') - .then(response => response.json()) - .then(json => - dispatch({type: RECEIVE_SETTINGS, settings: json.data}) - ) - // TODO: Error handling + default: + console.error('unknown settings update', msg) + return { type: UNKNOWN_CMD, msg } } } +/** + * @public + */ export function updateSettings(settings) { fetchApi.put('/settings', settings) - return { type: SET_INTERCEPT } + return { type: REQUEST_UPDATE } +} + +/** + * @public websocket + */ +export function fetchData() { + return msgQueueActions.fetchData(MSG_TYPE) +} + +/** + * @public msgQueue + */ +export function receiveData(settings) { + return { type: RECEIVE, settings } } diff --git a/web/src/js/ducks/utils/list.js b/web/src/js/ducks/utils/list.js index e66a8549..a93b2d45 100644 --- a/web/src/js/ducks/utils/list.js +++ b/web/src/js/ducks/utils/list.js @@ -1,54 +1,74 @@ import _ from 'lodash' -export const SET = 'LIST_SET' -export const CLEAR = 'LIST_CLEAR' -export const REQUEST = 'LIST_REQUEST' +export const ADD = 'LIST_ADD' +export const UPDATE = 'LIST_UPDATE' +export const REMOVE = 'LIST_REMOVE' export const RECEIVE = 'LIST_RECEIVE' const defaultState = { - data: {}, - pendingActions: null, + data: [], + byId: {}, + indexOf: {}, } export default function reduce(state = defaultState, action) { switch (action.type) { - case SET: - if (state.pendingActions) { - return { - ...state, - pendingActions: [...state.pendingActions, action] - } - } + case ADD: return { ...state, - data: { ...state.data, [action.id]: null, [action.item.id]: action.item } + data: [...state.data, action.item], + byId: { ...state.byId, [action.item.id]: action.item }, + indexOf: { ...state.indexOf, [action.item.id]: state.data.length }, } - case CLEAR: - if (state.pendingActions) { - return { - ...state, - pendingActions: [...state.pendingActions, action] - } + case UPDATE: { + const data = [...state.data] + const index = state.indexOf[action.id] + + if (index == null) { + throw new Error('Item not found') } + + data[index] = action.item + return { ...state, - data: { ...state.data, [action.id]: null } + data, + byId: { ...state.byId, [action.id]: null, [action.item.id]: action.item }, + indexOf: { ...state.indexOf, [action.id]: null, [action.item.id]: index }, + } + } + + case REMOVE: { + const data = [...state.data] + const indexOf = { ...state.indexOf } + const index = indexOf[action.id] + + if (index == null) { + throw new Error('Item not found') + } + + data.splice(index, 1) + for (let i = data.length - 1; i >= index; i--) { + indexOf[data[i].id] = i } - case REQUEST: return { ...state, - pendingActions: [] + data, + indexOf, + byId: { ...state.byId, [action.id]: null }, } + } case RECEIVE: - return state.pendingActions.reduce(reduce, { + return { ...state, - pendingActions: null, - data: _.fromPairs(action.list.map(item => [item.id, item])), - }) + data: action.list, + byId: _.fromPairs(action.list.map(item => [item.id, item])), + indexOf: _.fromPairs(action.list.map((item, index) => [item.id, index])), + } default: return state @@ -59,28 +79,21 @@ export default function reduce(state = defaultState, action) { * @public */ export function add(item) { - return { type: SET, id: item.id, item } + return { type: ADD, item } } /** * @public */ export function update(id, item) { - return { type: SET, id, item } + return { type: UPDATE, id, item } } /** * @public */ export function remove(id) { - return { type: CLEAR, id } -} - -/** - * @public - */ -export function request() { - return { type: REQUEST } + return { type: REMOVE, id } } /** diff --git a/web/src/js/ducks/utils/view.js b/web/src/js/ducks/utils/view.js index 3b552378..87f9bd2a 100755 --- a/web/src/js/ducks/utils/view.js +++ b/web/src/js/ducks/utils/view.js @@ -16,7 +16,7 @@ export default function reduce(state = defaultState, action) { switch (action.type) { case UPDATE_FILTER: { - const data = _.values(action.list.data).filter(action.filter).sort(action.sorter) + const data = action.list.data.filter(action.filter).sort(action.sorter) return { ...state, data, @@ -69,7 +69,7 @@ export default function reduce(state = defaultState, action) { } case RECEIVE: { - const data = _.values(action.list.data).filter(action.filter).sort(action.sorter) + const data = action.list.data.filter(action.filter).sort(action.sorter) return { ...state, data, @@ -138,7 +138,7 @@ function sortedIndex(list, item, sorter) { while (low < high) { const middle = (low + high) >>> 1 - if (sorter(item, list[middle]) > 0) { + if (sorter(item, list[middle]) >= 0) { low = middle + 1 } else { high = middle diff --git a/web/src/js/ducks/websocket.js b/web/src/js/ducks/websocket.js index c79d887a..aa0d7f7d 100644 --- a/web/src/js/ducks/websocket.js +++ b/web/src/js/ducks/websocket.js @@ -1,5 +1,7 @@ import { ConnectionActions } from '../actions.js' import { AppDispatcher } from '../dispatcher.js' + +import * as msgQueueActions from './msgQueue' import * as eventLogActions from './eventLog' import * as flowsActions from './flows' import * as settingsActions from './settings' @@ -45,17 +47,12 @@ export function connect() { return dispatch => { const socket = new WebSocket(location.origin.replace('http', 'ws') + '/updates') - // @todo remove this - window.ws = socket - socket.addEventListener('open', () => dispatch(onConnect())) socket.addEventListener('close', () => dispatch(onDisconnect())) - socket.addEventListener('message', msg => dispatch(onMessage(msg))) + socket.addEventListener('message', msg => dispatch(onMessage(JSON.parse(msg.data)))) socket.addEventListener('error', error => dispatch(onError(error))) dispatch({ type: CONNECT, socket }) - - return socket } } @@ -70,39 +67,18 @@ export function onConnect() { // workaround to make sure that our state is already available. return dispatch => { dispatch({ type: CONNECTED }) - dispatch(settingsActions.fetchSettings()) - dispatch(flowsActions.fetchFlows()).then(() => ConnectionActions.open()) + dispatch(settingsActions.fetchData()) + dispatch(flowsActions.fetchData()) + dispatch(eventLogActions.fetchData()) } } export function onMessage(msg) { - return dispatch => { - const data = JSON.parse(msg.data) - - AppDispatcher.dispatchServerAction(data) - - switch (data.type) { - - case eventLogActions.WS_MSG_TYPE: - return dispatch(eventLogActions.handleWsMsg(data)) - - case flowsActions.WS_MSG_TYPE: - return dispatch(flowsActions.handleWsMsg(data)) - - case settingsActions.UPDATE_SETTINGS: - return dispatch(settingsActions.handleWsMsg(data)) - - default: - console.warn('unknown message', data) - } - - dispatch({ type: MESSAGE, msg }) - } + return msgQueueActions.handleWsMsg(msg) } export function onDisconnect() { return dispatch => { - ConnectionActions.close() dispatch(eventLogActions.addLogEntry('WebSocket connection closed.')) dispatch({ type: DISCONNECTED }) } @@ -111,7 +87,6 @@ export function onDisconnect() { export function onError(error) { // @todo let event log subscribe WebSocketActions.ERROR return dispatch => { - ConnectionActions.error() dispatch(eventLogActions.addLogEntry('WebSocket connection error.')) dispatch({ type: ERROR, error }) } -- cgit v1.2.3