aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/components/FlowView
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2016-07-21 01:14:55 -0700
committerMaximilian Hils <git@maximilianhils.com>2016-07-21 01:14:55 -0700
commit8a3a21bba1e6706295cc22e1b3a876a7a86cb705 (patch)
tree9408324d45850fd4def75c60cf3537a12f632217 /web/src/js/components/FlowView
parent427fffbcb82ba16dd65a4fee4000a05215e859b8 (diff)
downloadmitmproxy-8a3a21bba1e6706295cc22e1b3a876a7a86cb705.tar.gz
mitmproxy-8a3a21bba1e6706295cc22e1b3a876a7a86cb705.tar.bz2
mitmproxy-8a3a21bba1e6706295cc22e1b3a876a7a86cb705.zip
web: fix ValueEditor, clean up code
Diffstat (limited to 'web/src/js/components/FlowView')
-rw-r--r--web/src/js/components/FlowView/FlowEditorButton.jsx39
-rw-r--r--web/src/js/components/FlowView/Headers.jsx71
-rw-r--r--web/src/js/components/FlowView/Messages.jsx226
-rw-r--r--web/src/js/components/FlowView/ToggleEdit.jsx38
4 files changed, 199 insertions, 175 deletions
diff --git a/web/src/js/components/FlowView/FlowEditorButton.jsx b/web/src/js/components/FlowView/FlowEditorButton.jsx
deleted file mode 100644
index 3d0d1d16..00000000
--- a/web/src/js/components/FlowView/FlowEditorButton.jsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React, { PropTypes, Component } from 'react'
-import { connect } from 'react-redux'
-
-import {closeFlowEditor} from '../../ducks/ui.js'
-import {openFlowEditor} from '../../ducks/ui.js'
-
-FlowEditorButton.propTypes = {
- isFlowEditorOpen: PropTypes.bool.isRequired,
- content: PropTypes.string.isRequired,
- onContentChange: PropTypes.func.isRequired
-}
-
-function FlowEditorButton ({ isFlowEditorOpen, closeFlowEditor, openFlowEditor, onContentChange, content }) {
- return (
- <div className="edit-flow-container">
- {isFlowEditorOpen ?
- <a className="edit-flow" onClick={() => {onContentChange(content); closeFlowEditor()}}>
- <i className="fa fa-check"/>
- </a>
- :
- <a className="edit-flow" onClick={() => openFlowEditor()}>
- <i className="fa fa-pencil"/>
- </a>
- }
- </div>
- )
-}
-
-export default connect(
- state => ({
- isFlowEditorOpen: state.ui.isFlowEditorOpen,
- content: state.ui.modifiedFlow.content
- }),
- {
- closeFlowEditor,
- openFlowEditor
-
- }
-)(FlowEditorButton)
diff --git a/web/src/js/components/FlowView/Headers.jsx b/web/src/js/components/FlowView/Headers.jsx
index 880eeda1..706dd404 100644
--- a/web/src/js/components/FlowView/Headers.jsx
+++ b/web/src/js/components/FlowView/Headers.jsx
@@ -1,12 +1,21 @@
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
-import ValueEditor from '../ValueEditor'
-import { Key } from '../../utils.js'
+import ValueEditor from '../ValueEditor/ValueEditor'
+import { Key } from '../../utils'
class HeaderEditor extends Component {
+ constructor(props) {
+ super(props)
+ this.onKeyDown = this.onKeyDown.bind(this)
+ }
+
render() {
- return <ValueEditor ref="input" {...this.props} onKeyDown={this.onKeyDown} inline/>
+ let { onTab, ...props } = this.props
+ return <ValueEditor
+ {...props}
+ onKeyDown={this.onKeyDown}
+ />
}
focus() {
@@ -21,6 +30,7 @@ class HeaderEditor extends Component {
this.props.onRemove(e)
}
break
+ case Key.ENTER:
case Key.TAB:
if (!e.shiftKey) {
this.props.onTab(e)
@@ -66,7 +76,12 @@ export default class Headers extends Component {
onTab(row, col, e) {
const headers = this.props.message.headers
- if (row !== headers.length - 1 || col !== 1) {
+ if (col === 0) {
+ this._nextSel = `${row}-value`
+ return
+ }
+ if (row !== headers.length - 1) {
+ this._nextSel = `${row + 1}-key`
return
}
@@ -96,33 +111,35 @@ export default class Headers extends Component {
}
render() {
- const { message } = this.props
+ const { message, readonly } = this.props
return (
<table className="header-table">
<tbody>
- {message.headers.map((header, i) => (
- <tr key={i}>
- <td className="header-name">
- <HeaderEditor
- ref={`${i}-key`}
- content={header[0]}
- onDone={val => this.onChange(i, 0, val)}
- onRemove={event => this.onRemove(i, 0, event)}
- onTab={event => this.onTab(i, 0, event)}
- />:
- </td>
- <td className="header-value">
- <HeaderEditor
- ref={`${i}-value`}
- content={header[1]}
- onDone={val => this.onChange(i, 1, val)}
- onRemove={event => this.onRemove(i, 1, event)}
- onTab={event => this.onTab(i, 1, event)}
- />
- </td>
- </tr>
- ))}
+ {message.headers.map((header, i) => (
+ <tr key={i}>
+ <td className="header-name">
+ <HeaderEditor
+ ref={`${i}-key`}
+ content={header[0]}
+ readonly={readonly}
+ onDone={val => this.onChange(i, 0, val)}
+ onRemove={event => this.onRemove(i, 0, event)}
+ onTab={event => this.onTab(i, 0, event)}
+ />:
+ </td>
+ <td className="header-value">
+ <HeaderEditor
+ ref={`${i}-value`}
+ content={header[1]}
+ readonly={readonly}
+ onDone={val => this.onChange(i, 1, val)}
+ onRemove={event => this.onRemove(i, 1, event)}
+ onTab={event => this.onTab(i, 1, event)}
+ />
+ </td>
+ </tr>
+ ))}
</tbody>
</table>
)
diff --git a/web/src/js/components/FlowView/Messages.jsx b/web/src/js/components/FlowView/Messages.jsx
index 2f03c712..133b2883 100644
--- a/web/src/js/components/FlowView/Messages.jsx
+++ b/web/src/js/components/FlowView/Messages.jsx
@@ -1,172 +1,180 @@
import React, { Component, PropTypes } from 'react'
-import _ from 'lodash'
-
-import { RequestUtils, isValidHttpVersion, parseUrl, parseHttpVersion } from '../../flow/utils.js'
-import { Key, formatTimeStamp } from '../../utils.js'
-import ContentView from '../ContentView'
-import ValueEditor from '../ValueEditor'
-import Headers from './Headers'
-import * as flowActions from '../../ducks/flows'
-import FlowEditorButton from './FlowEditorButton'
+import { connect } from 'react-redux'
-class RequestLine extends Component {
+import { RequestUtils, isValidHttpVersion, parseUrl } from '../../flow/utils.js'
+import { formatTimeStamp } from '../../utils.js'
+import ContentView from '../ContentView'
+import ValidateEditor from '../ValueEditor/ValidateEditor'
+import ValueEditor from '../ValueEditor/ValueEditor'
- render() {
- const { flow, updateFlow } = this.props
+import Headers from './Headers'
+import { startEdit, updateEdit } from '../../ducks/ui/flow'
+import ToggleEdit from './ToggleEdit'
- return (
- <div className="first-line request-line">
+function RequestLine({ flow, readonly, updateFlow }) {
+ return (
+ <div className="first-line request-line">
+ <div>
<ValueEditor
- ref="method"
content={flow.request.method}
+ readonly={readonly}
onDone={method => updateFlow({ request: { method } })}
- inline
/>
&nbsp;
- <ValueEditor
- ref="url"
+ <ValidateEditor
content={RequestUtils.pretty_url(flow.request)}
- onDone={url => updateFlow({ request: Object.assign({ path: '' }, parseUrl(url)) })}
+ readonly={readonly}
+ onDone={url => updateFlow({ request: {path: '', ...parseUrl(url)}})}
isValid={url => !!parseUrl(url).host}
- inline
/>
&nbsp;
- <ValueEditor
- ref="httpVersion"
+ <ValidateEditor
content={flow.request.http_version}
- onDone={ver => updateFlow({ request: { http_version: parseHttpVersion(ver) } })}
+ readonly={readonly}
+ onDone={http_version => updateFlow({ request: { http_version } })}
isValid={isValidHttpVersion}
- inline
/>
</div>
- )
- }
+ </div>
+ )
}
-class ResponseLine extends Component {
-
- render() {
- const { flow, updateFlow } = this.props
+function ResponseLine({ flow, readonly, updateFlow }) {
+ return (
+ <div className="first-line response-line">
+ <ValidateEditor
+ content={flow.response.http_version}
+ readonly={readonly}
+ onDone={nextVer => updateFlow({ response: { http_version: nextVer } })}
+ isValid={isValidHttpVersion}
+ />
+ &nbsp;
+ <ValidateEditor
+ content={flow.response.status_code + ''}
+ readonly={readonly}
+ onDone={code => updateFlow({ response: { code: parseInt(code) } })}
+ isValid={code => /^\d+$/.test(code)}
+ />
+ &nbsp;
+ <ValueEditor
+ content={flow.response.reason}
+ readonly={readonly}
+ onDone={msg => updateFlow({ response: { msg } })}
+ />
+ </div>
+ )
+}
- return (
- <div className="first-line response-line">
- <ValueEditor
- ref="httpVersion"
- content={flow.response.http_version}
- onDone={nextVer => updateFlow({ response: { http_version: parseHttpVersion(nextVer) } })}
- isValid={isValidHttpVersion}
- inline
- />
- &nbsp;
- <ValueEditor
- ref="code"
- content={flow.response.status_code + ''}
- onDone={code => updateFlow({ response: { code: parseInt(code) } })}
- isValid={code => /^\d+$/.test(code)}
- inline
- />
- &nbsp;
- <ValueEditor
- ref="msg"
- content={flow.response.reason}
- onDone={msg => updateFlow({ response: { msg } })}
- inline
- />
- </div>
- )
+const Message = connect(
+ state => ({
+ flow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]],
+ isEdit: !!state.ui.flow.modifiedFlow,
+ }),
+ {
+ updateFlow: updateEdit,
}
-}
+)
export class Request extends Component {
- render() {
- const { flow, updateFlow } = this.props
- let onContentChange = content => flowActions.updateContent(this.props.flow, content, "request")
+ render() {
+ const { flow, isEdit, updateFlow } = this.props
return (
<section className="request">
- <FlowEditorButton onContentChange={onContentChange}/>
- <RequestLine ref="requestLine" flow={flow} updateFlow={updateFlow} />
+ <ToggleEdit/>
+ <RequestLine
+ flow={flow}
+ readonly={!isEdit}
+ updateFlow={updateFlow}/>
<Headers
- ref="headers"
message={flow.request}
+ readonly={!isEdit}
onChange={headers => updateFlow({ request: { headers } })}
/>
<hr/>
- <ContentView flow={flow}
- onContentChange={onContentChange}
- message={flow.request}
- />
+ <ContentView flow={flow} message={flow.request}/>
</section>
)
}
+
edit(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 new Error(`Unimplemented: ${k}`)
- }
+ throw "unimplemented"
+ /*
+ 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 new Error(`Unimplemented: ${k}`)
+ }
+ */
}
+
}
-export class Response extends Component {
+Request = Message(Request)
+export class Response extends Component {
render() {
- const { flow, updateFlow } = this.props
- let onContentChange = content => flowActions.updateContent(this.props.flow, content, "response")
+ const { flow, isEdit, updateFlow } = this.props
return (
<section className="response">
- <FlowEditorButton onContentChange={onContentChange}/>
- <ResponseLine ref="responseLine" flow={flow} updateFlow={updateFlow} />
+ <ToggleEdit/>
+ <ResponseLine
+ flow={flow}
+ readonly={!isEdit}
+ updateFlow={updateFlow}/>
<Headers
- ref="headers"
message={flow.response}
+ readonly={!isEdit}
onChange={headers => updateFlow({ response: { headers } })}
/>
<hr/>
- <ContentView flow={flow}
- onContentChange={onContentChange}
- message={flow.response}
- />
+ <ContentView flow={flow} message={flow.response}/>
</section>
)
}
edit(k) {
- switch (k) {
- case 'c':
- this.refs.responseLine.refs.status_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 new Error(`'Unimplemented: ${k}`)
- }
+ throw "unimplemented"
+ /*
+ switch (k) {
+ case 'c':
+ this.refs.responseLine.refs.status_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 new Error(`'Unimplemented: ${k}`)
+ }
+ */
}
}
+Response = Message(Response)
+
+
ErrorView.propTypes = {
flow: PropTypes.object.isRequired,
}
diff --git a/web/src/js/components/FlowView/ToggleEdit.jsx b/web/src/js/components/FlowView/ToggleEdit.jsx
new file mode 100644
index 00000000..0c8cbbd8
--- /dev/null
+++ b/web/src/js/components/FlowView/ToggleEdit.jsx
@@ -0,0 +1,38 @@
+import React, { PropTypes, Component } from 'react'
+import { connect } from 'react-redux'
+
+import { startEdit, stopEdit } from '../../ducks/ui/flow'
+
+ToggleEdit.propTypes = {
+ isEdit: PropTypes.bool.isRequired,
+ flow: PropTypes.object.isRequired,
+ startEdit: PropTypes.func.isRequired,
+ stopEdit: PropTypes.func.isRequired,
+}
+
+function ToggleEdit({ isEdit, startEdit, stopEdit, flow }) {
+ return (
+ <div className="edit-flow-container">
+ {isEdit ?
+ <a className="edit-flow" onClick={() => stopEdit(flow)}>
+ <i className="fa fa-check"/>
+ </a>
+ :
+ <a className="edit-flow" onClick={() => startEdit(flow)}>
+ <i className="fa fa-pencil"/>
+ </a>
+ }
+ </div>
+ )
+}
+
+export default connect(
+ state => ({
+ isEdit: !!state.ui.flow.modifiedFlow,
+ flow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]]
+ }),
+ {
+ startEdit,
+ stopEdit,
+ }
+)(ToggleEdit)