diff --git a/packages/xod-client-browser/test-func/copy-save.spec.js b/packages/xod-client-browser/test-func/copy-save.spec.js index 7b8b35d95..ade9f9ece 100644 --- a/packages/xod-client-browser/test-func/copy-save.spec.js +++ b/packages/xod-client-browser/test-func/copy-save.spec.js @@ -1,4 +1,4 @@ -/* global browser:false, assert:false, navigator:false */ +/* global browser:false, assert:false, navigator:false, localStorage: false */ import { tmpdir } from 'os'; import { promises as fs } from 'fs'; import { resolve } from 'path'; @@ -9,16 +9,26 @@ import getPage from './utils/getPage'; import Debugger from './pageObjects/Debugger'; describe('copy & save log', () => { + beforeEach(async () => { + const page = await getPage(browser); + // We have to clear the localStorage to ensure that the deployment + // pane will be in a default initial state + await page.evaluate(() => localStorage.clear()); + }); const openIdeAndDeploymentPane = async browser => { const page = await getPage(browser); - const debugPanel = await Debugger.findOnPage(page); - + // TODO: Replace with `const` and do not find the DOM elment on the page + // after opening it, when rerendering of the element will be fixed + let debugPanel = await Debugger.findOnPage(page); // Open debugger assert.isTrue( await debugPanel.isCollapsed(), 'debugger panel is collapsed by default' ); + await debugPanel.click(); + debugPanel = await Debugger.findOnPage(page); // TODO + assert.isTrue( await debugPanel.isOpened(), 'debugger panel is opened by click' diff --git a/packages/xod-client/package.json b/packages/xod-client/package.json index 303a07b31..f31318551 100644 --- a/packages/xod-client/package.json +++ b/packages/xod-client/package.json @@ -47,7 +47,7 @@ "react-highlight-words": "^0.8.1", "react-hotkeys": "^1.1.4", "react-redux": "^4.0.6", - "react-reflex": "^2.2.7", + "react-reflex": "^2.2.9", "react-remarkable": "^1.1.3", "react-resize-detector": "^1.1.0", "react-skylight": "git+/~https://github.com/xodio/react-skylight.git#6dc266edc5198d0d1a6feb57f329826e782ec967", diff --git a/packages/xod-client/src/core/containers/App.jsx b/packages/xod-client/src/core/containers/App.jsx index ce879ba2c..c8c0d8a50 100644 --- a/packages/xod-client/src/core/containers/App.jsx +++ b/packages/xod-client/src/core/containers/App.jsx @@ -59,6 +59,7 @@ import { USERNAME_NEEDED_FOR_LITERAL } from '../../user/messages'; import { PROJECT_NAME_NEEDED_FOR_LITERAL } from '../../project/messages'; import { DO_NOT_USE_TETHERING_INTERNET_IN_BROWSER } from '../../debugger/messages'; import { COMMAND } from '../../utils/constants'; +import { PANEL_IDS } from '../../editor/constants'; import formatErrorMessage from '../formatErrorMessage'; @@ -438,7 +439,7 @@ App.actions = { startDebuggerSession: actions.startDebuggerSession, startSerialSession: actions.startSerialSession, stopDebuggerSession: actions.stopDebuggerSession, - toggleDebugger: actions.toggleDebugger, + toggleDebugger: () => actions.togglePanel(PANEL_IDS.DEPLOYMENT), logDebugger: actions.addMessagesToDebuggerLog, clearDebugger: actions.clearDebuggerLog, cutEntities: actions.cutEntities, diff --git a/packages/xod-client/src/core/styles/components/Debugger.scss b/packages/xod-client/src/core/styles/components/Debugger.scss index 88e8a8d03..87185c21d 100644 --- a/packages/xod-client/src/core/styles/components/Debugger.scss +++ b/packages/xod-client/src/core/styles/components/Debugger.scss @@ -10,16 +10,20 @@ } .Debugger { + display: flex; + flex: 1; + flex-direction: column; + bottom: 0; - height: 220px; width: 100%; - border-top: 2px solid $chrome-outlines; + border-top: 0; box-sizing: border-box; color: $sidebar-color-text; &.isCollapsed { height: 24px; + border-top: 2px solid $chrome-outlines; } .titlebar { @@ -171,7 +175,9 @@ } .container { - display: block; + display: flex; + flex-direction: column; + flex: 1; position: relative; height: 165px; @@ -180,7 +186,8 @@ } .log { - height: 161px; + flex: 1; + // height: 161px; overflow-y: scroll; white-space: pre-wrap; @@ -220,8 +227,6 @@ } &.compact { - height: 143px; - .skipped { bottom: 24px; padding: 0 28px 7px; @@ -230,6 +235,7 @@ } .SerialInput { + display: block; position: relative; input { diff --git a/packages/xod-client/src/core/styles/components/Workarea.scss b/packages/xod-client/src/core/styles/components/Workarea.scss index aa38ad310..374fffc36 100644 --- a/packages/xod-client/src/core/styles/components/Workarea.scss +++ b/packages/xod-client/src/core/styles/components/Workarea.scss @@ -4,6 +4,20 @@ flex-direction: column; flex-grow: 1; max-width: 100%; + + & > .reflex-layout > .reflex-element > div { + flex-direction: column; + } + + .Deployment-pane { + min-height: 24px; + } +} + +.Workarea-content { + &.isCollapsed .reflex-splitter { + display: none; + } } .Workarea-inner { diff --git a/packages/xod-client/src/debugger/actionTypes.js b/packages/xod-client/src/debugger/actionTypes.js index dfdf558dc..1eaf1a77a 100644 --- a/packages/xod-client/src/debugger/actionTypes.js +++ b/packages/xod-client/src/debugger/actionTypes.js @@ -3,8 +3,6 @@ export const INSTALL_ARDUINO_DEPENDENCIES = 'INSTALL_ARDUINO_DEPENDENCIES'; export const CHECK_ARDUINO_DEPENDENCIES = 'CHECK_ARDUINO_DEPENDENCIES'; export const UPGRADE_ARDUINO_DEPENDECIES = 'UPGRADE_ARDUINO_DEPENDECIES'; -export const TOGGLE_DEBUGGER_PANEL = 'TOGGLE_DEBUGGER_PANEL'; - export const SELECT_DEBUGGER_TAB = 'SELECT_DEBUGGER_TAB'; export const DEBUGGER_LOG_ADD_MESSAGES = 'DEBUGGER_LOG_ADD_MESSAGES'; diff --git a/packages/xod-client/src/debugger/actions.js b/packages/xod-client/src/debugger/actions.js index a755707c7..d259a2b75 100644 --- a/packages/xod-client/src/debugger/actions.js +++ b/packages/xod-client/src/debugger/actions.js @@ -3,10 +3,6 @@ import { maybeProp } from 'xod-func-tools'; import * as AT from './actionTypes'; import { tetheringInetChunksToSend } from './selectors'; -export const toggleDebugger = () => ({ - type: AT.TOGGLE_DEBUGGER_PANEL, -}); - export const addMessagesToDebuggerLog = messages => ({ type: AT.DEBUGGER_LOG_ADD_MESSAGES, payload: messages, diff --git a/packages/xod-client/src/debugger/containers/Debugger.jsx b/packages/xod-client/src/debugger/containers/Debugger.jsx index c30b5939c..2e3f1edb7 100644 --- a/packages/xod-client/src/debugger/containers/Debugger.jsx +++ b/packages/xod-client/src/debugger/containers/Debugger.jsx @@ -10,6 +10,7 @@ import { foldMaybe } from 'xod-func-tools'; import { Maybe } from 'ramda-fantasy'; import { LOG_TAB_TYPE } from '../constants'; +import { PANEL_IDS } from '../../editor/constants'; import * as selectors from '../selectors'; import { addError, addConfirmation } from '../../messages/actions'; import * as DA from '../actions'; @@ -51,7 +52,7 @@ const TAB_ORDER = [ LOG_TAB_TYPE.TESTER, ]; -class Debugger extends React.Component { +class Debugger extends React.PureComponent { constructor(props) { super(props); @@ -196,6 +197,7 @@ class Debugger extends React.Component { isConnectedToSerial, stopDebuggerSession, currentTab, + isResizing, } = this.props; const uploadProgress = foldMaybe( @@ -216,7 +218,6 @@ class Debugger extends React.Component { ); const isDebuggerTab = currentTab === LOG_TAB_TYPE.DEBUGGER; - return (
@@ -301,7 +302,7 @@ class Debugger extends React.Component { {this.renderTabSelector()}
- + {isDebuggerTab ? ( + EditorActions.togglePanel(PANEL_IDS.DEPLOYMENT); + const mapDispatchToProps = dispatch => ({ actions: bindActionCreators( { - toggleDebugger: DA.toggleDebugger, + toggleDebugger: toggleDeploymentPane, sendToSerial: DA.sendToSerial, toggleCapturingDebuggerProtocolMessages: DA.toggleCapturingDebuggerProtocolMessages, diff --git a/packages/xod-client/src/debugger/containers/Log.jsx b/packages/xod-client/src/debugger/containers/Log.jsx index 145b831b9..9df3f7240 100644 --- a/packages/xod-client/src/debugger/containers/Log.jsx +++ b/packages/xod-client/src/debugger/containers/Log.jsx @@ -52,6 +52,7 @@ class Log extends React.PureComponent { const { log, error, + doNotSkipLines, isSkippingNewSerialLogLines, numberOfSkippedSerialLogLines, isSkipOnScrollEnabled, @@ -64,7 +65,9 @@ class Log extends React.PureComponent { className={cn('log', { compact })} ref={el => (this.autoscrollRef = el)} onScrolledFromBottom={ - isSkipOnScrollEnabled ? startSkippingNewLogLines : noop + isSkipOnScrollEnabled && !doNotSkipLines + ? startSkippingNewLogLines + : noop } > {log} @@ -81,7 +84,12 @@ class Log extends React.PureComponent { } } +Log.defaultProps = { + doNotSkipLines: false, +}; + Log.propTypes = { + doNotSkipLines: PropTypes.bool.isRequired, log: PropTypes.string.isRequired, error: PropTypes.string.isRequired, isSkippingNewSerialLogLines: PropTypes.bool.isRequired, diff --git a/packages/xod-client/src/debugger/reducer.js b/packages/xod-client/src/debugger/reducer.js index ed4b2d755..f99d977cc 100644 --- a/packages/xod-client/src/debugger/reducer.js +++ b/packages/xod-client/src/debugger/reducer.js @@ -8,7 +8,6 @@ import { INSTALL_ARDUINO_DEPENDENCIES, CHECK_ARDUINO_DEPENDENCIES, UPGRADE_ARDUINO_DEPENDECIES, - TOGGLE_DEBUGGER_PANEL, DEBUGGER_LOG_ADD_MESSAGES, DEBUGGER_LOG_CLEAR, DEBUGGER_LOG_START_SKIPPING_NEW_LINES, @@ -38,6 +37,7 @@ import { createFlasherMessage, createErrorMessage, createOutgoingLogMessage, + isErrorMessage, } from './utils'; import { default as initialState, DEFAULT_TETHERING_INET_STATE } from './state'; @@ -177,8 +177,6 @@ const updateInteractiveErroredNodePins = R.curry((messageList, state) => { ); }); -const showDebuggerPane = R.assoc('isVisible', true); - const hideProgressBar = R.assoc('uploadProgress', null); const getMessageFromErrResponce = R.compose( @@ -284,7 +282,6 @@ export default (state = initialState, action) => { if (status === STATUS.STARTED) { return R.compose( - type === CHECK_ARDUINO_DEPENDENCIES ? R.identity : showDebuggerPane, R.assoc('currentTab', LOG_TAB_TYPE.INSTALLER), R.assoc('currentStage', LOG_TAB_TYPE.INSTALLER), R.assoc('uploadProgress', 0), @@ -333,8 +330,7 @@ export default (state = initialState, action) => { hideProgressBar, overStageError(state.currentStage)( appendMessage(createErrorMessage(payload.message)) - ), - showDebuggerPane + ) )(state); } @@ -387,15 +383,12 @@ export default (state = initialState, action) => { hideProgressBar, overStageError(state.currentStage)( appendMessage(createErrorMessage(payload.message)) - ), - showDebuggerPane + ) )(state); } return state; } - case TOGGLE_DEBUGGER_PANEL: - return R.over(R.lensProp('isVisible'), R.not, state); case DEBUGGER_LOG_START_SKIPPING_NEW_LINES: return R.assoc('isSkippingNewSerialLogLines', true, state); case DEBUGGER_LOG_STOP_SKIPPING_NEW_LINES: @@ -422,16 +415,12 @@ export default (state = initialState, action) => { const allMessages = action.payload; const [errorMessages, logMessages] = R.compose( - R.partition(R.propEq('type', UPLOAD_MSG_TYPE.ERROR)), + R.partition(isErrorMessage), state.isCapturingDebuggerProtocolMessages ? R.identity : R.reject(R.propEq('type', UPLOAD_MSG_TYPE.XOD)) )(allMessages); - const showPanelOnErrorMessages = R.isEmpty(errorMessages) - ? R.identity - : showDebuggerPane; - const addErrorMessage = R.isEmpty(errorMessages) ? R.identity : overStageError(state.currentStage)( @@ -439,7 +428,6 @@ export default (state = initialState, action) => { ); return R.compose( - showPanelOnErrorMessages, addErrorMessage, addMessagesOrIncrementSkippedLines(logMessages), updateInteractiveErroredNodePins(allMessages), @@ -482,8 +470,7 @@ export default (state = initialState, action) => { ), R.assoc('activeSession', SESSION_TYPE.DEBUG), R.assoc('isOutdated', false), - R.assoc('globals', action.payload.globals), - showDebuggerPane + R.assoc('globals', action.payload.globals) )(state); } case SERIAL_SESSION_STARTED: @@ -496,8 +483,7 @@ export default (state = initialState, action) => { R.assoc('isSkippingNewSerialLogLines', false), R.assoc('numberOfSkippedSerialLogLines', 0), R.assoc('activeSession', SESSION_TYPE.SERIAL), - R.assoc('isOutdated', false), - showDebuggerPane + R.assoc('isOutdated', false) )(state); case DEBUG_SESSION_STOPPED: return R.compose( @@ -573,8 +559,7 @@ export default (state = initialState, action) => { overStageError(LOG_TAB_TYPE.TESTER)( R.always(formatWasmError(action.payload)) ), - hideProgressBar, - showDebuggerPane + hideProgressBar )(state); case EAT.SIMULATION_RUN_REQUESTED: @@ -633,8 +618,7 @@ export default (state = initialState, action) => { R.assoc('isPreparingSimulation', false), R.assoc('globals', {}), R.assoc('tetheringInet', DEFAULT_TETHERING_INET_STATE), - hideProgressBar, - showDebuggerPane + hideProgressBar )(state); default: diff --git a/packages/xod-client/src/debugger/selectors.js b/packages/xod-client/src/debugger/selectors.js index bd7965cf9..e7a74fa3a 100644 --- a/packages/xod-client/src/debugger/selectors.js +++ b/packages/xod-client/src/debugger/selectors.js @@ -52,11 +52,6 @@ export const isSimulationAbortable = R.either( isSimulationRunning ); -export const isDebuggerVisible = R.compose( - R.prop('isVisible'), - getDebuggerState -); - export const isDebugSessionOutdated = R.compose( R.prop('isOutdated'), getDebuggerState diff --git a/packages/xod-client/src/debugger/state.js b/packages/xod-client/src/debugger/state.js index 24ac018d4..36c57a93c 100644 --- a/packages/xod-client/src/debugger/state.js +++ b/packages/xod-client/src/debugger/state.js @@ -9,7 +9,6 @@ export const DEFAULT_TETHERING_INET_STATE = { }; export default { - isVisible: false, activeSession: SESSION_TYPE.NONE, isPreparingSimulation: false, isOutdated: false, diff --git a/packages/xod-client/src/debugger/utils.js b/packages/xod-client/src/debugger/utils.js index 9c45ec4c7..756dca344 100644 --- a/packages/xod-client/src/debugger/utils.js +++ b/packages/xod-client/src/debugger/utils.js @@ -36,3 +36,5 @@ export const getTetheringInetNodeId = R.curry( XP.getPatchByPath(patchPath) )(project) ); + +export const isErrorMessage = R.propEq('type', UPLOAD_MSG_TYPE.ERROR); diff --git a/packages/xod-client/src/editor/actions.js b/packages/xod-client/src/editor/actions.js index 44f170061..275e54c79 100644 --- a/packages/xod-client/src/editor/actions.js +++ b/packages/xod-client/src/editor/actions.js @@ -622,6 +622,7 @@ export const resizePanels = sizes => ({ type: ActionType.RESIZE_PANELS, payload: sizes, }); +export const resizePanel = (name, size) => resizePanels({ [name]: size }); export const minimizePanel = panelId => ({ type: ActionType.MINIMIZE_PANEL, payload: { diff --git a/packages/xod-client/src/editor/constants.js b/packages/xod-client/src/editor/constants.js index 00661cb45..6e093198d 100644 --- a/packages/xod-client/src/editor/constants.js +++ b/packages/xod-client/src/editor/constants.js @@ -73,11 +73,13 @@ export const PANEL_IDS = { INSPECTOR: 'INSPECTOR', HELPBAR: 'HELPBAR', ACCOUNT: 'ACCOUNT', + DEPLOYMENT: 'DEPLOYMENT', }; export const SIDEBAR_IDS = { LEFT: 'LEFT', RIGHT: 'RIGHT', + BOTTOM: 'BOTTOM', }; export const PANEL_CONTEXT_MENU_ID = 'PANEL_CONTEXT_MENU_ID'; diff --git a/packages/xod-client/src/editor/containers/Editor.jsx b/packages/xod-client/src/editor/containers/Editor.jsx index a534a1df0..1561c0485 100644 --- a/packages/xod-client/src/editor/containers/Editor.jsx +++ b/packages/xod-client/src/editor/containers/Editor.jsx @@ -3,7 +3,7 @@ import React from 'react'; import $ from 'sanctuary-def'; import PropTypes from 'prop-types'; import cn from 'classnames'; -import { $Maybe, explodeMaybe, foldMaybe } from 'xod-func-tools'; +import { $Maybe, explodeMaybe, foldMaybe, notEquals } from 'xod-func-tools'; import { DragDropContext } from 'react-dnd'; import HTML5Backend from 'react-dnd-html5-backend'; import { connect } from 'react-redux'; @@ -20,7 +20,7 @@ import * as EditorSelectors from '../selectors'; import { isInputTarget } from '../../utils/browser'; import sanctuaryPropType from '../../utils/sanctuaryPropType'; -import { FOCUS_AREAS, TAB_TYPES, SIDEBAR_IDS } from '../constants'; +import { FOCUS_AREAS, TAB_TYPES, SIDEBAR_IDS, PANEL_IDS } from '../constants'; import Patch from './Patch'; import CppImplementationEditor from '../components/CppImplementationEditor'; @@ -29,17 +29,22 @@ import NoPatch from '../components/NoPatch'; import Suggester from '../components/Suggester'; import PanelContextMenu from '../components/PanelContextMenu'; import LibSuggester from '../components/LibSuggester'; -import Debugger from '../../debugger/containers/Debugger'; import DebuggerTopPane from '../../debugger/containers/DebuggerTopPane'; import Sidebar from './Sidebar'; import SnackBar from '../../messages/containers/SnackBar'; import Helpbox from './Helpbox'; import Tooltip from '../../tooltip/components/Tooltip'; +import Workarea from './Workarea'; import Tabs from './Tabs'; import DragLayer from './DragLayer'; +const pickPropsToCheck = R.compose( + R.evolve({ panelSettings: R.map(R.omit(['size'])) }), + R.reject(R.is(Function)) +); + class Editor extends React.Component { constructor(props) { super(props); @@ -61,6 +66,10 @@ class Editor extends React.Component { ); } + shouldComponentUpdate(nextProps) { + return notEquals(pickPropsToCheck(nextProps), pickPropsToCheck(this.props)); + } + onAddNode(patchPath) { // TODO: rewrite this when implementing "zombie" nodes const position = @@ -264,17 +273,17 @@ class Editor extends React.Component { isDebugSessionOutdated={this.props.isDebugSessionOutdated} stopDebuggerSession={this.props.stopDebuggerSession} /> -
- {this.renderOpenedPatchTab()} - {this.renderOpenedAttachmentEditorTabs()} - -
- + windowSize={this.props.size} + > + {this.renderOpenedPatchTab()} + {this.renderOpenedAttachmentEditorTabs()} + + @@ -344,6 +353,7 @@ const mapStateToProps = R.applySpec({ isHelpboxVisible: EditorSelectors.isHelpboxVisible, isDebugSessionRunning: DebuggerSelectors.isDebugSession, isDebugSessionOutdated: DebuggerSelectors.isDebugSessionOutdated, + isDebugPanelExpanded: EditorSelectors.isPanelMaximized(PANEL_IDS.DEPLOYMENT), defaultNodePosition: EditorSelectors.getDefaultNodePlacePosition, isTabtestRunning: EditorSelectors.isTabtestRunning, panelsSettings: EditorSelectors.getAllPanelsSettings, diff --git a/packages/xod-client/src/editor/containers/Workarea.jsx b/packages/xod-client/src/editor/containers/Workarea.jsx new file mode 100644 index 000000000..ca9b88b36 --- /dev/null +++ b/packages/xod-client/src/editor/containers/Workarea.jsx @@ -0,0 +1,138 @@ +import * as R from 'ramda'; +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; +import cn from 'classnames'; +import debounce from 'throttle-debounce/debounce'; +import { notEquals } from 'xod-func-tools'; + +import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex'; +import Debugger from '../../debugger/containers/Debugger'; + +import { SLOT_SIZE } from '../../project/nodeLayout'; +import { PANEL_IDS } from '../constants'; +import * as Actions from '../actions'; +import * as EditorSelectors from '../selectors'; + +const pickPropsToCheck = R.compose( + R.evolve({ panelSettings: R.map(R.omit(['size'])) }), + R.pick(['children', 'panelSettings', 'windowSize']) +); + +class Workarea extends React.Component { + constructor(props) { + super(props); + + this.state = { + resizing: false, + sizes: { + WORKAREA: 1, + [PANEL_IDS.DEPLOYMENT]: props.panelSettings.size || 0, + }, + }; + + this.onResizePanel = this.onResizePanel.bind(this); + this.onStartResizePanel = this.onStartResizePanel.bind(this); + this.onStopResizePanel = this.onStopResizePanel.bind(this); + + this.resizePanelAction = debounce(300, this.props.actions.resizePanel); + } + shouldComponentUpdate(nextProps) { + // Optimize rendering + return notEquals(pickPropsToCheck(nextProps), pickPropsToCheck(this.props)); + } + onResizePanel(event) { + const { name, flex } = event.component.props; + this.setState(R.assocPath(['sizes', name], flex)); + this.resizePanelAction( + PANEL_IDS.DEPLOYMENT, + this.state.sizes[PANEL_IDS.DEPLOYMENT] + ); + } + onStartResizePanel() { + this.setState({ resizing: true }); + } + onStopResizePanel() { + this.setState({ resizing: false }); + } + getDeploymentPanelSize() { + const size = R.propOr(0.2, 'size', this.props.panelSettings); + return this.props.isDebugPanelExpanded ? size : 0; + } + render() { + return ( + + + {this.props.children} + + + + + + + ); + } +} + +Workarea.propTypes = { + // Props propagated from + children: PropTypes.node.isRequired, + // We need windowSize to re-render component on window resizing + // eslint-disable-next-line react/no-unused-prop-types + windowSize: PropTypes.object.isRequired, + // Props via connect + isDebugPanelExpanded: PropTypes.bool.isRequired, + panelSettings: PropTypes.object.isRequired, + // Actions propagated from + stopDebuggerSession: PropTypes.func.isRequired, + onUploadClick: PropTypes.func.isRequired, + onUploadAndDebugClick: PropTypes.func.isRequired, + onRunSimulationClick: PropTypes.func.isRequired, + // Actions binded with connect + actions: PropTypes.shape({ + resizePanel: PropTypes.func.isRequired, + }), +}; + +const mapStateToProps = R.applySpec({ + isDebugPanelExpanded: EditorSelectors.isPanelMaximized(PANEL_IDS.DEPLOYMENT), + panelSettings: EditorSelectors.getPanelSettings(PANEL_IDS.DEPLOYMENT), +}); + +const mapDispatchToProps = dispatch => ({ + actions: bindActionCreators( + { + resizePanel: Actions.resizePanel, + }, + dispatch + ), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(Workarea); diff --git a/packages/xod-client/src/editor/reducer.js b/packages/xod-client/src/editor/reducer.js index d8276ad14..40c5edb5c 100644 --- a/packages/xod-client/src/editor/reducer.js +++ b/packages/xod-client/src/editor/reducer.js @@ -16,6 +16,7 @@ import { TAB_TYPES, PANEL_IDS, } from './constants'; +import { STATUS } from '../utils/constants'; import { createSelectionEntity, getNewSelection, @@ -24,6 +25,7 @@ import { import { setCurrentPatchOffset, switchPatchUnsafe } from './actions'; import { getInitialPatchOffset } from '../project/utils'; +import { isErrorMessage } from '../debugger/utils'; import { default as initialState } from './state'; @@ -367,6 +369,11 @@ const openDebuggerTab = R.curry((patchPath, state) => { )(state); }); +const showDebuggerPane = R.assocPath( + ['panels', PANEL_IDS.DEPLOYMENT, 'maximized'], + true +); + // ============================================================================= // // Reducer @@ -573,7 +580,10 @@ const editorReducer = (state = initialState, action) => { // debugger // case DAT.DEBUG_SESSION_STARTED: - return openDebuggerTab(action.payload.patchPath, state); + return R.compose( + openDebuggerTab(action.payload.patchPath), + showDebuggerPane + )(state); case DAT.DEBUG_SESSION_STOPPED: return closeTabById(DEBUGGER_TAB_ID, state); case DAT.DEBUG_DRILL_DOWN: @@ -631,7 +641,31 @@ const editorReducer = (state = initialState, action) => { R.not, state ); - + // + // Show deployment pane on some actions + // + case DAT.INSTALL_ARDUINO_DEPENDENCIES: + case DAT.UPGRADE_ARDUINO_DEPENDECIES: + case DAT.CHECK_ARDUINO_DEPENDENCIES: { + const { type, meta: { status } } = action; + return type !== DAT.CHECK_ARDUINO_DEPENDENCIES && + (status === STATUS.STARTED || status === STATUS.FAILED) + ? showDebuggerPane(state) + : state; + } + case DAT.UPLOAD: { + const { meta: { status } } = action; + return status === STATUS.FAILED ? showDebuggerPane(state) : state; + } + case DAT.DEBUGGER_LOG_ADD_MESSAGES: { + const errorMessages = R.filter(isErrorMessage, action.payload); + return errorMessages.length > 0 ? showDebuggerPane(state) : state; + } + case DAT.SERIAL_SESSION_STARTED: + return showDebuggerPane(state); + // + // + // case EAT.FOCUS_BOUND_VALUE: case EAT.FOCUS_LABEL: // maximize Inspector panel to focus & select widget's input @@ -650,7 +684,8 @@ const editorReducer = (state = initialState, action) => { case EAT.TABTEST_ERROR: return R.compose( R.assoc('tabtestWorker', null), - R.assoc('isTabtestRunning', false) + R.assoc('isTabtestRunning', false), + showDebuggerPane )(state); case EAT.SIMULATION_LAUNCHED: @@ -662,7 +697,8 @@ const editorReducer = (state = initialState, action) => { case EAT.SIMULATION_ERROR: return R.compose( R.assoc('simulationWorker', null), - closeTabById(DEBUGGER_TAB_ID) + closeTabById(DEBUGGER_TAB_ID), + showDebuggerPane )(state); case EAT.SHOW_COLORPICKER_WIDGET: diff --git a/packages/xod-client/src/editor/state.js b/packages/xod-client/src/editor/state.js index 3a4403203..b023cb5cc 100644 --- a/packages/xod-client/src/editor/state.js +++ b/packages/xod-client/src/editor/state.js @@ -56,5 +56,11 @@ export default { sidebar: SIDEBAR_IDS.RIGHT, size: 0.5, }, + [PANEL_IDS.DEPLOYMENT]: { + index: 0, + maximized: false, + sidebar: SIDEBAR_IDS.BOTTOM, + size: 0.2, + }, }, }; diff --git a/yarn.lock b/yarn.lock index da504a9a6..1464d5b44 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14114,10 +14114,10 @@ react-redux@^4.0.6, react-redux@^4.4.5: loose-envify "^1.1.0" prop-types "^15.5.4" -react-reflex@^2.2.7: - version "2.2.7" - resolved "https://registry.yarnpkg.com/react-reflex/-/react-reflex-2.2.7.tgz#ff1a0a73981224bc4935a018e3da1056cb000b99" - integrity sha1-/xoKc5gSJLxJNaAY49oQVssAC5k= +react-reflex@^2.2.9: + version "2.2.9" + resolved "https://registry.yarnpkg.com/react-reflex/-/react-reflex-2.2.9.tgz#e8cebe6c0f183da319c8c155d8d82096b1026770" + integrity sha512-NDn2fu7TuQlc0vKfIJW1gHa7n5SDj2fonfmpm9NzO1ql4je6mcqjTibeN0eyIAomcNwKAd5IPe8JOHKbK7pYYA== dependencies: babel-runtime "^6.23.0" lodash.throttle "^4.1.1"