From 7e0a44efc261cd56203832fd90b9e0f3a0839a61 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Tue, 27 Sep 2016 17:07:53 +0200 Subject: [PATCH 1/5] Kinda nice --- client/app/scripts/components/embedded-terminal.js | 10 +++++----- client/app/scripts/components/terminal.js | 8 +++++++- client/app/styles/main.less | 11 +++++------ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/client/app/scripts/components/embedded-terminal.js b/client/app/scripts/components/embedded-terminal.js index 2ad699449..3c50fcc6e 100644 --- a/client/app/scripts/components/embedded-terminal.js +++ b/client/app/scripts/components/embedded-terminal.js @@ -1,7 +1,7 @@ import React from 'react'; import { connect } from 'react-redux'; -import { getNodeColor, getNodeColorDark } from '../utils/color-utils'; +import { brightenColor, getNodeColorDark } from '../utils/color-utils'; import Terminal from './terminal'; import { DETAILS_PANEL_WIDTH, DETAILS_PANEL_MARGINS, DETAILS_PANEL_OFFSET } from '../constants/styles'; @@ -12,13 +12,13 @@ class EmeddedTerminal extends React.Component { const nodeId = pipe.get('nodeId'); const node = details.get(nodeId); const d = node && node.details; - const titleBarColor = d && getNodeColorDark(d.rank, d.label); - const statusBarColor = d && getNodeColor(d.rank, d.label); + const titleBarColor = d && getNodeColorDark(d.rank, d.label, d.pseudo); + const statusBarColor = d && brightenColor(titleBarColor); const title = d && d.label; const style = { - right: DETAILS_PANEL_MARGINS.right + DETAILS_PANEL_WIDTH + 10 + - (details.size * DETAILS_PANEL_OFFSET) + right: DETAILS_PANEL_MARGINS.right + DETAILS_PANEL_WIDTH + + ((details.size - 1) * DETAILS_PANEL_OFFSET) }; // React unmount/remounts when key changes, this is important for cleaning up diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index a514a7b3b..8ea4d44e1 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -247,8 +247,14 @@ class Terminal extends React.Component { } getTerminalHeader() { + const dark = this.props.titleBarColor || getNeutralColor(); + const light = this.props.statusBarColor || getNeutralColor(); + const border = `4px solid ${dark}`; const style = { - backgroundColor: this.props.titleBarColor || getNeutralColor() + borderTop: border, + borderBottom: border, + borderLeft: border, + backgroundColor: light, }; return (
diff --git a/client/app/styles/main.less b/client/app/styles/main.less index 9d1d47832..56119dce8 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -41,7 +41,7 @@ @details-window-padding-left: 36px; @border-radius: 4px; -@terminal-header-height: 34px; +@terminal-header-height: 44px + 8px; @node-opacity-blurred: 0.25; @node-highlight-fill-opacity: 0.1; @@ -979,7 +979,7 @@ h2 { } &-embedded { - z-index: 512; + z-index: 1024; position: fixed; top: 24px; bottom: 48px; @@ -996,18 +996,17 @@ h2 { border: 0px solid #000000; border-radius: 4px; color: #f0f0f0; - font-family: @mono-font; - .shadow-2; } &-header { .truncate; - text-align: center; color: @white; height: @terminal-header-height; padding: 8px 24px; background-color: @text-color; position: relative; + font-size: 14px; + line-height: 28px; &-title { cursor: default; @@ -1030,7 +1029,6 @@ h2 { font-size: 0.8em; font-weight: bold; text-transform: uppercase; - word-spacing: -4px; &:hover { opacity: 1; @@ -1047,6 +1045,7 @@ h2 { &-embedded &-inner { top: @terminal-header-height; } &-app &-inner { top: 0; } &-inner { + font-family: @mono-font; position: absolute; bottom: 0; left: 0; From 288dff86bcd812e575e9e9dfff145dac071965bc Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Tue, 4 Oct 2016 17:15:57 +0200 Subject: [PATCH 2/5] Working nicely w/ flexbox etc. --- client/app/scripts/components/app.js | 5 +-- client/app/scripts/components/details-card.js | 18 +++++++-- .../scripts/components/embedded-terminal.js | 11 +----- client/app/scripts/components/terminal.js | 37 +++++++++++-------- client/app/styles/main.less | 23 +++++------- 5 files changed, 49 insertions(+), 45 deletions(-) diff --git a/client/app/scripts/components/app.js b/client/app/scripts/components/app.js index 3621f64e9..4220d859d 100644 --- a/client/app/scripts/components/app.js +++ b/client/app/scripts/components/app.js @@ -18,7 +18,6 @@ import Nodes from './nodes'; import GridModeSelector from './grid-mode-selector'; import MetricSelector from './metric-selector'; import NetworkSelector from './networks-selector'; -import EmbeddedTerminal from './embedded-terminal'; import { getRouter } from '../utils/router-utils'; import DebugToolbar, { showingDebugToolbar, toggleDebugToolbar } from './debug-toolbar.js'; @@ -103,7 +102,7 @@ class App extends React.Component { render() { const { gridMode, showingDetails, showingHelp, showingMetricsSelector, - showingNetworkSelector, showingTerminal } = this.props; + showingNetworkSelector } = this.props; const isIframe = window !== window.top; return ( @@ -114,8 +113,6 @@ class App extends React.Component { {showingDetails &&
} - {showingTerminal && } -
{!isIframe && diff --git a/client/app/scripts/components/details-card.js b/client/app/scripts/components/details-card.js index a8469625d..ffd7a1f04 100644 --- a/client/app/scripts/components/details-card.js +++ b/client/app/scripts/components/details-card.js @@ -2,6 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; import NodeDetails from './node-details'; +import EmbeddedTerminal from './embedded-terminal'; import { DETAILS_PANEL_WIDTH as WIDTH, DETAILS_PANEL_OFFSET as OFFSET, DETAILS_PANEL_MARGINS as MARGINS } from '../constants/styles'; @@ -22,7 +23,7 @@ class DetailsCard extends React.Component { render() { let transform; - const origin = this.props.origin; + const { origin, showingTerminal } = this.props; const panelHeight = window.innerHeight - MARGINS.bottom - MARGINS.top; if (origin && !this.state.mounted) { // render small panel near origin, will transition into normal panel after being mounted @@ -45,12 +46,23 @@ class DetailsCard extends React.Component { transform = `translateX(${shiftX}px)`; } } + const style = {transform, left: showingTerminal ? 36 : null}; return ( -
+
+ {showingTerminal && }
); } } -export default connect()(DetailsCard); + +function mapStateToProps(state, props) { + const pipe = state.get('controlPipes').last(); + return { + showingTerminal: pipe && pipe.get('nodeId') === props.id, + }; +} + + +export default connect(mapStateToProps)(DetailsCard); diff --git a/client/app/scripts/components/embedded-terminal.js b/client/app/scripts/components/embedded-terminal.js index 3c50fcc6e..e85ef251d 100644 --- a/client/app/scripts/components/embedded-terminal.js +++ b/client/app/scripts/components/embedded-terminal.js @@ -3,8 +3,6 @@ import { connect } from 'react-redux'; import { brightenColor, getNodeColorDark } from '../utils/color-utils'; import Terminal from './terminal'; -import { DETAILS_PANEL_WIDTH, DETAILS_PANEL_MARGINS, - DETAILS_PANEL_OFFSET } from '../constants/styles'; class EmeddedTerminal extends React.Component { render() { @@ -16,17 +14,12 @@ class EmeddedTerminal extends React.Component { const statusBarColor = d && brightenColor(titleBarColor); const title = d && d.label; - const style = { - right: DETAILS_PANEL_MARGINS.right + DETAILS_PANEL_WIDTH + - ((details.size - 1) * DETAILS_PANEL_OFFSET) - }; - // React unmount/remounts when key changes, this is important for cleaning up // the term.js and creating a new one for the new pipe. return ( -
+
); diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index 8ea4d44e1..03f4c1590 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -88,9 +88,11 @@ class Terminal extends React.Component { pixelPerCol: 0, pixelPerRow: 0 }; + this.handleCloseClick = this.handleCloseClick.bind(this); this.handlePopoutTerminal = this.handlePopoutTerminal.bind(this); this.handleResize = this.handleResize.bind(this); + this.focusTerminal = this.focusTerminal.bind(this); } createWebsocket(term) { @@ -106,7 +108,13 @@ class Terminal extends React.Component { }; socket.onclose = () => { - log('socket closed'); + // + // componentWillUnmount has called close and tidied up! don't try and do it again here + // (setState etc), its too late. + // + if (!this.socket) { + return; + } this.socket = null; const wereConnected = this.state.connected; this.setState({connected: false}); @@ -134,15 +142,13 @@ class Terminal extends React.Component { } componentDidMount() { - const component = this; - this.term = new Term({ cols: this.state.cols, rows: this.state.rows, convertEol: !this.props.raw }); - const innerNode = ReactDOM.findDOMNode(component.inner); + const innerNode = ReactDOM.findDOMNode(this.inner); this.term.open(innerNode); this.term.on('data', (data) => { if (this.socket) { @@ -180,6 +186,7 @@ class Terminal extends React.Component { this.term.destroy(); this.term = null; } + if (this.socket) { log('close socket'); this.socket.close(); @@ -187,14 +194,6 @@ class Terminal extends React.Component { } } - componentWillReceiveProps(nextProps) { - const containerMarginChanged = nextProps.containerMargin !== this.props.containerMargin; - log(nextProps.containerMargin); - if (containerMarginChanged) { - this.handleResize(); - } - } - componentDidUpdate(prevProps, prevState) { const sizeChanged = ( prevState.cols !== this.state.cols || @@ -213,6 +212,12 @@ class Terminal extends React.Component { this.props.dispatch(clickCloseTerminal(this.getPipeId(), true)); } + focusTerminal() { + if (this.term) { + this.term.focus(); + } + } + handlePopoutTerminal(ev) { ev.preventDefault(); const paramString = JSON.stringify(this.props); @@ -252,7 +257,6 @@ class Terminal extends React.Component { const border = `4px solid ${dark}`; const style = { borderTop: border, - borderBottom: border, borderLeft: border, backgroundColor: light, }; @@ -324,8 +328,11 @@ class Terminal extends React.Component { return (
{this.isEmbedded() && this.getTerminalHeader()} -
this.innerFlex = ref} - className={innerClassName} style={innerFlexStyle} > +
this.innerFlex = ref} + className={innerClassName} + style={innerFlexStyle} >
this.inner = ref} />
{this.getTerminalStatusBar()} diff --git a/client/app/styles/main.less b/client/app/styles/main.less index 56119dce8..e4819553e 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -41,7 +41,7 @@ @details-window-padding-left: 36px; @border-radius: 4px; -@terminal-header-height: 44px + 8px; +@terminal-header-height: 40px + 8px; @node-opacity-blurred: 0.25; @node-highlight-fill-opacity: 0.1; @@ -578,17 +578,19 @@ h2 { .details { &-wrapper { position: fixed; + display: flex; z-index: 1024; right: @details-window-padding-left; top: 24px; bottom: 48px; - width: @details-window-width; transition: transform 0.33333s cubic-bezier(0,0,0.21,1); + .shadow-2; } } .node-details { height: 100%; + width: @details-window-width; background-color: rgba(255, 255, 255, 0.86); display: flex; flex-flow: column; @@ -596,7 +598,6 @@ h2 { padding-bottom: 2px; border-radius: 2px; background-color: #fff; - .shadow-2; &:last-child { margin-bottom: 0; @@ -979,20 +980,13 @@ h2 { } &-embedded { - z-index: 1024; - position: fixed; - top: 24px; - bottom: 48px; - left: 36px; - right: (@details-window-width + @details-window-padding-left + 10px); + position: relative; + flex: 1; } &-wrapper { - position: absolute; - bottom: 0; - top: 0; - left: 0; - right: 0; + width: 100%; + height: 100%; border: 0px solid #000000; border-radius: 4px; color: #f0f0f0; @@ -1045,6 +1039,7 @@ h2 { &-embedded &-inner { top: @terminal-header-height; } &-app &-inner { top: 0; } &-inner { + cursor: text; font-family: @mono-font; position: absolute; bottom: 0; From 83d4fad5b43980fac5823284da18d0dc05188fec Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Wed, 5 Oct 2016 10:04:43 +0200 Subject: [PATCH 3/5] Animate terminal appearance, slide in from details panel. - Terminal shadow has been lost. --- client/app/scripts/components/details-card.js | 6 ++- .../scripts/components/embedded-terminal.js | 45 +++++++++++++++++-- client/app/scripts/components/terminal.js | 18 ++++++++ client/app/styles/main.less | 9 +++- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/client/app/scripts/components/details-card.js b/client/app/scripts/components/details-card.js index ffd7a1f04..0660f7612 100644 --- a/client/app/scripts/components/details-card.js +++ b/client/app/scripts/components/details-card.js @@ -46,7 +46,11 @@ class DetailsCard extends React.Component { transform = `translateX(${shiftX}px)`; } } - const style = {transform, left: showingTerminal ? 36 : null}; + const style = { + transform, + left: showingTerminal ? 36 : null, + width: showingTerminal ? null : 420 + }; return (
{showingTerminal && } diff --git a/client/app/scripts/components/embedded-terminal.js b/client/app/scripts/components/embedded-terminal.js index e85ef251d..8626893a3 100644 --- a/client/app/scripts/components/embedded-terminal.js +++ b/client/app/scripts/components/embedded-terminal.js @@ -5,6 +5,36 @@ import { brightenColor, getNodeColorDark } from '../utils/color-utils'; import Terminal from './terminal'; class EmeddedTerminal extends React.Component { + + constructor(props, context) { + super(props, context); + this.state = { + mounted: null, + animated: null, + }; + + this.handleTransitionEnd = this.handleTransitionEnd.bind(this); + } + + componentDidMount() { + setTimeout(() => { + this.setState({mounted: true}); + }); + } + + getTransform() { + // + // lazy but close enough for a quick transition + // + const dx = this.state.mounted ? 0 : window.innerWidth - 420; + console.log('dx', dx); + return `translateX(${dx}px)`; + } + + handleTransitionEnd() { + this.setState({ animated: true }); + } + render() { const { pipe, details } = this.props; const nodeId = pipe.get('nodeId'); @@ -18,9 +48,18 @@ class EmeddedTerminal extends React.Component { // the term.js and creating a new one for the new pipe. return (
- +
+ +
); } diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index 03f4c1590..f06f75967 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -141,7 +141,19 @@ class Terminal extends React.Component { this.socket = socket; } + componentWillReceiveProps(nextProps) { + if (this.props.connect !== nextProps.connect && nextProps.connect) { + this.mountTerminal(); + } + } + componentDidMount() { + if (this.props.connect) { + this.mountTerminal(); + } + } + + mountTerminal() { this.term = new Term({ cols: this.state.cols, rows: this.state.rows, @@ -341,4 +353,10 @@ class Terminal extends React.Component { } } + +Terminal.defaultProps = { + connect: true +}; + + export default connect()(Terminal); diff --git a/client/app/styles/main.less b/client/app/styles/main.less index e4819553e..97f77c38b 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -584,7 +584,6 @@ h2 { top: 24px; bottom: 48px; transition: transform 0.33333s cubic-bezier(0,0,0.21,1); - .shadow-2; } } @@ -598,6 +597,7 @@ h2 { padding-bottom: 2px; border-radius: 2px; background-color: #fff; + .shadow-2; &:last-child { margin-bottom: 0; @@ -982,6 +982,13 @@ h2 { &-embedded { position: relative; flex: 1; + overflow-x: hidden; + } + + &-animation-wrapper { + width: 100%; + height: 100%; + transition: transform 0.5s cubic-bezier(0.230, 1.000, 0.320, 1.000); } &-wrapper { From 6996e58c8b4721a2bc3677df584a9f75e0e6e248 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Wed, 5 Oct 2016 10:12:16 +0200 Subject: [PATCH 4/5] Remove magic numbers and tidy up --- client/app/scripts/components/details-card.js | 4 ++-- client/app/scripts/components/embedded-terminal.js | 8 +++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/client/app/scripts/components/details-card.js b/client/app/scripts/components/details-card.js index 0660f7612..1179248c4 100644 --- a/client/app/scripts/components/details-card.js +++ b/client/app/scripts/components/details-card.js @@ -48,8 +48,8 @@ class DetailsCard extends React.Component { } const style = { transform, - left: showingTerminal ? 36 : null, - width: showingTerminal ? null : 420 + left: showingTerminal ? MARGINS.right : null, + width: showingTerminal ? null : WIDTH }; return (
diff --git a/client/app/scripts/components/embedded-terminal.js b/client/app/scripts/components/embedded-terminal.js index 8626893a3..149d5998e 100644 --- a/client/app/scripts/components/embedded-terminal.js +++ b/client/app/scripts/components/embedded-terminal.js @@ -2,6 +2,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { brightenColor, getNodeColorDark } from '../utils/color-utils'; +import { DETAILS_PANEL_WIDTH, DETAILS_PANEL_MARGINS } from '../constants/styles'; import Terminal from './terminal'; class EmeddedTerminal extends React.Component { @@ -23,11 +24,8 @@ class EmeddedTerminal extends React.Component { } getTransform() { - // - // lazy but close enough for a quick transition - // - const dx = this.state.mounted ? 0 : window.innerWidth - 420; - console.log('dx', dx); + const dx = this.state.mounted ? 0 : + window.innerWidth - DETAILS_PANEL_WIDTH - DETAILS_PANEL_MARGINS.right; return `translateX(${dx}px)`; } From c56fcaccee6ad4cbbd0d6752360f352abdb738d2 Mon Sep 17 00:00:00 2001 From: Simon Howe Date: Mon, 24 Oct 2016 16:45:17 +0200 Subject: [PATCH 5/5] Change terminal aesthetic so it appears to float below details panel --- client/app/scripts/components/terminal.js | 4 ---- client/app/styles/main.less | 12 +++++++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/client/app/scripts/components/terminal.js b/client/app/scripts/components/terminal.js index f06f75967..570cdd06c 100644 --- a/client/app/scripts/components/terminal.js +++ b/client/app/scripts/components/terminal.js @@ -264,12 +264,8 @@ class Terminal extends React.Component { } getTerminalHeader() { - const dark = this.props.titleBarColor || getNeutralColor(); const light = this.props.statusBarColor || getNeutralColor(); - const border = `4px solid ${dark}`; const style = { - borderTop: border, - borderLeft: border, backgroundColor: light, }; return ( diff --git a/client/app/styles/main.less b/client/app/styles/main.less index 97f77c38b..c719681b4 100644 --- a/client/app/styles/main.less +++ b/client/app/styles/main.less @@ -41,7 +41,7 @@ @details-window-padding-left: 36px; @border-radius: 4px; -@terminal-header-height: 40px + 8px; +@terminal-header-height: 44px; @node-opacity-blurred: 0.25; @node-highlight-fill-opacity: 0.1; @@ -598,6 +598,8 @@ h2 { border-radius: 2px; background-color: #fff; .shadow-2; + // keep node-details above the terminal. + z-index: 2; &:last-child { margin-bottom: 0; @@ -981,6 +983,9 @@ h2 { &-embedded { position: relative; + // shadow of animation-wrapper is 10px, let it fit in here without being + // overflow hiddened. + padding: 10px 0 10px 10px; flex: 1; overflow-x: hidden; } @@ -989,13 +994,13 @@ h2 { width: 100%; height: 100%; transition: transform 0.5s cubic-bezier(0.230, 1.000, 0.320, 1.000); + .shadow-2; } &-wrapper { width: 100%; height: 100%; border: 0px solid #000000; - border-radius: 4px; color: #f0f0f0; } @@ -1008,6 +1013,7 @@ h2 { position: relative; font-size: 14px; line-height: 28px; + border-radius: 4px 0 0 0; &-title { cursor: default; @@ -1054,7 +1060,7 @@ h2 { right: 0; background-color: rgba(0, 0, 0, 0.93); padding: 8px; - border-radius: 0 0 2px 2px; + border-radius: 0 0 0 4px; .terminal { background-color: transparent !important;