diff options
Diffstat (limited to 'web/src/js/components/FlowView')
-rw-r--r-- | web/src/js/components/FlowView/Headers.jsx | 71 | ||||
-rw-r--r-- | web/src/js/components/FlowView/Messages.jsx | 210 | ||||
-rw-r--r-- | web/src/js/components/FlowView/ToggleEdit.jsx | 38 |
3 files changed, 198 insertions, 121 deletions
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 9295f97c..133b2883 100644 --- a/web/src/js/components/FlowView/Messages.jsx +++ b/web/src/js/components/FlowView/Messages.jsx @@ -1,130 +1,146 @@ import React, { Component, PropTypes } from 'react' -import _ from 'lodash' +import { connect } from 'react-redux' -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' -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 /> - <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 /> - <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} + /> + + <ValidateEditor + content={flow.response.status_code + ''} + readonly={readonly} + onDone={code => updateFlow({ response: { code: parseInt(code) } })} + isValid={code => /^\d+$/.test(code)} + /> + + <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 - /> - - <ValueEditor - ref="code" - content={flow.response.status_code + ''} - onDone={code => updateFlow({ response: { code: parseInt(code) } })} - isValid={code => /^\d+$/.test(code)} - inline - /> - - <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 + const { flow, isEdit, updateFlow } = this.props return ( <section className="request"> - <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} 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 + const { flow, isEdit, updateFlow } = this.props return ( <section className="response"> - <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/> @@ -134,25 +150,31 @@ export class Response extends Component { } 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) |