1import React, { Component } from 'react'
2import PropTypes from 'prop-types'
3import { connect } from 'react-redux'
4
5
6import { RequestUtils, isValidHttpVersion, parseUrl } from '../../flow/utils.js'
7import { formatTimeStamp } from '../../utils.js'
8import ContentView from '../ContentView'
9import ContentViewOptions from '../ContentView/ContentViewOptions'
10import ValidateEditor from '../ValueEditor/ValidateEditor'
11import ValueEditor from '../ValueEditor/ValueEditor'
12import HideInStatic from '../common/HideInStatic'
13
14import Headers from './Headers'
15import { startEdit, updateEdit } from '../../ducks/ui/flow'
16import * as FlowActions from '../../ducks/flows'
17import ToggleEdit from './ToggleEdit'
18
19function RequestLine({ flow, readonly, updateFlow }) {
20    return (
21        <div className="first-line request-line">
22            <div>
23                <ValueEditor
24                    content={flow.request.method}
25                    readonly={readonly}
26                    onDone={method => updateFlow({ request: { method } })}
27                />
28                &nbsp;
29                <ValidateEditor
30                    content={RequestUtils.pretty_url(flow.request)}
31                    readonly={readonly}
32                    onDone={url => updateFlow({ request: {path: '', ...parseUrl(url)}})}
33                    isValid={url => !!parseUrl(url).host}
34                />
35                &nbsp;
36                <ValidateEditor
37                    content={flow.request.http_version}
38                    readonly={readonly}
39                    onDone={http_version => updateFlow({ request: { http_version } })}
40                    isValid={isValidHttpVersion}
41                />
42            </div>
43        </div>
44    )
45}
46
47function ResponseLine({ flow, readonly, updateFlow }) {
48    return (
49        <div className="first-line response-line">
50            <ValidateEditor
51                content={flow.response.http_version}
52                readonly={readonly}
53                onDone={nextVer => updateFlow({ response: { http_version: nextVer } })}
54                isValid={isValidHttpVersion}
55            />
56            &nbsp;
57            <ValidateEditor
58                content={flow.response.status_code + ''}
59                readonly={readonly}
60                onDone={code => updateFlow({ response: { code: parseInt(code) } })}
61                isValid={code => /^\d+$/.test(code)}
62            />
63            &nbsp;
64            <ValueEditor
65                content={flow.response.reason}
66                readonly={readonly}
67                onDone={msg => updateFlow({ response: { msg } })}
68            />
69        </div>
70    )
71}
72
73const Message = connect(
74    state => ({
75        flow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]],
76        isEdit: !!state.ui.flow.modifiedFlow,
77    }),
78    {
79        updateFlow: updateEdit,
80        uploadContent: FlowActions.uploadContent
81    }
82)
83
84export class Request extends Component {
85    render() {
86        const { flow, isEdit, updateFlow, uploadContent } = this.props
87        let noContent =  !isEdit && (flow.request.contentLength == 0 || flow.request.contentLength == null)
88        return (
89            <section className="request">
90                <article>
91                    <ToggleEdit/>
92                    <RequestLine
93                        flow={flow}
94                        readonly={!isEdit}
95                        updateFlow={updateFlow}/>
96                    <Headers
97                        message={flow.request}
98                        readonly={!isEdit}
99                        onChange={headers => updateFlow({ request: { headers } })}
100                    />
101
102                    <hr/>
103                    <ContentView
104                        readonly={!isEdit}
105                        flow={flow}
106                        onContentChange={content => updateFlow({ request: {content}})}
107                        message={flow.request}/>
108
109                    <hr/>
110                    <Headers
111                        message={flow.request}
112                        readonly={!isEdit}
113                        onChange={trailers => updateFlow({ request: { trailers } })}
114                        type='trailers'
115                    />
116                </article>
117                <HideInStatic>
118                {!noContent &&
119                    <footer>
120                        <ContentViewOptions
121                            flow={flow}
122                            readonly={!isEdit}
123                            message={flow.request}
124                            uploadContent={content => uploadContent(flow, content, "request")}/>
125                    </footer>
126                }
127                </HideInStatic>
128            </section>
129        )
130    }
131}
132
133Request = Message(Request)
134
135
136export class Response extends Component {
137    render() {
138        const { flow, isEdit, updateFlow, uploadContent } = this.props
139        let noContent =  !isEdit && (flow.response.contentLength == 0 || flow.response.contentLength == null)
140
141        return (
142            <section className="response">
143                <article>
144                    <ToggleEdit/>
145                    <ResponseLine
146                        flow={flow}
147                        readonly={!isEdit}
148                        updateFlow={updateFlow}/>
149                    <Headers
150                        message={flow.response}
151                        readonly={!isEdit}
152                        onChange={headers => updateFlow({ response: { headers } })}
153                    />
154                    <hr/>
155                    <ContentView
156                        readonly={!isEdit}
157                        flow={flow}
158                        onContentChange={content => updateFlow({ response: {content}})}
159                        message={flow.response}
160                    />
161                    <hr/>
162                    <Headers
163                        message={flow.response}
164                        readonly={!isEdit}
165                        onChange={trailers => updateFlow({ response: { trailers } })}
166                        type='trailers'
167                    />
168                </article>
169                <HideInStatic>
170                {!noContent &&
171                    <footer >
172                        <ContentViewOptions
173                            flow={flow}
174                            message={flow.response}
175                            uploadContent={content => uploadContent(flow, content, "response")}
176                            readonly={!isEdit}/>
177                    </footer>
178                }
179                </HideInStatic>
180            </section>
181        )
182    }
183}
184
185Response = Message(Response)
186
187
188ErrorView.propTypes = {
189    flow: PropTypes.object.isRequired,
190}
191
192export function ErrorView({ flow }) {
193    return (
194        <section className="error">
195            <div className="alert alert-warning">
196                {flow.error.msg}
197                <div>
198                    <small>{formatTimeStamp(flow.error.timestamp)}</small>
199                </div>
200            </div>
201        </section>
202    )
203}
204