From 544b1e32389d28df4a40013ea6886f1f9d61e37d Mon Sep 17 00:00:00 2001 From: Clemens Date: Mon, 11 Jul 2016 19:49:58 +0200 Subject: modify flow content --- web/package.json | 5 ++-- web/src/js/app.jsx | 2 +- web/src/js/components/ContentView.jsx | 6 ++-- web/src/js/components/ContentView/ContentViews.jsx | 16 +++++++--- web/src/js/components/FlowView/Messages.jsx | 4 +-- web/src/js/components/common/MonacoEditor.jsx | 34 ++++++++++++++++++++++ 6 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 web/src/js/components/common/MonacoEditor.jsx (limited to 'web') diff --git a/web/package.json b/web/package.json index 55106cb8..1484961d 100644 --- a/web/package.json +++ b/web/package.json @@ -3,7 +3,7 @@ "private": true, "scripts": { "test": "jest", - "build": "gulp prod", + "build": "gulp dev", "start": "gulp" }, "jest": { @@ -28,7 +28,8 @@ "redux": "^3.5.2", "redux-logger": "^2.6.1", "redux-thunk": "^2.1.0", - "shallowequal": "^0.2.2" + "shallowequal": "^0.2.2", + "monaco-editor": "^0.5.1" }, "devDependencies": { "babel-core": "^6.7.7", diff --git a/web/src/js/app.jsx b/web/src/js/app.jsx index bd2d3d58..51b2b639 100644 --- a/web/src/js/app.jsx +++ b/web/src/js/app.jsx @@ -12,7 +12,7 @@ import { add as addLog } from './ducks/eventLog' const middlewares = [thunk]; -if (process.env.NODE_ENV === 'development') { +if (process.env.NODE_ENV === 'development' || true) { const createLogger = require('redux-logger'); middlewares.push(createLogger()); } diff --git a/web/src/js/components/ContentView.jsx b/web/src/js/components/ContentView.jsx index 1533684e..f6dbe90a 100644 --- a/web/src/js/components/ContentView.jsx +++ b/web/src/js/components/ContentView.jsx @@ -59,11 +59,11 @@ export default class ContentView extends Component { return (
{View.textView ? ( - - + + ) : ( - + )}
diff --git a/web/src/js/components/ContentView/ContentViews.jsx b/web/src/js/components/ContentView/ContentViews.jsx index b0297dcc..e5a864bf 100644 --- a/web/src/js/components/ContentView/ContentViews.jsx +++ b/web/src/js/components/ContentView/ContentViews.jsx @@ -1,6 +1,8 @@ import React, { PropTypes } from 'react' import ContentLoader from './ContentLoader' import { MessageUtils } from '../../flow/utils.js' +import Button from '../common/Button' + const views = [ViewAuto, ViewImage, ViewJSON, ViewRaw] @@ -22,13 +24,19 @@ export function ViewImage({ flow, message }) { ViewRaw.textView = true ViewRaw.matches = () => true +ViewRaw.input = {} ViewRaw.propTypes = { content: React.PropTypes.string.isRequired, } -export function ViewRaw({ content }) { - return
{content}
+export function ViewRaw({ content, onChange }) { + return ( +
+ +
+ ) } ViewJSON.textView = true @@ -58,10 +66,10 @@ ViewAuto.propTypes = { flow: React.PropTypes.object.isRequired, } -export function ViewAuto({ message, flow }) { +export function ViewAuto({ message, flow, onChange }) { const View = ViewAuto.findView(message) if (View.textView) { - return + return } else { return } diff --git a/web/src/js/components/FlowView/Messages.jsx b/web/src/js/components/FlowView/Messages.jsx index 9295f97c..d2c42a54 100644 --- a/web/src/js/components/FlowView/Messages.jsx +++ b/web/src/js/components/FlowView/Messages.jsx @@ -89,7 +89,7 @@ export class Request extends Component { onChange={headers => updateFlow({ request: { headers } })} />
- + updateFlow({request: {content} })}/> ) } @@ -128,7 +128,7 @@ export class Response extends Component { onChange={headers => updateFlow({ response: { headers } })} />
- + updateFlow({response: {content} }) }/> ) } diff --git a/web/src/js/components/common/MonacoEditor.jsx b/web/src/js/components/common/MonacoEditor.jsx new file mode 100644 index 00000000..a0e8d58c --- /dev/null +++ b/web/src/js/components/common/MonacoEditor.jsx @@ -0,0 +1,34 @@ +//not working +import React, { Component, PropTypes } from 'react' + +export default class MonacoEditor extends Component { + + constructor(props) { + super(props) + } + + onLoad(){ + window.MonacoEnvironment = { + getWorkerUrl: function(workerId, label) { + return 'worker-loader-proxy.js'; + } + }; + require.config({ + paths: { + vs: '../release/min/vs' + } + }); + + } + + + render() { + return ( +
this.editor = ref} + style="width:800px;height:600px;border:1px solid grey" + onLoad={this.onLoad()}> +
+ ) + } +} -- cgit v1.2.3 From f84098554a3d50ec02255603bb0a145b3aa0c6b2 Mon Sep 17 00:00:00 2001 From: Clemens Date: Wed, 13 Jul 2016 18:16:31 +0200 Subject: added code editor and file upload --- web/package.json | 4 +-- web/src/js/app.jsx | 2 +- web/src/js/components/ContentView.jsx | 24 +++++++++++-- web/src/js/components/ContentView/ContentViews.jsx | 30 +++++++++++----- web/src/js/components/common/Button.jsx | 6 ++-- web/src/js/components/common/CodeEditor.jsx | 41 ++++++++++++++++++++++ web/src/js/components/common/MonacoEditor.jsx | 34 ------------------ web/src/js/ducks/flows.js | 8 +++++ 8 files changed, 99 insertions(+), 50 deletions(-) create mode 100644 web/src/js/components/common/CodeEditor.jsx delete mode 100644 web/src/js/components/common/MonacoEditor.jsx (limited to 'web') diff --git a/web/package.json b/web/package.json index 1484961d..7cfd3d90 100644 --- a/web/package.json +++ b/web/package.json @@ -3,7 +3,7 @@ "private": true, "scripts": { "test": "jest", - "build": "gulp dev", + "build": "gulp prod", "start": "gulp" }, "jest": { @@ -29,7 +29,7 @@ "redux-logger": "^2.6.1", "redux-thunk": "^2.1.0", "shallowequal": "^0.2.2", - "monaco-editor": "^0.5.1" + "react-ace": "^3.5.0" }, "devDependencies": { "babel-core": "^6.7.7", diff --git a/web/src/js/app.jsx b/web/src/js/app.jsx index 51b2b639..5acf5dd4 100644 --- a/web/src/js/app.jsx +++ b/web/src/js/app.jsx @@ -12,7 +12,7 @@ import { add as addLog } from './ducks/eventLog' const middlewares = [thunk]; -if (process.env.NODE_ENV === 'development' || true) { +if (process.env.NODE_ENV === 'development' ) { const createLogger = require('redux-logger'); middlewares.push(createLogger()); } diff --git a/web/src/js/components/ContentView.jsx b/web/src/js/components/ContentView.jsx index f6dbe90a..6c9d9b26 100644 --- a/web/src/js/components/ContentView.jsx +++ b/web/src/js/components/ContentView.jsx @@ -4,6 +4,7 @@ import { ViewAuto, ViewImage } from './ContentView/ContentViews' import * as MetaViews from './ContentView/MetaViews' import ContentLoader from './ContentView/ContentLoader' import ViewSelector from './ContentView/ViewSelector' +import * as flowsActions from '../ducks/flows' export default class ContentView extends Component { @@ -40,6 +41,15 @@ export default class ContentView extends Component { return msg.contentLength > 1024 * 1024 * (ViewImage.matches(msg) ? 10 : 0.2) } + onOpenFile(e) { + if (e.target.files.length > 0) { + //alert(e.target.files[0]) + flowsActions.update_content(this.props.flow, e.target.files[0]) + //this.fileInput.value = '' + } + e.preventDefault() + } + render() { const { flow, message } = this.props const { displayLarge, View } = this.state @@ -60,10 +70,10 @@ export default class ContentView extends Component {
{View.textView ? ( - + flowsActions.update_content(this.props.flow, content)} content="" /> ) : ( - + flowsActions.update_content(this.props.flow, content)} message={message} /> )}
@@ -71,6 +81,16 @@ export default class ContentView extends Component { +   + {this.fileInput.click(); e.preventDefault();}}> + + + this.fileInput = ref} + className="hidden" + type="file" + onChange={e => this.onOpenFile(e)} + />
) diff --git a/web/src/js/components/ContentView/ContentViews.jsx b/web/src/js/components/ContentView/ContentViews.jsx index e5a864bf..617ed242 100644 --- a/web/src/js/components/ContentView/ContentViews.jsx +++ b/web/src/js/components/ContentView/ContentViews.jsx @@ -1,10 +1,12 @@ import React, { PropTypes } from 'react' import ContentLoader from './ContentLoader' import { MessageUtils } from '../../flow/utils.js' -import Button from '../common/Button' +import CodeEditor from '../common/CodeEditor' +import {formatSize} from '../../utils.js' -const views = [ViewAuto, ViewImage, ViewJSON, ViewRaw] + +const views = [ViewAuto, ViewImage, ViewJSON, ViewRaw, ViewFile] ViewImage.regex = /^image\/(png|jpe?g|gif|vnc.microsoft.icon|x-icon)$/i ViewImage.matches = msg => ViewImage.regex.test(MessageUtils.getContentType(msg)) @@ -30,12 +32,9 @@ ViewRaw.propTypes = { content: React.PropTypes.string.isRequired, } -export function ViewRaw({ content, onChange }) { +export function ViewRaw({ content, update_content }) { return ( -
- -
+ ) } @@ -66,13 +65,26 @@ ViewAuto.propTypes = { flow: React.PropTypes.object.isRequired, } -export function ViewAuto({ message, flow, onChange }) { +export function ViewAuto({ message, flow, update_content }) { const View = ViewAuto.findView(message) if (View.textView) { - return + return } else { return } } +ViewFile.matches = () => false + +ViewFile.propTypes = { + message: React.PropTypes.object.isRequired, + flow: React.PropTypes.object.isRequired, +} + +export function ViewFile({ message, flow }) { + return
+ {formatSize(message.contentLength)} content size. +
+} + export default views diff --git a/web/src/js/components/common/Button.jsx b/web/src/js/components/common/Button.jsx index 574288df..221c6ace 100644 --- a/web/src/js/components/common/Button.jsx +++ b/web/src/js/components/common/Button.jsx @@ -10,8 +10,10 @@ export default function Button({ onClick, text, icon, disabled }) {
- -   + {text}
) diff --git a/web/src/js/components/common/CodeEditor.jsx b/web/src/js/components/common/CodeEditor.jsx new file mode 100644 index 00000000..d7e6aabb --- /dev/null +++ b/web/src/js/components/common/CodeEditor.jsx @@ -0,0 +1,41 @@ +import React, { Component, PropTypes } from 'react' +import { render } from 'react-dom'; +import brace from 'brace'; +import AceEditor from 'react-ace'; +import Button from './Button' + + +import 'brace/mode/javascript'; +import 'brace/mode/json'; +import 'brace/theme/monokai'; + + + + +export default class CodeEditor extends Component{ + constructor( props ) { + super(props) + this.state = {value: this.props.value} + } + + onChange(newValue) { + this.setState({value: newValue}) + } + + render() { + return ( +
e.stopPropagation()}> + this.onChange(e)} + mode="javascript" + theme="monokai" + value={this.state.value} + width="100%" + name="codeEditor" + editorProps={{$blockScrolling: Infinity}} + /> +
+ ) + } +} diff --git a/web/src/js/components/common/MonacoEditor.jsx b/web/src/js/components/common/MonacoEditor.jsx deleted file mode 100644 index a0e8d58c..00000000 --- a/web/src/js/components/common/MonacoEditor.jsx +++ /dev/null @@ -1,34 +0,0 @@ -//not working -import React, { Component, PropTypes } from 'react' - -export default class MonacoEditor extends Component { - - constructor(props) { - super(props) - } - - onLoad(){ - window.MonacoEnvironment = { - getWorkerUrl: function(workerId, label) { - return 'worker-loader-proxy.js'; - } - }; - require.config({ - paths: { - vs: '../release/min/vs' - } - }); - - } - - - render() { - return ( -
this.editor = ref} - style="width:800px;height:600px;border:1px solid grey" - onLoad={this.onLoad()}> -
- ) - } -} diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js index f0b09530..36274f39 100644 --- a/web/src/js/ducks/flows.js +++ b/web/src/js/ducks/flows.js @@ -117,6 +117,14 @@ export function update(flow, data) { return { type: REQUEST_ACTION } } +export function update_content(flow, file) { + const body = new FormData() + body.append('file', file) + fetchApi(`/flows/${flow.id}/response/content`, {method: 'post', body} ) + return { type: REQUEST_ACTION } +} + + /** * @public */ -- cgit v1.2.3 From 121079934e705ae91a983c0ea5858b5483941d7f Mon Sep 17 00:00:00 2001 From: Clemens Date: Wed, 13 Jul 2016 20:18:04 +0200 Subject: make file out ouf string to combine flow content updates via editor and fileupload --- web/src/js/ducks/flows.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'web') diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js index 36274f39..8815db25 100644 --- a/web/src/js/ducks/flows.js +++ b/web/src/js/ducks/flows.js @@ -119,6 +119,8 @@ export function update(flow, data) { export function update_content(flow, file) { const body = new FormData() + if (typeof file !== File) + file = new Blob([file], {type: 'plain/text'}) body.append('file', file) fetchApi(`/flows/${flow.id}/response/content`, {method: 'post', body} ) return { type: REQUEST_ACTION } -- cgit v1.2.3 From baac6c4693d140bd42be22fea8b0c784cda61cdd Mon Sep 17 00:00:00 2001 From: Clemens Date: Wed, 13 Jul 2016 20:44:35 +0200 Subject: gzip issue --- web/src/js/ducks/flows.js | 1 + 1 file changed, 1 insertion(+) (limited to 'web') diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js index 8815db25..1dc88c67 100644 --- a/web/src/js/ducks/flows.js +++ b/web/src/js/ducks/flows.js @@ -123,6 +123,7 @@ export function update_content(flow, file) { file = new Blob([file], {type: 'plain/text'}) body.append('file', file) fetchApi(`/flows/${flow.id}/response/content`, {method: 'post', body} ) + update(flow, {response: {headers: [['Content-Encoding', '']]} } ) return { type: REQUEST_ACTION } } -- cgit v1.2.3 From 45349b3597f53ee08207b20eb8bff9dfc9166aa8 Mon Sep 17 00:00:00 2001 From: Clemens Date: Wed, 13 Jul 2016 20:53:05 +0200 Subject: chaged editor style --- web/src/js/components/common/CodeEditor.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'web') diff --git a/web/src/js/components/common/CodeEditor.jsx b/web/src/js/components/common/CodeEditor.jsx index d7e6aabb..85da0507 100644 --- a/web/src/js/components/common/CodeEditor.jsx +++ b/web/src/js/components/common/CodeEditor.jsx @@ -7,7 +7,7 @@ import Button from './Button' import 'brace/mode/javascript'; import 'brace/mode/json'; -import 'brace/theme/monokai'; +import 'brace/theme/kuroir'; @@ -28,7 +28,7 @@ export default class CodeEditor extends Component{ this.onChange(e)} mode="javascript" - theme="monokai" + theme="kuroir" value={this.state.value} width="100%" name="codeEditor" -- cgit v1.2.3 From 5f3782dd5fb8be4c196f57cb07fd1cc2fd6b2f56 Mon Sep 17 00:00:00 2001 From: Clemens Date: Thu, 14 Jul 2016 23:01:34 +0200 Subject: change way to edit --- web/src/css/flowdetail.less | 2 +- web/src/js/components/ContentView.jsx | 81 ++++++++++++++-------- .../js/components/ContentView/ContentEditor.jsx | 42 +++++++++++ web/src/js/components/ContentView/ContentViews.jsx | 29 ++------ web/src/js/components/FlowView/Messages.jsx | 11 ++- web/src/js/components/common/Button.jsx | 10 ++- web/src/js/components/common/CodeEditor.jsx | 24 ++----- web/src/js/ducks/flows.js | 5 +- 8 files changed, 122 insertions(+), 82 deletions(-) create mode 100644 web/src/js/components/ContentView/ContentEditor.jsx (limited to 'web') diff --git a/web/src/css/flowdetail.less b/web/src/css/flowdetail.less index edf97566..43078eff 100644 --- a/web/src/css/flowdetail.less +++ b/web/src/css/flowdetail.less @@ -109,4 +109,4 @@ text-overflow: ellipsis; white-space: nowrap; } -} \ No newline at end of file +} diff --git a/web/src/js/components/ContentView.jsx b/web/src/js/components/ContentView.jsx index 6c9d9b26..fa26a057 100644 --- a/web/src/js/components/ContentView.jsx +++ b/web/src/js/components/ContentView.jsx @@ -4,7 +4,7 @@ import { ViewAuto, ViewImage } from './ContentView/ContentViews' import * as MetaViews from './ContentView/MetaViews' import ContentLoader from './ContentView/ContentLoader' import ViewSelector from './ContentView/ViewSelector' -import * as flowsActions from '../ducks/flows' +import ContentEditor from './ContentView/ContentEditor' export default class ContentView extends Component { @@ -14,12 +14,13 @@ export default class ContentView extends Component { // flow: React.PropTypes.object.isRequired, message: React.PropTypes.object.isRequired, + onContentChange: React.PropTypes.func.isRequired } constructor(props, context) { super(props, context) - this.state = { displayLarge: false, View: ViewAuto } + this.state = { displayLarge: false, View: ViewAuto, contentEditorClosed: true } this.selectView = this.selectView.bind(this) } @@ -43,9 +44,7 @@ export default class ContentView extends Component { onOpenFile(e) { if (e.target.files.length > 0) { - //alert(e.target.files[0]) - flowsActions.update_content(this.props.flow, e.target.files[0]) - //this.fileInput.value = '' + this.props.onContentChange(e.target.files[0]) } e.preventDefault() } @@ -68,30 +67,56 @@ export default class ContentView extends Component { return (
- {View.textView ? ( - - flowsActions.update_content(this.props.flow, content)} content="" /> - - ) : ( - flowsActions.update_content(this.props.flow, content)} message={message} /> - )} -
- -   - - - -   - {this.fileInput.click(); e.preventDefault();}}> - - - this.fileInput = ref} - className="hidden" - type="file" - onChange={e => this.onOpenFile(e)} - /> +
+
+ + this.setState({contentEditorClosed : true})} + onOpen={() => this.setState({contentEditorClosed : false})} + isClosed={this.state.contentEditorClosed} + content="" + /> + +
+ + {this.state.contentEditorClosed && (
+ {View.textView ? ( + + + + ) : ( + + )} + + + +
+ +   + + + +   + {this.fileInput.click(); e.preventDefault();}} + title="Upload a file to replace the content." + > + + + this.fileInput = ref} + className="hidden" + type="file" + onChange={e => this.onOpenFile(e)} + /> +
+
)}
) } diff --git a/web/src/js/components/ContentView/ContentEditor.jsx b/web/src/js/components/ContentView/ContentEditor.jsx new file mode 100644 index 00000000..a38e4d6f --- /dev/null +++ b/web/src/js/components/ContentView/ContentEditor.jsx @@ -0,0 +1,42 @@ +import React, { Component, PropTypes } from 'react' +import CodeEditor from '../common/CodeEditor' + +export default class ContentEditor extends Component { + + static propTypes = { + content: PropTypes.string.isRequired, + onSave: PropTypes.func.isRequired, + onClose: PropTypes.func.isRequired, + onOpen: PropTypes.func.isRequired, + isClosed: PropTypes.bool.isRequired + } + + constructor(props){ + super(props) + this.state = {content: this.props.content} + } + + render() { + return ( +
+ {this.props.isClosed ? + + + : + + + + + this.props.onSave(this.state.content)}> + + + + } + {!this.props.isClosed && + this.setState({content: content})}/> + } +
+ + ) + } +} diff --git a/web/src/js/components/ContentView/ContentViews.jsx b/web/src/js/components/ContentView/ContentViews.jsx index 617ed242..82ee0adc 100644 --- a/web/src/js/components/ContentView/ContentViews.jsx +++ b/web/src/js/components/ContentView/ContentViews.jsx @@ -1,12 +1,9 @@ import React, { PropTypes } from 'react' import ContentLoader from './ContentLoader' import { MessageUtils } from '../../flow/utils.js' -import CodeEditor from '../common/CodeEditor' -import {formatSize} from '../../utils.js' - -const views = [ViewAuto, ViewImage, ViewJSON, ViewRaw, ViewFile] +const views = [ViewAuto, ViewImage, ViewJSON, ViewRaw] ViewImage.regex = /^image\/(png|jpe?g|gif|vnc.microsoft.icon|x-icon)$/i ViewImage.matches = msg => ViewImage.regex.test(MessageUtils.getContentType(msg)) @@ -26,16 +23,13 @@ export function ViewImage({ flow, message }) { ViewRaw.textView = true ViewRaw.matches = () => true -ViewRaw.input = {} ViewRaw.propTypes = { content: React.PropTypes.string.isRequired, } -export function ViewRaw({ content, update_content }) { - return ( - - ) +export function ViewRaw({ content }) { + return
{content}
} ViewJSON.textView = true @@ -65,26 +59,13 @@ ViewAuto.propTypes = { flow: React.PropTypes.object.isRequired, } -export function ViewAuto({ message, flow, update_content }) { +export function ViewAuto({ message, flow }) { const View = ViewAuto.findView(message) if (View.textView) { - return + return } else { return } } -ViewFile.matches = () => false - -ViewFile.propTypes = { - message: React.PropTypes.object.isRequired, - flow: React.PropTypes.object.isRequired, -} - -export function ViewFile({ message, flow }) { - return
- {formatSize(message.contentLength)} content size. -
-} - export default views diff --git a/web/src/js/components/FlowView/Messages.jsx b/web/src/js/components/FlowView/Messages.jsx index d2c42a54..27e18c05 100644 --- a/web/src/js/components/FlowView/Messages.jsx +++ b/web/src/js/components/FlowView/Messages.jsx @@ -6,6 +6,7 @@ import { Key, formatTimeStamp } from '../../utils.js' import ContentView from '../ContentView' import ValueEditor from '../ValueEditor' import Headers from './Headers' +import * as flowActions from '../../ducks/flows' class RequestLine extends Component { @@ -89,7 +90,10 @@ export class Request extends Component { onChange={headers => updateFlow({ request: { headers } })} />
- updateFlow({request: {content} })}/> + flowActions.updateContent(this.props.flow, content, "request") } + message={flow.request} + /> ) } @@ -128,7 +132,10 @@ export class Response extends Component { onChange={headers => updateFlow({ response: { headers } })} />
- updateFlow({response: {content} }) }/> + flowActions.updateContent(this.props.flow, content, "response") } + message={flow.response} + /> ) } diff --git a/web/src/js/components/common/Button.jsx b/web/src/js/components/common/Button.jsx index 221c6ace..cd01af22 100644 --- a/web/src/js/components/common/Button.jsx +++ b/web/src/js/components/common/Button.jsx @@ -2,7 +2,8 @@ import React, { PropTypes } from 'react' Button.propTypes = { onClick: PropTypes.func.isRequired, - text: PropTypes.string.isRequired + text: PropTypes.string, + icon: PropTypes.string } export default function Button({ onClick, text, icon, disabled }) { @@ -10,11 +11,8 @@ export default function Button({ onClick, text, icon, disabled }) {
- - {text} + {icon && ( )} + {text && text}
) } diff --git a/web/src/js/components/common/CodeEditor.jsx b/web/src/js/components/common/CodeEditor.jsx index 85da0507..b10b13ed 100644 --- a/web/src/js/components/common/CodeEditor.jsx +++ b/web/src/js/components/common/CodeEditor.jsx @@ -1,40 +1,28 @@ import React, { Component, PropTypes } from 'react' import { render } from 'react-dom'; -import brace from 'brace'; import AceEditor from 'react-ace'; -import Button from './Button' - import 'brace/mode/javascript'; -import 'brace/mode/json'; import 'brace/theme/kuroir'; - - - export default class CodeEditor extends Component{ - constructor( props ) { - super(props) - this.state = {value: this.props.value} - } - - onChange(newValue) { - this.setState({value: newValue}) + static propTypes = { + value: PropTypes.string.isRequired, + onChange: PropTypes.func.isRequired, } render() { return (
e.stopPropagation()}> this.onChange(e)} mode="javascript" theme="kuroir" - value={this.state.value} + onChange={this.props.onChange} + name="rea" + value={this.props.value} width="100%" - name="codeEditor" editorProps={{$blockScrolling: Infinity}} /> -
) } diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js index 1dc88c67..3dd21016 100644 --- a/web/src/js/ducks/flows.js +++ b/web/src/js/ducks/flows.js @@ -117,13 +117,12 @@ export function update(flow, data) { return { type: REQUEST_ACTION } } -export function update_content(flow, file) { +export function updateContent(flow, file, type) { const body = new FormData() if (typeof file !== File) file = new Blob([file], {type: 'plain/text'}) body.append('file', file) - fetchApi(`/flows/${flow.id}/response/content`, {method: 'post', body} ) - update(flow, {response: {headers: [['Content-Encoding', '']]} } ) + fetchApi(`/flows/${flow.id}/${type}/content`, {method: 'post', body} ) return { type: REQUEST_ACTION } } -- cgit v1.2.3 From 87797d7ac07108ce5fd00902918e4900907b94b6 Mon Sep 17 00:00:00 2001 From: Clemens Date: Fri, 15 Jul 2016 14:41:30 +0200 Subject: added new btn, changed to codemirror --- web/package.json | 2 +- web/src/css/app.less | 3 ++- web/src/css/codemirror.less | 5 +++++ web/src/css/flowview.less | 26 +++++++++++++++++++++- web/src/js/components/ContentView.jsx | 22 +++++++----------- .../js/components/ContentView/ContentEditor.jsx | 16 +++++-------- web/src/js/components/common/CodeEditor.jsx | 17 +++++--------- 7 files changed, 51 insertions(+), 40 deletions(-) create mode 100644 web/src/css/codemirror.less (limited to 'web') diff --git a/web/package.json b/web/package.json index 7cfd3d90..81b96adc 100644 --- a/web/package.json +++ b/web/package.json @@ -29,7 +29,7 @@ "redux-logger": "^2.6.1", "redux-thunk": "^2.1.0", "shallowequal": "^0.2.2", - "react-ace": "^3.5.0" + "react-codemirror" : "^0.2.6" }, "devDependencies": { "babel-core": "^6.7.7", diff --git a/web/src/css/app.less b/web/src/css/app.less index 046d378a..6f27f447 100644 --- a/web/src/css/app.less +++ b/web/src/css/app.less @@ -16,4 +16,5 @@ html { @import (less) "flowview.less"; @import (less) "prompt.less"; @import (less) "eventlog.less"; -@import (less) "footer.less"; \ No newline at end of file +@import (less) "footer.less"; +@import (less) "codemirror.less"; diff --git a/web/src/css/codemirror.less b/web/src/css/codemirror.less new file mode 100644 index 00000000..47c766f4 --- /dev/null +++ b/web/src/css/codemirror.less @@ -0,0 +1,5 @@ +.ReactCodeMirror { + border: 1px solid #ccc; +} + +@import (inline) "../../node_modules/codemirror/lib/codemirror.css"; diff --git a/web/src/css/flowview.less b/web/src/css/flowview.less index aa8a2df2..328e3a26 100644 --- a/web/src/css/flowview.less +++ b/web/src/css/flowview.less @@ -6,4 +6,28 @@ max-width: 100%; max-height: 100%; } -} \ No newline at end of file +} + +.edit-flow { + position: absolute; + right: 25px; + top: 140px; + height: 40px; + width: 40px; + border-radius: 20px; + + background-color: white; + border: solid 2px rgba(248, 145, 59, 0.7); + + text-align: center; + font-size: 22px; + line-height: 37px; + + transition: all 100ms ease-in-out; +} + +.edit-flow:hover { + background-color: rgba(239, 108, 0, 0.7); + color: rgba(0,0,0,0.8); + border: solid 2px transparent; +} diff --git a/web/src/js/components/ContentView.jsx b/web/src/js/components/ContentView.jsx index fa26a057..70bca249 100644 --- a/web/src/js/components/ContentView.jsx +++ b/web/src/js/components/ContentView.jsx @@ -67,20 +67,14 @@ export default class ContentView extends Component { return (
-
-
- - this.setState({contentEditorClosed : true})} - onOpen={() => this.setState({contentEditorClosed : false})} - isClosed={this.state.contentEditorClosed} - content="" - /> - -
-
- + + {this.props.onContentChange(content);this.setState({contentEditorClosed : true});}} + onOpen={() => this.setState({contentEditorClosed : false})} + isClosed={this.state.contentEditorClosed} + content="" + /> + {this.state.contentEditorClosed && (
{View.textView ? ( diff --git a/web/src/js/components/ContentView/ContentEditor.jsx b/web/src/js/components/ContentView/ContentEditor.jsx index a38e4d6f..ca2f3370 100644 --- a/web/src/js/components/ContentView/ContentEditor.jsx +++ b/web/src/js/components/ContentView/ContentEditor.jsx @@ -6,7 +6,6 @@ export default class ContentEditor extends Component { static propTypes = { content: PropTypes.string.isRequired, onSave: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired, onOpen: PropTypes.func.isRequired, isClosed: PropTypes.bool.isRequired } @@ -20,17 +19,12 @@ export default class ContentEditor extends Component { return (
{this.props.isClosed ? - - + + : - - - - - this.props.onSave(this.state.content)}> - - - + this.props.onSave(this.state.content)}> + + } {!this.props.isClosed && this.setState({content: content})}/> diff --git a/web/src/js/components/common/CodeEditor.jsx b/web/src/js/components/common/CodeEditor.jsx index b10b13ed..c122cf94 100644 --- a/web/src/js/components/common/CodeEditor.jsx +++ b/web/src/js/components/common/CodeEditor.jsx @@ -1,9 +1,7 @@ import React, { Component, PropTypes } from 'react' import { render } from 'react-dom'; -import AceEditor from 'react-ace'; +import Codemirror from 'react-codemirror'; -import 'brace/mode/javascript'; -import 'brace/theme/kuroir'; export default class CodeEditor extends Component{ static propTypes = { @@ -12,17 +10,12 @@ export default class CodeEditor extends Component{ } render() { + let options = { + lineNumbers: true + }; return (
e.stopPropagation()}> - +
) } -- cgit v1.2.3 From 48728af43ad746d70ef3e251dc28b75028dea1e6 Mon Sep 17 00:00:00 2001 From: Clemens Date: Tue, 19 Jul 2016 12:23:20 +0200 Subject: moved flow editor state to redux --- web/src/css/codemirror.less | 4 ++ web/src/css/flowview.less | 9 +++- web/src/js/components/ContentView.jsx | 32 ++++++++------- .../js/components/ContentView/ContentEditor.jsx | 36 ---------------- .../js/components/FlowView/FlowEditorButton.jsx | 48 ++++++++++++++++++++++ web/src/js/components/FlowView/Messages.jsx | 15 +++++-- web/src/js/components/common/CodeEditor.jsx | 12 +++++- web/src/js/components/common/Splitter.jsx | 1 + web/src/js/ducks/flows.js | 19 +++++++++ 9 files changed, 118 insertions(+), 58 deletions(-) delete mode 100644 web/src/js/components/ContentView/ContentEditor.jsx create mode 100644 web/src/js/components/FlowView/FlowEditorButton.jsx (limited to 'web') diff --git a/web/src/css/codemirror.less b/web/src/css/codemirror.less index 47c766f4..6504db50 100644 --- a/web/src/css/codemirror.less +++ b/web/src/css/codemirror.less @@ -2,4 +2,8 @@ border: 1px solid #ccc; } +.CodeMirror{ + height: auto !important; + max-height: 1000px !important; +} @import (inline) "../../node_modules/codemirror/lib/codemirror.css"; diff --git a/web/src/css/flowview.less b/web/src/css/flowview.less index 328e3a26..419739a4 100644 --- a/web/src/css/flowview.less +++ b/web/src/css/flowview.less @@ -8,13 +8,18 @@ } } +.edit-flow-container { + position: relative; +} + .edit-flow { position: absolute; - right: 25px; - top: 140px; + right: 0px; + top: 5px; height: 40px; width: 40px; border-radius: 20px; + z-index: 10000; background-color: white; border: solid 2px rgba(248, 145, 59, 0.7); diff --git a/web/src/js/components/ContentView.jsx b/web/src/js/components/ContentView.jsx index 70bca249..3cd9990c 100644 --- a/web/src/js/components/ContentView.jsx +++ b/web/src/js/components/ContentView.jsx @@ -1,12 +1,15 @@ import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' import { MessageUtils } from '../flow/utils.js' import { ViewAuto, ViewImage } from './ContentView/ContentViews' import * as MetaViews from './ContentView/MetaViews' import ContentLoader from './ContentView/ContentLoader' import ViewSelector from './ContentView/ViewSelector' -import ContentEditor from './ContentView/ContentEditor' +import CodeEditor from './common/CodeEditor' +import {setModifiedFlowContent} from '../ducks/flows' -export default class ContentView extends Component { + +class ContentView extends Component { static propTypes = { // It may seem a bit weird at the first glance: @@ -19,8 +22,7 @@ export default class ContentView extends Component { constructor(props, context) { super(props, context) - - this.state = { displayLarge: false, View: ViewAuto, contentEditorClosed: true } + this.state = { displayLarge: false, View: ViewAuto} this.selectView = this.selectView.bind(this) } @@ -50,7 +52,7 @@ export default class ContentView extends Component { } render() { - const { flow, message } = this.props + const { flow, message, setModifiedFlowContent, isFlowEditorOpen } = this.props const { displayLarge, View } = this.state if (message.contentLength === 0) { @@ -67,15 +69,11 @@ export default class ContentView extends Component { return (
- - {this.props.onContentChange(content);this.setState({contentEditorClosed : true});}} - onOpen={() => this.setState({contentEditorClosed : false})} - isClosed={this.state.contentEditorClosed} - content="" - /> - - {this.state.contentEditorClosed && (
+ {isFlowEditorOpen ? ( + + {setModifiedFlowContent(content)}}/> + + ): (
{View.textView ? ( @@ -115,3 +113,9 @@ export default class ContentView extends Component { ) } } +export default connect( + state => ( + {isFlowEditorOpen : state.ui.isFlowEditorOpen} + ), { + setModifiedFlowContent + })(ContentView) diff --git a/web/src/js/components/ContentView/ContentEditor.jsx b/web/src/js/components/ContentView/ContentEditor.jsx deleted file mode 100644 index ca2f3370..00000000 --- a/web/src/js/components/ContentView/ContentEditor.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { Component, PropTypes } from 'react' -import CodeEditor from '../common/CodeEditor' - -export default class ContentEditor extends Component { - - static propTypes = { - content: PropTypes.string.isRequired, - onSave: PropTypes.func.isRequired, - onOpen: PropTypes.func.isRequired, - isClosed: PropTypes.bool.isRequired - } - - constructor(props){ - super(props) - this.state = {content: this.props.content} - } - - render() { - return ( -
- {this.props.isClosed ? - - - : - this.props.onSave(this.state.content)}> - - - } - {!this.props.isClosed && - this.setState({content: content})}/> - } -
- - ) - } -} diff --git a/web/src/js/components/FlowView/FlowEditorButton.jsx b/web/src/js/components/FlowView/FlowEditorButton.jsx new file mode 100644 index 00000000..e9c75535 --- /dev/null +++ b/web/src/js/components/FlowView/FlowEditorButton.jsx @@ -0,0 +1,48 @@ +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 +// } + +class FlowEditorButton extends Component{ + static propTypes = { + isFlowEditorOpen: PropTypes.bool.isRequired, + content: PropTypes.string.isRequired, + onContentChange: PropTypes.func.isRequired + } + + render(){ + let { isFlowEditorOpen, closeFlowEditor, openFlowEditor, onContentChange, content } = this.props + return ( + + ) + } +} + +export default connect( + state => ({ + isFlowEditorOpen: state.ui.isFlowEditorOpen, + content: state.flows.modifiedFlow.content + }), + { + closeFlowEditor, + openFlowEditor + + } +)(FlowEditorButton) diff --git a/web/src/js/components/FlowView/Messages.jsx b/web/src/js/components/FlowView/Messages.jsx index 27e18c05..8cb918a8 100644 --- a/web/src/js/components/FlowView/Messages.jsx +++ b/web/src/js/components/FlowView/Messages.jsx @@ -7,6 +7,8 @@ import ContentView from '../ContentView' import ValueEditor from '../ValueEditor' import Headers from './Headers' import * as flowActions from '../../ducks/flows' +import FlowEditorButton from './FlowEditorButton.jsx' + class RequestLine extends Component { @@ -77,21 +79,23 @@ class ResponseLine extends Component { } export class Request extends Component { - - render() { + render() { const { flow, updateFlow } = this.props + let onContentChange = content => flowActions.updateContent(this.props.flow, content, "request") return (
+ updateFlow({ request: { headers } })} /> +
flowActions.updateContent(this.props.flow, content, "request") } + onContentChange={onContentChange} message={flow.request} />
@@ -120,11 +124,14 @@ export class Request extends Component { export class Response extends Component { + render() { const { flow, updateFlow } = this.props + let onContentChange = content => flowActions.updateContent(this.props.flow, content, "response") return (
+
flowActions.updateContent(this.props.flow, content, "response") } + onContentChange={onContentChange} message={flow.response} />
diff --git a/web/src/js/components/common/CodeEditor.jsx b/web/src/js/components/common/CodeEditor.jsx index c122cf94..5b2305a8 100644 --- a/web/src/js/components/common/CodeEditor.jsx +++ b/web/src/js/components/common/CodeEditor.jsx @@ -5,17 +5,25 @@ import Codemirror from 'react-codemirror'; export default class CodeEditor extends Component{ static propTypes = { - value: PropTypes.string.isRequired, + content: PropTypes.string.isRequired, onChange: PropTypes.func.isRequired, } + constructor(props){ + super(props) + } + + componentWillMount(){ + this.props.onChange(this.props.content) + } + render() { let options = { lineNumbers: true }; return (
e.stopPropagation()}> - +
) } diff --git a/web/src/js/components/common/Splitter.jsx b/web/src/js/components/common/Splitter.jsx index 9d22b6fd..bd4fb3d2 100644 --- a/web/src/js/components/common/Splitter.jsx +++ b/web/src/js/components/common/Splitter.jsx @@ -12,6 +12,7 @@ export default class Splitter extends Component { this.state = { applied: false, startX: false, startY: false } this.onMouseMove = this.onMouseMove.bind(this) + this.onMouseDown = this.onMouseDown.bind(this) this.onMouseUp = this.onMouseUp.bind(this) this.onDragEnd = this.onDragEnd.bind(this) } diff --git a/web/src/js/ducks/flows.js b/web/src/js/ducks/flows.js index 3dd21016..eea91924 100644 --- a/web/src/js/ducks/flows.js +++ b/web/src/js/ducks/flows.js @@ -14,10 +14,12 @@ export const RECEIVE = 'FLOWS_RECEIVE' export const REQUEST_ACTION = 'FLOWS_REQUEST_ACTION' export const UNKNOWN_CMD = 'FLOWS_UNKNOWN_CMD' export const FETCH_ERROR = 'FLOWS_FETCH_ERROR' +export const SET_MODIFIED_FLOW_CONTENT = "FLOWS_SET_MODIFIED_FLOW" const defaultState = { list: undefined, views: undefined, + modifiedFlow: {headers: "", content: ""} } export default function reduce(state = defaultState, action) { @@ -51,6 +53,12 @@ export default function reduce(state = defaultState, action) { list, views: reduceViews(state.views, viewsActions.receive(list)), } + case SET_MODIFIED_FLOW_CONTENT: + return{ + ...state, + modifiedFlow: {...state.modifiedFlow, content: action.content} + } + default: return { @@ -61,6 +69,17 @@ export default function reduce(state = defaultState, action) { } } +/** + * @public + */ +export function setModifiedFlowContent(content) { + return { + type: SET_MODIFIED_FLOW_CONTENT, + content + } +} + + /** * @public */ -- cgit v1.2.3 From 281f20ef1e9ac33a7e210ba562eb2914f6d187e6 Mon Sep 17 00:00:00 2001 From: Clemens Date: Tue, 19 Jul 2016 16:13:26 +0200 Subject: added flow_content update --- web/src/js/components/ContentView.jsx | 54 ++++++++++++++++------ .../js/components/FlowView/FlowEditorButton.jsx | 49 ++++++++------------ web/src/js/components/FlowView/Messages.jsx | 2 +- web/src/js/ducks/ui.js | 43 +++++++++++++++-- 4 files changed, 98 insertions(+), 50 deletions(-) (limited to 'web') diff --git a/web/src/js/components/ContentView.jsx b/web/src/js/components/ContentView.jsx index 0b93d3f0..766de26f 100644 --- a/web/src/js/components/ContentView.jsx +++ b/web/src/js/components/ContentView.jsx @@ -5,9 +5,8 @@ import * as ContentViews from './ContentView/ContentViews' import * as MetaViews from './ContentView/MetaViews' import ContentLoader from './ContentView/ContentLoader' import ViewSelector from './ContentView/ViewSelector' -import { setContentView, setDisplayLarge } from '../ducks/ui' +import { setContentView, setDisplayLarge, setModifiedFlowContent } from '../ducks/ui' import CodeEditor from './common/CodeEditor' -import {setModifiedFlowContent} from '../ducks/flows' ContentView.propTypes = { // It may seem a bit weird at the first glance: @@ -20,7 +19,7 @@ ContentView.propTypes = { ContentView.isContentTooLarge = msg => msg.contentLength > 1024 * 1024 * (ContentViews.ViewImage.matches(msg) ? 10 : 0.2) function ContentView(props) { - const { flow, message, contentView, selectView, displayLarge, setDisplayLarge } = props + const { flow, message, contentView, selectView, displayLarge, setDisplayLarge, onContentChange, isFlowEditorOpen, setModifiedFlowContent } = props if (message.contentLength === 0) { return @@ -38,20 +37,43 @@ function ContentView(props) { return (
- {View.textView ? ( + {isFlowEditorOpen ? ( - - - ) : ( - + {setModifiedFlowContent(content)}}/> + + ): ( +
+ {View.textView ? ( + + + + ) : ( + + )} +
+ +   + + + +   + ContentView.fileInput.click()} + title="Upload a file to replace the content." + > + + + ContentView.fileInput = ref} + className="hidden" + type="file" + onChange={e => {if(e.target.files.length > 0) onContentChange(e.target.files[0])}} + /> +
+
)} -
- -   - - - -
) } @@ -60,9 +82,11 @@ export default connect( state => ({ contentView: state.ui.contentView, displayLarge: state.ui.displayLarge, + isFlowEditorOpen : state.ui.isFlowEditorOpen }), { selectView: setContentView, setDisplayLarge, + setModifiedFlowContent } )(ContentView) diff --git a/web/src/js/components/FlowView/FlowEditorButton.jsx b/web/src/js/components/FlowView/FlowEditorButton.jsx index e9c75535..3d0d1d16 100644 --- a/web/src/js/components/FlowView/FlowEditorButton.jsx +++ b/web/src/js/components/FlowView/FlowEditorButton.jsx @@ -4,41 +4,32 @@ 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 -// } - -class FlowEditorButton extends Component{ - static propTypes = { - isFlowEditorOpen: PropTypes.bool.isRequired, - content: PropTypes.string.isRequired, - onContentChange: PropTypes.func.isRequired - } +FlowEditorButton.propTypes = { + isFlowEditorOpen: PropTypes.bool.isRequired, + content: PropTypes.string.isRequired, + onContentChange: PropTypes.func.isRequired +} - render(){ - let { isFlowEditorOpen, closeFlowEditor, openFlowEditor, onContentChange, content } = this.props - return ( - - ) - } +function FlowEditorButton ({ isFlowEditorOpen, closeFlowEditor, openFlowEditor, onContentChange, content }) { + return ( + + ) } export default connect( state => ({ isFlowEditorOpen: state.ui.isFlowEditorOpen, - content: state.flows.modifiedFlow.content + content: state.ui.modifiedFlow.content }), { closeFlowEditor, diff --git a/web/src/js/components/FlowView/Messages.jsx b/web/src/js/components/FlowView/Messages.jsx index 8cb918a8..2f03c712 100644 --- a/web/src/js/components/FlowView/Messages.jsx +++ b/web/src/js/components/FlowView/Messages.jsx @@ -7,7 +7,7 @@ import ContentView from '../ContentView' import ValueEditor from '../ValueEditor' import Headers from './Headers' import * as flowActions from '../../ducks/flows' -import FlowEditorButton from './FlowEditorButton.jsx' +import FlowEditorButton from './FlowEditorButton' class RequestLine extends Component { diff --git a/web/src/js/ducks/ui.js b/web/src/js/ducks/ui.js index f745f0af..ccd17eb6 100644 --- a/web/src/js/ducks/ui.js +++ b/web/src/js/ducks/ui.js @@ -9,6 +9,9 @@ export const UPDATE_QUERY = 'UI_UPDATE_QUERY' export const SELECT_TAB = 'UI_SELECT_TAB' export const SET_PROMPT = 'UI_SET_PROMPT' export const SET_DISPLAY_LARGE = 'UI_SET_DISPLAY_LARGE' +export const OPEN_FLOW_EDITOR= 'UI_OPEN_FLOW_EDITOR' +export const CLOSE_FLOW_EDITOR = 'UI_CLOSE_FLOW_EDITOR' +export const SET_MODIFIED_FLOW_CONTENT = 'UI_SET_MODIFIED_FLOW' const defaultState = { activeMenu: 'Start', @@ -18,7 +21,9 @@ const defaultState = { promptOpen: false, contentView: 'ViewAuto', query: {}, - panel: 'request' + panel: 'request', + modifiedFlow: {headers: "", content: ""}, + isFlowEditorOpen: false } export default function reducer(state = defaultState, action) { @@ -31,9 +36,10 @@ export default function reducer(state = defaultState, action) { } case flowsActions.SELECT: + let s = {...state, isFlowEditorOpen: false} if (action.flowIds.length && !state.isFlowSelected) { return { - ...state, + ...s, displayLarge: false, activeMenu: 'Flow', isFlowSelected: true, @@ -46,14 +52,14 @@ export default function reducer(state = defaultState, action) { activeMenu = 'Start' } return { - ...state, + ...s, activeMenu, isFlowSelected: false, } } return { - ...state, + ...s, displayLarge: false, } @@ -78,6 +84,7 @@ export default function reducer(state = defaultState, action) { case SELECT_TAB: return { ...state, + isFlowEditorOpen: false, panel: action.panel } @@ -92,7 +99,21 @@ export default function reducer(state = defaultState, action) { ...state, displayLarge: action.displayLarge, } - + case OPEN_FLOW_EDITOR: + return { + ...state, + isFlowEditorOpen: true + } + case CLOSE_FLOW_EDITOR: + return { + ...state, + isFlowEditorOpen: false + } + case SET_MODIFIED_FLOW_CONTENT: + return{ + ...state, + modifiedFlow: {...state.modifiedFlow, content: action.content} + } default: return state } @@ -126,6 +147,18 @@ export function setDisplayLarge(displayLarge) { return { type: SET_DISPLAY_LARGE, displayLarge } } +export function openFlowEditor(){ + return { type: OPEN_FLOW_EDITOR } +} + +export function closeFlowEditor(){ + return { type: CLOSE_FLOW_EDITOR } +} + +export function setModifiedFlowContent(content) { + return { type: SET_MODIFIED_FLOW_CONTENT, content } +} + export function onKeyDown(e) { if (e.ctrlKey) { return () => { -- cgit v1.2.3