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"