diff options
author | Maximilian Hils <git@maximilianhils.com> | 2015-03-30 03:49:50 +0200 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2015-03-30 03:49:50 +0200 |
commit | 6d29f93e9eaaabe20c0d46887048f2367bfbb3cf (patch) | |
tree | 0b3be8ff99d7b986596ca69e67b3e7fe885d4764 /web/src/js/components/flowview | |
parent | 737002921e9aed701afb49fda8777e8c9286bf09 (diff) | |
download | mitmproxy-6d29f93e9eaaabe20c0d46887048f2367bfbb3cf.tar.gz mitmproxy-6d29f93e9eaaabe20c0d46887048f2367bfbb3cf.tar.bz2 mitmproxy-6d29f93e9eaaabe20c0d46887048f2367bfbb3cf.zip |
web: add prompt for keyboard navigation
Diffstat (limited to 'web/src/js/components/flowview')
-rw-r--r-- | web/src/js/components/flowview/index.js | 59 | ||||
-rw-r--r-- | web/src/js/components/flowview/messages.js | 74 |
2 files changed, 115 insertions, 18 deletions
diff --git a/web/src/js/components/flowview/index.js b/web/src/js/components/flowview/index.js index 4214714e..739a46dc 100644 --- a/web/src/js/components/flowview/index.js +++ b/web/src/js/components/flowview/index.js @@ -5,6 +5,8 @@ var common = require("../common.js"); var Nav = require("./nav.js"); var Messages = require("./messages.js"); var Details = require("./details.js"); +var Prompt = require("../prompt.js"); + var allTabs = { request: Messages.Request, @@ -15,6 +17,11 @@ var allTabs = { var FlowView = React.createClass({ mixins: [common.StickyHeadMixin, common.Navigation, common.RouterState], + getInitialState: function () { + return { + prompt: false + }; + }, getTabs: function (flow) { var tabs = []; ["request", "response", "error"].forEach(function (e) { @@ -27,7 +34,7 @@ var FlowView = React.createClass({ }, nextTab: function (i) { var tabs = this.getTabs(this.props.flow); - var currentIndex = tabs.indexOf(this.getParams().detailTab); + var currentIndex = tabs.indexOf(this.getActive()); // JS modulo operator doesn't correct negative numbers, make sure that we are positive. var nextIndex = (currentIndex + i + tabs.length) % tabs.length; this.selectTab(tabs[nextIndex]); @@ -41,10 +48,50 @@ var FlowView = React.createClass({ } ); }, + getActive: function(){ + return this.getParams().detailTab; + }, + promptEdit: function () { + var options; + switch(this.getActive()){ + case "request": + options = [ + "method", + "url", + {text:"http version", key:"v"}, + "header" + /*, "content"*/]; + break; + case "response": + options = [ + {text:"http version", key:"v"}, + "code", + "message", + "header" + /*, "content"*/]; + break; + case "details": + return; + default: + throw "Unknown tab for edit: " + this.getActive(); + } + + this.setState({ + prompt: { + done: function (k) { + this.setState({prompt: false}); + if(k){ + this.refs.tab.edit(k); + } + }.bind(this), + options: options + } + }); + }, render: function () { var flow = this.props.flow; var tabs = this.getTabs(flow); - var active = this.getParams().detailTab; + var active = this.getActive(); if (!_.contains(tabs, active)) { if (active === "response" && flow.error) { @@ -57,6 +104,11 @@ var FlowView = React.createClass({ this.selectTab(active); } + var prompt = null; + if (this.state.prompt) { + prompt = <Prompt {...this.state.prompt}/>; + } + var Tab = allTabs[active]; return ( <div className="flow-detail" onScroll={this.adjustHead}> @@ -65,7 +117,8 @@ var FlowView = React.createClass({ tabs={tabs} active={active} selectTab={this.selectTab}/> - <Tab flow={flow}/> + <Tab ref="tab" flow={flow}/> + {prompt} </div> ); } diff --git a/web/src/js/components/flowview/messages.js b/web/src/js/components/flowview/messages.js index 7feaa634..cb166026 100644 --- a/web/src/js/components/flowview/messages.js +++ b/web/src/js/components/flowview/messages.js @@ -23,13 +23,16 @@ var Headers = React.createClass({ } else { nextHeaders.splice(row, 1); // manually move selection target if this has been the last row. - if(row === nextHeaders.length){ - this._nextSel = (row-1)+"-value"; + if (row === nextHeaders.length) { + this._nextSel = (row - 1) + "-value"; } } } this.props.onChange(nextHeaders); }, + edit: function () { + this.refs["0-key"].focus(); + }, onTab: function (row, col, e) { var headers = this.props.message.headers; if (row === headers.length - 1 && col === 1) { @@ -138,9 +141,11 @@ var InlineInput = React.createClass({ }, blur: function () { this.getDOMNode().blur(); + window.getSelection().removeAllRanges(); this.context.returnFocus && this.context.returnFocus(); }, - selectContents: function () { + focus: function () { + React.findDOMNode(this).focus(); var range = document.createRange(); range.selectNodeContents(this.getDOMNode()); var sel = window.getSelection(); @@ -148,7 +153,7 @@ var InlineInput = React.createClass({ sel.addRange(range); }, onFocus: function () { - this.setState({editable: true}, this.selectContents); + this.setState({editable: true}, this.focus); }, onBlur: function (e) { this.setState({editable: false}); @@ -182,7 +187,7 @@ var HeaderInlineInput = React.createClass({ } break; case utils.Key.TAB: - if(!e.shiftKey){ + if (!e.shiftKey) { this.props.onTab(e); } break; @@ -202,6 +207,9 @@ var ValidateInlineInput = React.createClass({ originalContent: this.props.content }; }, + focus: function () { + this.getDOMNode().focus(); + }, onChange: function (val) { this.setState({ content: val @@ -253,11 +261,11 @@ var RequestLine = React.createClass({ var httpver = "HTTP/" + flow.request.httpversion.join("."); return <div className="first-line request-line"> - <InlineInput content={flow.request.method} onChange={this.onMethodChange}/> + <InlineInput ref="method" content={flow.request.method} onChange={this.onMethodChange}/> - <ValidateInlineInput content={url} onChange={this.onUrlChange} isValid={this.isValidUrl} /> + <ValidateInlineInput ref="url" content={url} onChange={this.onUrlChange} isValid={this.isValidUrl} /> - <ValidateInlineInput immediate content={httpver} onChange={this.onHttpVersionChange} isValid={flowutils.isValidHttpVersion} /> + <ValidateInlineInput ref="httpVersion" immediate content={httpver} onChange={this.onHttpVersionChange} isValid={flowutils.isValidHttpVersion} /> </div> }, isValidUrl: function (url) { @@ -292,11 +300,11 @@ var ResponseLine = React.createClass({ var flow = this.props.flow; var httpver = "HTTP/" + flow.response.httpversion.join("."); return <div className="first-line response-line"> - <ValidateInlineInput immediate content={httpver} onChange={this.onHttpVersionChange} isValid={flowutils.isValidHttpVersion} /> + <ValidateInlineInput ref="httpVersion" immediate content={httpver} onChange={this.onHttpVersionChange} isValid={flowutils.isValidHttpVersion} /> - <ValidateInlineInput immediate content={flow.response.code + ""} onChange={this.onCodeChange} isValid={this.isValidCode} /> + <ValidateInlineInput ref="code" immediate content={flow.response.code + ""} onChange={this.onCodeChange} isValid={this.isValidCode} /> - <InlineInput content={flow.response.msg} onChange={this.onMsgChange}/> + <InlineInput ref="msg" content={flow.response.msg} onChange={this.onMsgChange}/> </div>; }, @@ -330,14 +338,32 @@ var Request = React.createClass({ var flow = this.props.flow; return ( <section className="request"> - <RequestLine flow={flow}/> + <RequestLine ref="requestLine" flow={flow}/> {/*<ResponseLine flow={flow}/>*/} - <Headers message={flow.request} onChange={this.onHeaderChange}/> + <Headers ref="headers" message={flow.request} onChange={this.onHeaderChange}/> <hr/> <ContentView flow={flow} message={flow.request}/> </section> ); }, + edit: function (k) { + switch (k) { + case "m": + this.refs.requestLine.refs.method.focus(); + break; + case "u": + this.refs.requestLine.refs.url.focus(); + break; + case "v": + this.refs.requestLine.refs.httpVersion.focus(); + break; + case "h": + this.refs.headers.edit(); + break; + default: + throw "Unimplemented: "+ k; + } + }, onHeaderChange: function (nextHeaders) { actions.FlowActions.update(this.props.flow, { request: { @@ -353,13 +379,31 @@ var Response = React.createClass({ return ( <section className="response"> {/*<RequestLine flow={flow}/>*/} - <ResponseLine flow={flow}/> - <Headers message={flow.response} onChange={this.onHeaderChange}/> + <ResponseLine ref="responseLine" flow={flow}/> + <Headers ref="headers" message={flow.response} onChange={this.onHeaderChange}/> <hr/> <ContentView flow={flow} message={flow.response}/> </section> ); }, + edit: function (k) { + switch (k) { + case "c": + this.refs.responseLine.refs.code.focus(); + break; + case "m": + this.refs.responseLine.refs.msg.focus(); + break; + case "v": + this.refs.responseLine.refs.httpVersion.focus(); + break; + case "h": + this.refs.headers.edit(); + break; + default: + throw "Unimplemented: "+ k; + } + }, onHeaderChange: function (nextHeaders) { actions.FlowActions.update(this.props.flow, { response: { |