file upload updates contentview, editable contentloader, diffs on upload

This commit is contained in:
Clemens 2016-07-22 19:07:53 +02:00
parent 70ca10b423
commit f578bf5122
8 changed files with 67 additions and 49 deletions

View File

@ -18,7 +18,7 @@ ContentView.propTypes = {
ContentView.isContentTooLarge = msg => msg.contentLength > 1024 * 1024 * (ContentViews.ViewImage.matches(msg) ? 10 : 0.2) ContentView.isContentTooLarge = msg => msg.contentLength > 1024 * 1024 * (ContentViews.ViewImage.matches(msg) ? 10 : 0.2)
function ContentView(props) { function ContentView(props) {
const { flow, message, contentView, selectView, displayLarge, setDisplayLarge, uploadContent, onContentChange, readonly } = props const { flow, message, contentView, selectView, displayLarge, setDisplayLarge, lastFileUpload, uploadContent, onContentChange, content, readonly } = props
if (message.contentLength === 0) { if (message.contentLength === 0) {
return <MetaViews.ContentEmpty {...props}/> return <MetaViews.ContentEmpty {...props}/>
@ -33,15 +33,14 @@ function ContentView(props) {
} }
const View = ContentViews[contentView] const View = ContentViews[contentView]
return ( return (
<div> <div>
{View.textView ? ( {View.textView ? (
<ContentLoader flow={flow} message={message}> <ContentLoader flow={flow} lastFileUpload={lastFileUpload} readonly={readonly} message={message}>
<View readonly={readonly} onChange={onContentChange} content="" /> <View readonly={readonly} onChange={onContentChange} content="" />
</ContentLoader> </ContentLoader>
) : ( ) : (
<View flow={flow} readonly={readonly} message={message} /> <View flow={flow} lastFileUpload={lastFileUpload} readonly={readonly} content={content} message={message} />
)} )}
<div className="view-options text-center"> <div className="view-options text-center">
<ViewSelector onSelectView={selectView} active={View} message={message}/> <ViewSelector onSelectView={selectView} active={View} message={message}/>
@ -73,6 +72,7 @@ export default connect(
state => ({ state => ({
contentView: state.ui.flow.contentView, contentView: state.ui.flow.contentView,
displayLarge: state.ui.flow.displayLarge, displayLarge: state.ui.flow.displayLarge,
lastFileUpload: state.ui.flow.lastFileUpload
}), }),
{ {
selectView: setContentView, selectView: setContentView,

View File

@ -46,10 +46,14 @@ export default class ContentLoader extends Component {
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps(nextProps) {
if (nextProps.message !== this.props.message) { let reload = nextProps.message !== this.props.message || nextProps.lastFileUpload !== this.props.lastFileUpload
let isUserEdit = !nextProps.readonly && nextProps.message.content
if (isUserEdit)
this.setState({content: nextProps.message.content})
else if(reload)
this.requestContent(nextProps) this.requestContent(nextProps)
} }
}
componentWillUnmount() { componentWillUnmount() {
if (this.state.request) { if (this.state.request) {

View File

@ -60,10 +60,10 @@ ViewAuto.propTypes = {
flow: React.PropTypes.object.isRequired, flow: React.PropTypes.object.isRequired,
} }
export function ViewAuto({ message, flow, readonly }) { export function ViewAuto({ message, flow, readonly, lastFileUpload }) {
const View = ViewAuto.findView(message) const View = ViewAuto.findView(message)
if (View.textView) { if (View.textView) {
return <ContentLoader message={message} flow={flow}><View readonly={readonly} content="" /></ContentLoader> return <ContentLoader message={message} lastFileUpload={lastFileUpload} flow={flow}><View readonly={readonly} content="" /></ContentLoader>
} else { } else {
return <View readonly={readonly} message={message} flow={flow} /> return <View readonly={readonly} message={message} flow={flow} />
} }

View File

@ -68,7 +68,7 @@ function ResponseLine({ flow, readonly, updateFlow }) {
const Message = connect( const Message = connect(
state => ({ state => ({
flow: state.flows.byId[state.flows.selected[0]], flow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]],
isEdit: !!state.ui.flow.modifiedFlow, isEdit: !!state.ui.flow.modifiedFlow,
}), }),
{ {

View File

@ -10,11 +10,11 @@ ToggleEdit.propTypes = {
stopEdit: PropTypes.func.isRequired, stopEdit: PropTypes.func.isRequired,
} }
function ToggleEdit({ isEdit, startEdit, stopEdit, flow, old_flow }) { function ToggleEdit({ isEdit, startEdit, stopEdit, flow, modifiedFlow }) {
return ( return (
<div className="edit-flow-container"> <div className="edit-flow-container">
{isEdit ? {isEdit ?
<a className="edit-flow" onClick={() => stopEdit(flow, old_flow)}> <a className="edit-flow" onClick={() => stopEdit(flow, modifiedFlow)}>
<i className="fa fa-check"/> <i className="fa fa-check"/>
</a> </a>
: :
@ -29,8 +29,8 @@ function ToggleEdit({ isEdit, startEdit, stopEdit, flow, old_flow }) {
export default connect( export default connect(
state => ({ state => ({
isEdit: !!state.ui.flow.modifiedFlow, isEdit: !!state.ui.flow.modifiedFlow,
flow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]], modifiedFlow: state.ui.flow.modifiedFlow || state.flows.byId[state.flows.selected[0]],
old_flow: state.flows.byId[state.flows.selected[0]] flow: state.flows.byId[state.flows.selected[0]]
}), }),
{ {
startEdit, startEdit,

View File

@ -3,24 +3,19 @@ import { render } from 'react-dom';
import Codemirror from 'react-codemirror'; import Codemirror from 'react-codemirror';
export default class CodeEditor extends Component{ CodeEditor.propTypes = {
static propTypes = {
content: PropTypes.string.isRequired, content: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
} }
constructor(props){ export default function CodeEditor ( { content, onChange} ){
super(props)
}
render() {
let options = { let options = {
lineNumbers: true lineNumbers: true
}; };
return ( return (
<div onKeyDown={e => e.stopPropagation()}> <div onKeyDown={e => e.stopPropagation()}>
<Codemirror value={this.props.content} onChange={this.props.onChange} options={options}/> <Codemirror value={content} onChange={onChange} options={options}/>
</div> </div>
) )
} }
}

View File

@ -1,4 +1,6 @@
import * as flowsActions from '../flows' import * as flowsActions from '../flows'
import { getDiff } from "../../utils"
import _ from 'lodash' import _ from 'lodash'
export const SET_CONTENT_VIEW = 'UI_FLOWVIEW_SET_CONTENT_VIEW', export const SET_CONTENT_VIEW = 'UI_FLOWVIEW_SET_CONTENT_VIEW',
@ -6,13 +8,15 @@ export const SET_CONTENT_VIEW = 'UI_FLOWVIEW_SET_CONTENT_VIEW',
SET_TAB = "UI_FLOWVIEW_SET_TAB", SET_TAB = "UI_FLOWVIEW_SET_TAB",
START_EDIT = 'UI_FLOWVIEW_START_EDIT', START_EDIT = 'UI_FLOWVIEW_START_EDIT',
UPDATE_EDIT = 'UI_FLOWVIEW_UPDATE_EDIT', UPDATE_EDIT = 'UI_FLOWVIEW_UPDATE_EDIT',
STOP_EDIT = 'UI_FLOWVIEW_STOP_EDIT' STOP_EDIT = 'UI_FLOWVIEW_STOP_EDIT',
UPLOAD_CONTENT = 'UI_FLOWVIEW_UPLOAD_CONTENT'
const defaultState = { const defaultState = {
displayLarge: false, displayLarge: false,
modifiedFlow: false, modifiedFlow: false,
contentView: 'ViewAuto', contentView: 'ViewAuto',
lastFileUpload: false,
tab: 'request', tab: 'request',
} }
@ -38,6 +42,12 @@ export default function reducer(state = defaultState, action) {
modifiedFlow: false modifiedFlow: false
} }
case UPLOAD_CONTENT:
return {
... state,
lastFileUpload: new Date()
}
case flowsActions.SELECT: case flowsActions.SELECT:
return { return {
...state, ...state,
@ -90,30 +100,25 @@ export function updateEdit(update) {
export function uploadContent(flow, content, type){ export function uploadContent(flow, content, type){
return (dispatch) => { return (dispatch) => {
dispatch(flowsActions.updateContent(flow, content, type)).then( () => { dispatch(flowsActions.updateContent(flow, content, type))
dispatch(flowsActions.updateFlow(flow)) dispatch({ type: UPLOAD_CONTENT })
dispatch({ type: STOP_EDIT })
})
} }
} }
export function stopEdit(modified_flow, old_flow) { export function stopEdit(flow, modified_flow) {
//make diff of modified_flow and old_flow let diff = getDiff(flow, modified_flow)
return (dispatch) => { return (dispatch) => {
let flow = {...modified_flow} if (diff.response && diff.response.content) {
dispatch(flowsActions.updateContent(flow, diff.response.content, "response"))
if (flow.response.content) { delete diff.response.content
dispatch(flowsActions.updateContent(flow, flow.response.content, "response"))
flow.response = _.omit(flow.response, "content")
} }
if (flow.request.content) { if (diff.request && diff.request.content) {
dispatch(flowsActions.updateContent(flow, flow.request.content, "request")) dispatch(flowsActions.updateContent(flow, diff.request.content, "request"))
flow.request = _.omit(flow.request, "content") delete diff.request.content
} }
dispatch(flowsActions.update(flow, diff)).then(() => {
dispatch(flowsActions.update(flow)).then(() => { dispatch(flowsActions.updateFlow(modified_flow))
dispatch(flowsActions.updateFlow(flow))
dispatch({ type: STOP_EDIT }) dispatch({ type: STOP_EDIT })
}) })
} }

View File

@ -105,3 +105,17 @@ fetchApi.put = (url, json, options) => fetchApi(
...options ...options
} }
) )
export function getDiff(obj1, obj2) {
let result = {...obj2};
_.forIn(obj1, (value, key) => {
if(_.isEqual(obj2[key], obj1[key]))
result[key] = undefined;
else if(typeof Array.isArray(obj2[key]) && Array.isArray(obj2[key]))
result[key] = {...obj2[key]};
else if(typeof obj2[key] == 'object' && typeof obj1[key] == 'object')
result[key] = getDiff(obj1[key], obj2[key]);
});
return result;
}