diff --git a/package.json b/package.json index 1c283d1c..11643109 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "redux": "^2.0.0" }, "dependencies": { + "react-dock": "0.0.2", "react-json-tree": "^0.1.8", "react-mixin": "^1.7.0", "react-redux": "^2.0.0", diff --git a/src/createDevTools.js b/src/createDevTools.js index b5eecadd..e1849699 100644 --- a/src/createDevTools.js +++ b/src/createDevTools.js @@ -1,5 +1,6 @@ import createAll from 'react-redux/lib/components/createAll'; import { ActionCreators } from './devTools'; +import DebugPanel from './react/DebugPanel'; export default function createDevTools(React) { const { PropTypes, Component } = React; @@ -11,8 +12,13 @@ export default function createDevTools(React) { ) class DevTools extends Component { render() { - const { monitor: Monitor } = this.props; - return ; + const { monitor: Monitor, panelState, setPanelState, + visibleOnLoad, position, ...props } = this.props; + return ( + + + + ); } } @@ -37,9 +43,9 @@ export default function createDevTools(React) { } render() { + const { store: { devToolsStore }, ...props } = this.props; return ( - + ); } }; diff --git a/src/devTools.js b/src/devTools.js index f57e9bc1..471de44e 100644 --- a/src/devTools.js +++ b/src/devTools.js @@ -6,7 +6,7 @@ const ActionTypes = { SWEEP: 'SWEEP', TOGGLE_ACTION: 'TOGGLE_ACTION', JUMP_TO_STATE: 'JUMP_TO_STATE', - SET_MONITOR_STATE: 'SET_MONITOR_STATE', + SET_PANEL_STATE: 'SET_PANEL_STATE', RECOMPUTE_STATES: 'RECOMPUTE_STATES' }; @@ -85,7 +85,8 @@ function liftReducer(reducer, initialState) { stagedActions: [INIT_ACTION], skippedActions: {}, currentStateIndex: 0, - monitorState: { + panelState: { + position: 'right', isVisible: true }, timestamps: [Date.now()] @@ -101,7 +102,7 @@ function liftReducer(reducer, initialState) { skippedActions, computedStates, currentStateIndex, - monitorState, + panelState, timestamps } = liftedState; @@ -145,8 +146,8 @@ function liftReducer(reducer, initialState) { stagedActions = [...stagedActions, liftedAction.action]; timestamps = [...timestamps, liftedAction.timestamp]; break; - case ActionTypes.SET_MONITOR_STATE: - monitorState = liftedAction.monitorState; + case ActionTypes.SET_PANEL_STATE: + panelState = liftedAction.panelState; break; case ActionTypes.RECOMPUTE_STATES: stagedActions = liftedAction.stagedActions; @@ -172,7 +173,7 @@ function liftReducer(reducer, initialState) { skippedActions, computedStates, currentStateIndex, - monitorState, + panelState, timestamps }; }; @@ -244,8 +245,8 @@ export const ActionCreators = { jumpToState(index) { return { type: ActionTypes.JUMP_TO_STATE, index }; }, - setMonitorState(monitorState) { - return { type: ActionTypes.SET_MONITOR_STATE, monitorState }; + setPanelState(panelState) { + return { type: ActionTypes.SET_PANEL_STATE, panelState }; }, recomputeStates(committedState, stagedActions) { return { diff --git a/src/react/DebugPanel.js b/src/react/DebugPanel.js index d58dc3b4..bc0aff38 100644 --- a/src/react/DebugPanel.js +++ b/src/react/DebugPanel.js @@ -1,51 +1,71 @@ import React, { PropTypes, Component } from 'react'; +import Dock from 'react-dock'; -export function getDefaultStyle(props) { - let { left, right, bottom, top } = props; - if (typeof left === 'undefined' && typeof right === 'undefined') { - right = true; - } - if (typeof top === 'undefined' && typeof bottom === 'undefined') { - bottom = true; - } - - return { - position: 'fixed', - zIndex: 10000, - fontSize: 17, - overflow: 'hidden', - opacity: 1, - color: 'white', - left: left ? 0 : undefined, - right: right ? 0 : undefined, - top: top ? 0 : undefined, - bottom: bottom ? 0 : undefined, - maxHeight: (bottom && top) ? '100%' : '30%', - maxWidth: (left && right) ? '100%' : '30%', - wordWrap: 'break-word', - boxSizing: 'border-box', - boxShadow: '-2px 0 7px 0 rgba(0, 0, 0, 0.5)' - }; -} +const POSITIONS = ['left', 'top', 'right', 'bottom']; export default class DebugPanel extends Component { static propTypes = { - left: PropTypes.bool, - right: PropTypes.bool, - bottom: PropTypes.bool, - top: PropTypes.bool, getStyle: PropTypes.func.isRequired }; static defaultProps = { - getStyle: getDefaultStyle + getStyle: () => ({}), + panelState: { + position: 'right', + isVisible: true + }, + visibleOnLoad: true, + position: 'right', + dimMode: 'none' }; + componentWillMount() { + const { panelState, visibleOnLoad, position } = this.props; + + this.props.setPanelState({ + ...panelState, + isVisible: visibleOnLoad, + position: position + }); + } + + componentDidMount() { + if (typeof window !== 'undefined') { + window.addEventListener('keydown', this.handleKeyPress); + } + } + + componentWillUnmount() { + if (typeof window !== 'undefined') { + window.removeEventListener('keydown', this.handleKeyPress); + } + } + render() { + const { getStyle, dimMode, panelState: { position, isVisible } } = this.props; return ( -
+ {this.props.children} -
+ ); } + + handleKeyPress = event => { + const { panelState } = this.props; + if (event.ctrlKey && event.keyCode === 72) { // Ctrl+H + event.preventDefault(); + this.props.setPanelState({ + ...panelState, + isVisible: !panelState.isVisible + }); + } else if (event.ctrlKey && event.keyCode === 68) { // Ctrl+D + event.preventDefault(); + const positionIdx = POSITIONS.indexOf(panelState.position); + this.props.setPanelState({ + ...panelState, + position: POSITIONS[(positionIdx + 1) % POSITIONS.length] + }); + } + } } diff --git a/src/react/LogMonitor.js b/src/react/LogMonitor.js index d960f460..17b818e2 100644 --- a/src/react/LogMonitor.js +++ b/src/react/LogMonitor.js @@ -33,17 +33,9 @@ const styles = { }; export default class LogMonitor extends Component { - constructor(props) { - super(props); - if (typeof window !== 'undefined') { - window.addEventListener('keydown', ::this.handleKeyPress); - } - } - static propTypes = { computedStates: PropTypes.array.isRequired, currentStateIndex: PropTypes.number.isRequired, - monitorState: PropTypes.object.isRequired, stagedActions: PropTypes.array.isRequired, skippedActions: PropTypes.object.isRequired, reset: PropTypes.func.isRequired, @@ -52,16 +44,12 @@ export default class LogMonitor extends Component { sweep: PropTypes.func.isRequired, toggleAction: PropTypes.func.isRequired, jumpToState: PropTypes.func.isRequired, - setMonitorState: PropTypes.func.isRequired, - select: PropTypes.func.isRequired, - visibleOnLoad: PropTypes.bool + select: PropTypes.func.isRequired }; static defaultProps = { select: (state) => state, - monitorState: { isVisible: true }, - theme: 'nicinabox', - visibleOnLoad: true + theme: 'nicinabox' }; componentWillReceiveProps(nextProps) { @@ -93,15 +81,6 @@ export default class LogMonitor extends Component { } } - componentWillMount() { - let visibleOnLoad = this.props.visibleOnLoad; - const { monitorState } = this.props; - this.props.setMonitorState({ - ...monitorState, - isVisible: visibleOnLoad - }); - } - handleRollback() { this.props.rollback(); } @@ -122,21 +101,9 @@ export default class LogMonitor extends Component { this.props.reset(); } - handleKeyPress(event) { - const { monitorState } = this.props; - - if (event.ctrlKey && event.keyCode === 72) { // Ctrl+H - event.preventDefault(); - this.props.setMonitorState({ - ...monitorState, - isVisible: !monitorState.isVisible - }); - } - } - render() { const elements = []; - const { monitorState, skippedActions, stagedActions, computedStates, select } = this.props; + const { skippedActions, stagedActions, computedStates, select } = this.props; let theme; if (typeof this.props.theme === 'string') { if (typeof themes[this.props.theme] !== 'undefined') { @@ -148,10 +115,6 @@ export default class LogMonitor extends Component { } else { theme = this.props.theme; } - if (!monitorState.isVisible) { - return null; - } - for (let i = 0; i < stagedActions.length; i++) { const action = stagedActions[i]; const { state, error } = computedStates[i]; diff --git a/src/react/index.js b/src/react/index.js index cce0e96d..d3e831d2 100644 --- a/src/react/index.js +++ b/src/react/index.js @@ -3,4 +3,3 @@ import createDevTools from '../createDevTools'; export const DevTools = createDevTools(React); export { default as LogMonitor } from './LogMonitor'; -export { default as DebugPanel } from './DebugPanel';