Skip to content

Commit

Permalink
Import-Export States to your DevTools
Browse files Browse the repository at this point in the history
  • Loading branch information
pabloalonso committed Sep 18, 2015
1 parent fc839a0 commit da5e376
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 3 deletions.
30 changes: 29 additions & 1 deletion src/devTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const ActionTypes = {
RESET: 'RESET',
ROLLBACK: 'ROLLBACK',
COMMIT: 'COMMIT',
EXPORT: 'EXPORT',
IMPORT: 'IMPORT',
SWEEP: 'SWEEP',
TOGGLE_ACTION: 'TOGGLE_ACTION',
JUMP_TO_STATE: 'JUMP_TO_STATE',
Expand Down Expand Up @@ -86,7 +88,8 @@ function liftReducer(reducer, initialState) {
skippedActions: {},
currentStateIndex: 0,
monitorState: {
isVisible: true
isVisible: true,
exportMode: false
},
timestamps: [Date.now()]
};
Expand Down Expand Up @@ -120,6 +123,25 @@ function liftReducer(reducer, initialState) {
currentStateIndex = 0;
timestamps = [liftedAction.timestamp];
break;
case ActionTypes.EXPORT:
monitorState = Object.assign(
{},
monitorState,
{ exportMode: !monitorState.exportMode }
);
break;
case ActionTypes.IMPORT:
(
{
stagedActions,
skippedActions,
computedStates,
currentStateIndex,
monitorState,
timestamps
} = liftedAction.newState
);
break;
case ActionTypes.ROLLBACK:
stagedActions = [INIT_ACTION];
skippedActions = {};
Expand Down Expand Up @@ -235,6 +257,12 @@ export const ActionCreators = {
commit() {
return { type: ActionTypes.COMMIT, timestamp: Date.now() };
},
export() {
return { type: ActionTypes.EXPORT };
},
import(newState) {
return { type: ActionTypes.IMPORT, newState };
},
sweep() {
return { type: ActionTypes.SWEEP };
},
Expand Down
18 changes: 16 additions & 2 deletions src/react/LogMonitor.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import React, { PropTypes, findDOMNode, Component } from 'react';
import LogMonitorEntry from './LogMonitorEntry';
import LogMonitorButton from './LogMonitorButton';
import LogMonitorTextarea from './LogMonitorTextarea';
import * as themes from './themes';

const EXPORT_CONTAINER_HEIGHT = 150;
const ELEMENTS_CONTAINER_TOP = 38;

const styles = {
container: {
fontFamily: 'monaco, Consolas, Lucida Console, monospace',
Expand All @@ -25,7 +29,7 @@ const styles = {
position: 'absolute',
left: 0,
right: 0,
top: 38,
top: ELEMENTS_CONTAINER_TOP,
bottom: 0,
overflowX: 'hidden',
overflowY: 'auto'
Expand Down Expand Up @@ -114,6 +118,14 @@ export default class LogMonitor extends Component {
this.props.commit();
}

handleExport() {
this.props.export();
}

handleImport(newState) {
this.props.import(newState);
}

handleToggleAction(index) {
this.props.toggleAction(index);
}
Expand Down Expand Up @@ -180,8 +192,10 @@ export default class LogMonitor extends Component {
<LogMonitorButton theme={theme} onClick={::this.handleRollback} enabled={computedStates.length}>Revert</LogMonitorButton>
<LogMonitorButton theme={theme} onClick={::this.handleSweep} enabled={Object.keys(skippedActions).some(key => skippedActions[key])}>Sweep</LogMonitorButton>
<LogMonitorButton theme={theme} onClick={::this.handleCommit} enabled={computedStates.length > 1}>Commit</LogMonitorButton>
<LogMonitorButton theme={theme} onClick={::this.handleExport} enabled={computedStates.length}>Export</LogMonitorButton>
</div>
<div style={styles.elements} ref="elements">
<LogMonitorTextarea theme={theme} handleImport={::this.handleImport} currentState={this.props.store.getState()} />
<div style={{...styles.elements, top: monitorState.exportMode ? EXPORT_CONTAINER_HEIGHT : ELEMENTS_CONTAINER_TOP }} ref="elements">
{elements}
</div>
</div>
Expand Down
42 changes: 42 additions & 0 deletions src/react/LogMonitorTextarea.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { PropTypes, findDOMNode, Component } from 'react';

const EXPORT_CONTAINER_HEIGHT = 150;
const ELEMENTS_CONTAINER_TOP = 38;

var styles = {
exportContainer: {
width: '100%',
height: EXPORT_CONTAINER_HEIGHT
},
exportArea: {
position: 'relative',
resize: 'none',
width: '100%',
height: 112,
backgroundColor: '#4F5A66',
color: 'white'
}
};

export default class LogMonitorTextarea extends Component {
constructor(props) {
super(props);
}

parseInput(event) {
try {
this.props.handleImport(JSON.parse(event.target.value))
} catch(err) {
console.warn('There was an error parsing the new state. Please enter a valid schema.');
}
}

render() {
let { handleImport, currentState, theme } = this.props;
return currentState.monitorState.exportMode ? (
<div style={{...styles.exportContainer, backgroundColor: theme.base00}}>
<textarea style={styles.exportArea} value={JSON.stringify(currentState)} onChange={::this.parseInput} />
</div>
) : null;
}
}

0 comments on commit da5e376

Please sign in to comment.