From 33d7ff50de7a804636bbd028e0c6c7d2e6516d31 Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Fri, 17 Feb 2017 12:28:51 +0000 Subject: [PATCH 01/10] Implemented vertical splitting into SplitPane --- frontend/Container.js | 34 ++++++++++++++++++ frontend/SplitPane.js | 55 +++++++++++++++++++++++++----- frontend/detail_pane/DetailPane.js | 1 + 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/frontend/Container.js b/frontend/Container.js index 747d2fa660..7f53754b34 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -19,6 +19,12 @@ var TabbedPane = require('./TabbedPane'); import type MenuItem from './ContextMenu'; +type Props = {}; + +type State = { + isVertical: boolean, +}; + class Container extends React.Component { props: { reload: () => void, @@ -37,14 +43,42 @@ class Container extends React.Component { }, extraTabs: {[key: string]: () => React$Element}, }; + state: State; + + constructor(props: Props) { + super(props); + + this.state = { + isVertical: (window.innerWidth < 500), + }; + } + + componentDidMount() { + window.addEventListener('resize', (e) => this.handleResize(e), false); + this.setState({ + isVertical: (window.innerWidth < 500), + }); + } + + componentWillUnmount() { + window.removeEventListener('resize'); + } + + handleResize(e) { + this.setState({ + isVertical: (e.target.innerWidth < 500), + }); + } render() { var tabs = { Elements: () => ( } right={() => } + isVertical={this.state.isVertical} /> ), ...this.props.extraTabs, diff --git a/frontend/SplitPane.js b/frontend/SplitPane.js index 111e7696c0..490647f99a 100644 --- a/frontend/SplitPane.js +++ b/frontend/SplitPane.js @@ -21,13 +21,18 @@ type Props = { left: () => React$Element, right: () => React$Element, initialWidth: number, + initialHeight: number, + isVertical: bool, }; -type DefaultProps = {}; +type DefaultProps = { + isVertical: true, +}; type State = { moving: boolean, width: number, + height: number, }; class SplitPane extends React.Component { @@ -39,30 +44,45 @@ class SplitPane extends React.Component { super(props); this.state = { moving: false, - width: props.initialWidth, + width: (props.isVertical) ? '100%' : props.initialWidth, + height: (!props.isVertical) ? '100%' : props.initialHeight, }; } - onMove(x: number) { + componentWillReceiveProps(nextProps: Props) { + this.setState({ + width: (nextProps.isVertical) ? '100%' : this.state.width, + height: (!nextProps.isVertical) ? '100%' : this.state.height, + }); + } + + onMove(x: number, y: number) { var node = ReactDOM.findDOMNode(this); this.setState({ - width: (node.offsetLeft + node.offsetWidth) - x, + width: (this.props.isVertical) ? '100%' : (node.offsetLeft + node.offsetWidth) - x, + height: (!this.props.isVertical) ? '100%' : (node.offsetTop + node.offsetHeight) - y, }); } render() { var rightStyle = assign({}, styles.rightPane, { width: this.state.width, + height: this.state.height, + marginLeft: (this.props.isVertical) ? 0 : -3, }); + + var containerStyles = (this.props.isVertical) ? styles.containerVertical : styles.container; + var draggerStyles = (this.props.isVertical) ? styles.draggerVertical : styles.dragger; + return ( -
+
{this.props.left()}
this.setState({moving: true})} - onMove={x => this.onMove(x)} + onMove={(x, y) => this.onMove(x, y)} onStop={() => this.setState({moving: false})}>
@@ -81,6 +101,13 @@ var styles = { flex: 1, }, + containerVertical: { + display: 'flex', + minWidth: 0, + flex: 1, + flexDirection: 'column', + }, + dragger: { padding: '0 3px', cursor: 'ew-resize', @@ -88,6 +115,14 @@ var styles = { zIndex: 1, }, + draggerVertical: { + backgroundColor: '#efefef', + padding: '3px 0', + cursor: 'ns-resize', + position: 'relative', + zIndex: 1, + }, + draggerInner: { backgroundColor: '#ccc', height: '100%', @@ -97,13 +132,17 @@ var styles = { rightPane: { display: 'flex', marginLeft: -3, + minWidth: 100, + minHeight: 100, }, leftPane: { display: 'flex', marginRight: -3, - minWidth: '255px', + minWidth: 255, + minHeight: 100, flex: 1, + borderBottom: '1px solid #ccc', }, }; diff --git a/frontend/detail_pane/DetailPane.js b/frontend/detail_pane/DetailPane.js index ece64638a3..90c711074f 100644 --- a/frontend/detail_pane/DetailPane.js +++ b/frontend/detail_pane/DetailPane.js @@ -45,6 +45,7 @@ var styles = { userSelect: 'none', }, header: { + backgroundColor: '#efefef', padding: 5, flexShrink: 0, }, From d7e26da82b80ea843ef524b1d5a472d42307dab8 Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Fri, 17 Feb 2017 21:28:55 +0000 Subject: [PATCH 02/10] Fixed minor issues based on comments in PR --- frontend/Container.js | 25 ++++++++++++++++++------- frontend/SplitPane.js | 19 +++++++++++-------- plugins/Relay/QueriesTab.js | 2 ++ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/frontend/Container.js b/frontend/Container.js index 7f53754b34..4c6c162c79 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -25,6 +25,9 @@ type State = { isVertical: boolean, }; +var IS_VERTICAL_BREAKPOINT = 500; +var resizeTimeout = null; + class Container extends React.Component { props: { reload: () => void, @@ -49,24 +52,32 @@ class Container extends React.Component { super(props); this.state = { - isVertical: (window.innerWidth < 500), + isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), }; } componentDidMount() { - window.addEventListener('resize', (e) => this.handleResize(e), false); + window.addEventListener('resize', this.handleResize, false); this.setState({ - isVertical: (window.innerWidth < 500), + isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), }); } componentWillUnmount() { - window.removeEventListener('resize'); + window.removeEventListener('resize', this.handleResize); } - handleResize(e) { - this.setState({ - isVertical: (e.target.innerWidth < 500), + handleResize = (e: Object) => { + if (!resizeTimeout) { + resizeTimeout = setTimeout(this.handleResizeTimeout, 50, this, e); + } + } + + handleResizeTimeout(scope: Object, e: Object) { + resizeTimeout = null; + + scope.setState({ + isVertical: (e.target.innerWidth < IS_VERTICAL_BREAKPOINT), }); } diff --git a/frontend/SplitPane.js b/frontend/SplitPane.js index 490647f99a..317ee628d0 100644 --- a/frontend/SplitPane.js +++ b/frontend/SplitPane.js @@ -20,8 +20,8 @@ type Props = { style?: {[key: string]: any}, left: () => React$Element, right: () => React$Element, - initialWidth: number, - initialHeight: number, + initialWidth: string, + initialHeight: string, isVertical: bool, }; @@ -31,8 +31,8 @@ type DefaultProps = { type State = { moving: boolean, - width: number, - height: number, + width: string, + height: string, }; class SplitPane extends React.Component { @@ -50,10 +50,13 @@ class SplitPane extends React.Component { } componentWillReceiveProps(nextProps: Props) { - this.setState({ - width: (nextProps.isVertical) ? '100%' : this.state.width, - height: (!nextProps.isVertical) ? '100%' : this.state.height, - }); + if (nextProps.isVertical !== this.props.isVertical) { + if (nextProps.isVertical && !this.props.isVertical) { + this.setState({width: '100%'}); + } else if (!nextProps.isVertical && this.props.isVertical) { + this.setState({height: '100%'}); + } + } } onMove(x: number, y: number) { diff --git a/plugins/Relay/QueriesTab.js b/plugins/Relay/QueriesTab.js index 3dec0bd9b4..a70058a3ef 100644 --- a/plugins/Relay/QueriesTab.js +++ b/plugins/Relay/QueriesTab.js @@ -28,8 +28,10 @@ class QueriesTab extends React.Component { contents = ( } right={() => } + isVertical={false} /> ); } From d555b6250f8d4c8fadc551feacc2bc082df47467 Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Fri, 17 Feb 2017 21:45:07 +0000 Subject: [PATCH 03/10] Updated annotations to match params --- frontend/Container.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/Container.js b/frontend/Container.js index 4c6c162c79..f87948a7c6 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -67,13 +67,13 @@ class Container extends React.Component { window.removeEventListener('resize', this.handleResize); } - handleResize = (e: Object) => { + handleResize = (e: Event) => { if (!resizeTimeout) { resizeTimeout = setTimeout(this.handleResizeTimeout, 50, this, e); } } - handleResizeTimeout(scope: Object, e: Object) { + handleResizeTimeout(scope: Container, e: Event) { resizeTimeout = null; scope.setState({ From a03ddd2bd40e61f5243fe204376e02eab375f533 Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Fri, 17 Feb 2017 22:02:28 +0000 Subject: [PATCH 04/10] A few more minor fixes --- frontend/Container.js | 9 +++++---- frontend/SplitPane.js | 10 ++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/frontend/Container.js b/frontend/Container.js index f87948a7c6..ee07c78d0e 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -65,19 +65,20 @@ class Container extends React.Component { componentWillUnmount() { window.removeEventListener('resize', this.handleResize); + clearTimeout(resizeTimeout); } handleResize = (e: Event) => { if (!resizeTimeout) { - resizeTimeout = setTimeout(this.handleResizeTimeout, 50, this, e); + resizeTimeout = setTimeout(this.handleResizeTimeout, 50); } } - handleResizeTimeout(scope: Container, e: Event) { + handleResizeTimeout = () => { resizeTimeout = null; - scope.setState({ - isVertical: (e.target.innerWidth < IS_VERTICAL_BREAKPOINT), + this.setState({ + isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), }); } diff --git a/frontend/SplitPane.js b/frontend/SplitPane.js index 317ee628d0..e0905551b6 100644 --- a/frontend/SplitPane.js +++ b/frontend/SplitPane.js @@ -50,12 +50,10 @@ class SplitPane extends React.Component { } componentWillReceiveProps(nextProps: Props) { - if (nextProps.isVertical !== this.props.isVertical) { - if (nextProps.isVertical && !this.props.isVertical) { - this.setState({width: '100%'}); - } else if (!nextProps.isVertical && this.props.isVertical) { - this.setState({height: '100%'}); - } + if (nextProps.isVertical && !this.props.isVertical) { + this.setState({width: '100%'}); + } else if (!nextProps.isVertical && this.props.isVertical) { + this.setState({height: '100%'}); } } From f6deaac385db8e9f70093389878c3ded4b956036 Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Sun, 19 Feb 2017 18:29:03 +0000 Subject: [PATCH 05/10] Fixing failing tests for type incompatibility --- frontend/SplitPane.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/SplitPane.js b/frontend/SplitPane.js index e0905551b6..a3f6f8390e 100644 --- a/frontend/SplitPane.js +++ b/frontend/SplitPane.js @@ -20,8 +20,8 @@ type Props = { style?: {[key: string]: any}, left: () => React$Element, right: () => React$Element, - initialWidth: string, - initialHeight: string, + initialWidth: number, + initialHeight: number, isVertical: bool, }; @@ -44,8 +44,8 @@ class SplitPane extends React.Component { super(props); this.state = { moving: false, - width: (props.isVertical) ? '100%' : props.initialWidth, - height: (!props.isVertical) ? '100%' : props.initialHeight, + width: (props.isVertical) ? '100%' : props.initialWidth.toString(), + height: (!props.isVertical) ? '100%' : props.initialHeight.toString(), }; } @@ -60,15 +60,15 @@ class SplitPane extends React.Component { onMove(x: number, y: number) { var node = ReactDOM.findDOMNode(this); this.setState({ - width: (this.props.isVertical) ? '100%' : (node.offsetLeft + node.offsetWidth) - x, - height: (!this.props.isVertical) ? '100%' : (node.offsetTop + node.offsetHeight) - y, + width: (this.props.isVertical) ? '100%' : ((node.offsetLeft + node.offsetWidth) - x).toString(), + height: (!this.props.isVertical) ? '100%' : ((node.offsetTop + node.offsetHeight) - y).toString(), }); } render() { var rightStyle = assign({}, styles.rightPane, { - width: this.state.width, - height: this.state.height, + width: (this.state.width === '100%') ? '100%' : parseInt(this.state.width, 10), + height: (this.state.height === '100%') ? '100%' : parseInt(this.state.height, 10), marginLeft: (this.props.isVertical) ? 0 : -3, }); From ee34dff7b3dee8b94907dcec9cd65d2131112676 Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Mon, 20 Feb 2017 19:52:55 +0000 Subject: [PATCH 06/10] Added semicolon to try and quiet the linter --- frontend/Container.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/Container.js b/frontend/Container.js index ee07c78d0e..c9b95ee32c 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -80,7 +80,7 @@ class Container extends React.Component { this.setState({ isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), }); - } + }; render() { var tabs = { From ccfc3e30423ee6715fdff89d74084f239675df48 Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Mon, 20 Feb 2017 20:48:55 +0000 Subject: [PATCH 07/10] Moved resizeTimeout to be class property --- frontend/Container.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/Container.js b/frontend/Container.js index c9b95ee32c..14287f0f73 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -26,7 +26,6 @@ type State = { }; var IS_VERTICAL_BREAKPOINT = 500; -var resizeTimeout = null; class Container extends React.Component { props: { @@ -47,6 +46,7 @@ class Container extends React.Component { extraTabs: {[key: string]: () => React$Element}, }; state: State; + resizeTimeout: number = null; constructor(props: Props) { super(props); @@ -65,17 +65,17 @@ class Container extends React.Component { componentWillUnmount() { window.removeEventListener('resize', this.handleResize); - clearTimeout(resizeTimeout); + clearTimeout(this.resizeTimeout); } handleResize = (e: Event) => { - if (!resizeTimeout) { - resizeTimeout = setTimeout(this.handleResizeTimeout, 50); + if (!this.resizeTimeout) { + this.resizeTimeout = setTimeout(this.handleResizeTimeout, 50); } } handleResizeTimeout = () => { - resizeTimeout = null; + this.resizeTimeout = null; this.setState({ isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), From 3d25e608cc8c1c4b0b637072ce3d2e84c177c501 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Fri, 24 Feb 2017 21:32:20 +0000 Subject: [PATCH 08/10] Fix Flow --- .flowconfig | 1 + frontend/Container.js | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.flowconfig b/.flowconfig index c0f52e6d66..ef46c95a41 100644 --- a/.flowconfig +++ b/.flowconfig @@ -13,6 +13,7 @@ flow [options] +esproposal.class_instance_fields=enable suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe suppress_comment=\\(.\\|\n\\)*\\$FlowIssue diff --git a/frontend/Container.js b/frontend/Container.js index 6bdabc8e62..5601fc8661 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -46,7 +46,7 @@ class Container extends React.Component { extraTabs: {[key: string]: () => React$Element}, }; state: State; - resizeTimeout: number = null; + resizeTimeout: ?number; constructor(props: Props) { super(props); @@ -68,13 +68,15 @@ class Container extends React.Component { clearTimeout(this.resizeTimeout); } - handleResize = (e: Event) => { + // $FlowFixMe future versions of Flow can infer this + handleResize = (e: Event): void => { if (!this.resizeTimeout) { this.resizeTimeout = setTimeout(this.handleResizeTimeout, 50); } - } + }; - handleResizeTimeout = () => { + // $FlowFixMe future versions of Flow can infer this + handleResizeTimeout = (): void => { this.resizeTimeout = null; this.setState({ From 9c147838e5bbb1b9cb4cf64458c612c219e2646f Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Sat, 4 Mar 2017 19:17:30 +0000 Subject: [PATCH 09/10] Swapped type back to number and remembers spilt position --- frontend/Container.js | 10 +++++----- frontend/SplitPane.js | 39 +++++++++++++++++---------------------- 2 files changed, 22 insertions(+), 27 deletions(-) diff --git a/frontend/Container.js b/frontend/Container.js index 5601fc8661..ca07f3ef14 100644 --- a/frontend/Container.js +++ b/frontend/Container.js @@ -52,14 +52,14 @@ class Container extends React.Component { super(props); this.state = { - isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), + isVertical: (window.innerWidth > IS_VERTICAL_BREAKPOINT), }; } componentDidMount() { window.addEventListener('resize', this.handleResize, false); this.setState({ - isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), + isVertical: (window.innerWidth > IS_VERTICAL_BREAKPOINT), }); } @@ -80,7 +80,7 @@ class Container extends React.Component { this.resizeTimeout = null; this.setState({ - isVertical: (window.innerWidth < IS_VERTICAL_BREAKPOINT), + isVertical: (window.innerWidth > IS_VERTICAL_BREAKPOINT), }); }; @@ -88,8 +88,8 @@ class Container extends React.Component { var tabs = { Elements: () => ( } right={() => } isVertical={this.state.isVertical} diff --git a/frontend/SplitPane.js b/frontend/SplitPane.js index bf1a9fdfaf..cefc6becda 100644 --- a/frontend/SplitPane.js +++ b/frontend/SplitPane.js @@ -31,8 +31,8 @@ type DefaultProps = { type State = { moving: boolean, - width: string, - height: string, + width: number, + height: number, }; class SplitPane extends React.Component { @@ -44,36 +44,31 @@ class SplitPane extends React.Component { super(props); this.state = { moving: false, - width: (props.isVertical) ? '100%' : props.initialWidth.toString(), - height: (!props.isVertical) ? '100%' : props.initialHeight.toString(), + width: props.initialWidth, + height: props.initialHeight, }; } - componentWillReceiveProps(nextProps: Props) { - if (nextProps.isVertical && !this.props.isVertical) { - this.setState({width: '100%'}); - } else if (!nextProps.isVertical && this.props.isVertical) { - this.setState({height: '100%'}); - } - } - onMove(x: number, y: number) { var node = ReactDOM.findDOMNode(this); - this.setState({ - width: (this.props.isVertical) ? '100%' : ((node.offsetLeft + node.offsetWidth) - x).toString(), - height: (!this.props.isVertical) ? '100%' : ((node.offsetTop + node.offsetHeight) - y).toString(), - }); + + this.setState(prevState => ({ + width: !this.props.isVertical ? prevState.width : (node.offsetLeft + node.offsetWidth) - x, + height: this.props.isVertical ? prevState.height : (node.offsetTop + node.offsetHeight) - y, + })); } render() { + var newWidth = this.state.width === this.props.initialWidth ? '50%' : this.state.width; + var newHeight = this.state.height === this.props.initialHeight ? '50%' : this.state.height; var rightStyle = assign({}, styles.rightPane, { - width: (this.state.width === '100%') ? '100%' : parseInt(this.state.width, 10), - height: (this.state.height === '100%') ? '100%' : parseInt(this.state.height, 10), + width: this.props.isVertical ? newWidth : '100%', + height: this.props.isVertical ? '100%' : newHeight, marginLeft: (this.props.isVertical) ? 0 : -3, }); - var containerStyles = (this.props.isVertical) ? styles.containerVertical : styles.container; - var draggerStyles = (this.props.isVertical) ? styles.draggerVertical : styles.dragger; + var containerStyles = this.props.isVertical ? styles.container : styles.containerVertical; + var draggerStyles = this.props.isVertical ? styles.dragger : styles.draggerVertical; return (
@@ -141,8 +136,8 @@ var styles = { leftPane: { display: 'flex', marginRight: -3, - minWidth: 255, - minHeight: 100, + minWidth: '50%', + minHeight: '50%', flex: 1, borderBottom: '1px solid #ccc', }, From 4a477333639e293d66d4499d93680094951b7bbb Mon Sep 17 00:00:00 2001 From: Jolyon Russ Date: Tue, 28 Mar 2017 13:16:04 +0100 Subject: [PATCH 10/10] SplitPane.js now has a more fixed behaviour when resizing --- frontend/SplitPane.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/frontend/SplitPane.js b/frontend/SplitPane.js index cefc6becda..2e0eafe84e 100644 --- a/frontend/SplitPane.js +++ b/frontend/SplitPane.js @@ -49,6 +49,15 @@ class SplitPane extends React.Component { }; } + componentDidMount() { + var node = ReactDOM.findDOMNode(this); + + this.setState({ + width: this.props.isVertical ? node.offsetWidth * 0.3 : node.offsetWidth * 0.6, + height: node.offsetHeight * 0.3, + }); + } + onMove(x: number, y: number) { var node = ReactDOM.findDOMNode(this); @@ -59,11 +68,9 @@ class SplitPane extends React.Component { } render() { - var newWidth = this.state.width === this.props.initialWidth ? '50%' : this.state.width; - var newHeight = this.state.height === this.props.initialHeight ? '50%' : this.state.height; var rightStyle = assign({}, styles.rightPane, { - width: this.props.isVertical ? newWidth : '100%', - height: this.props.isVertical ? '100%' : newHeight, + width: this.props.isVertical ? this.state.width : '100%', + height: this.props.isVertical ? '100%' : this.state.height, marginLeft: (this.props.isVertical) ? 0 : -3, });