Merge remote-tracking branch 'origin/de-organize' into de-organize
commit
d6cf66e91c
|
@ -7,28 +7,36 @@ import QueryTabItem from './QueryTabItem';
|
|||
import SimpleDropdown from 'src/shared/components/SimpleDropdown';
|
||||
|
||||
import * as viewActions from '../actions/view';
|
||||
const {
|
||||
arrayOf,
|
||||
func,
|
||||
shape,
|
||||
string,
|
||||
} = PropTypes;
|
||||
|
||||
const QueryBuilder = React.createClass({
|
||||
propTypes: {
|
||||
queries: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
timeRange: PropTypes.shape({
|
||||
upper: PropTypes.string,
|
||||
lower: PropTypes.string,
|
||||
queries: arrayOf(shape({})).isRequired,
|
||||
timeRange: shape({
|
||||
upper: string,
|
||||
lower: string,
|
||||
}).isRequired,
|
||||
actions: PropTypes.shape({
|
||||
chooseNamespace: PropTypes.func.isRequired,
|
||||
chooseMeasurement: PropTypes.func.isRequired,
|
||||
chooseTag: PropTypes.func.isRequired,
|
||||
groupByTag: PropTypes.func.isRequired,
|
||||
addQuery: PropTypes.func.isRequired,
|
||||
deleteQuery: PropTypes.func.isRequired,
|
||||
toggleField: PropTypes.func.isRequired,
|
||||
groupByTime: PropTypes.func.isRequired,
|
||||
toggleTagAcceptance: PropTypes.func.isRequired,
|
||||
applyFuncsToField: PropTypes.func.isRequired,
|
||||
actions: shape({
|
||||
chooseNamespace: func.isRequired,
|
||||
chooseMeasurement: func.isRequired,
|
||||
chooseTag: func.isRequired,
|
||||
groupByTag: func.isRequired,
|
||||
addQuery: func.isRequired,
|
||||
deleteQuery: func.isRequired,
|
||||
toggleField: func.isRequired,
|
||||
groupByTime: func.isRequired,
|
||||
toggleTagAcceptance: func.isRequired,
|
||||
applyFuncsToField: func.isRequired,
|
||||
}).isRequired,
|
||||
setActiveQuery: PropTypes.func.isRequired,
|
||||
activeQueryID: PropTypes.string,
|
||||
height: string,
|
||||
top: string,
|
||||
setActiveQuery: func.isRequired,
|
||||
activeQueryID: string,
|
||||
},
|
||||
|
||||
handleSetActiveQuery(query) {
|
||||
|
@ -56,8 +64,9 @@ const QueryBuilder = React.createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
const {height, top} = this.props;
|
||||
return (
|
||||
<div className="query-builder">
|
||||
<div className="query-builder" style={{height, top}}>
|
||||
{this.renderQueryTabList()}
|
||||
{this.renderQueryEditor()}
|
||||
</div>
|
||||
|
|
|
@ -6,15 +6,23 @@ import LineGraph from 'shared/components/LineGraph';
|
|||
import MultiTable from './MultiTable';
|
||||
const RefreshingLineGraph = AutoRefresh(LineGraph);
|
||||
|
||||
const {
|
||||
arrayOf,
|
||||
number,
|
||||
shape,
|
||||
string,
|
||||
} = PropTypes;
|
||||
|
||||
const Visualization = React.createClass({
|
||||
propTypes: {
|
||||
timeRange: PropTypes.shape({
|
||||
upper: PropTypes.string,
|
||||
lower: PropTypes.string,
|
||||
timeRange: shape({
|
||||
upper: string,
|
||||
lower: string,
|
||||
}).isRequired,
|
||||
queryConfigs: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
name: PropTypes.string,
|
||||
activeQueryIndex: PropTypes.number,
|
||||
queryConfigs: arrayOf(shape({})).isRequired,
|
||||
name: string,
|
||||
activeQueryIndex: number,
|
||||
height: string,
|
||||
},
|
||||
|
||||
contextTypes: {
|
||||
|
@ -36,7 +44,7 @@ const Visualization = React.createClass({
|
|||
},
|
||||
|
||||
render() {
|
||||
const {queryConfigs, timeRange, activeQueryIndex} = this.props;
|
||||
const {queryConfigs, timeRange, activeQueryIndex, height} = this.props;
|
||||
const {source} = this.context;
|
||||
const proxyLink = source.links.proxy;
|
||||
|
||||
|
@ -52,7 +60,7 @@ const Visualization = React.createClass({
|
|||
const isInDataExplorer = true;
|
||||
|
||||
return (
|
||||
<div className={classNames("graph", {active: true})}>
|
||||
<div className={classNames("graph", {active: true})} style={{height}}>
|
||||
<div className="graph-heading">
|
||||
<div className="graph-title">
|
||||
{name || "Graph"}
|
||||
|
|
|
@ -3,6 +3,7 @@ import {connect} from 'react-redux';
|
|||
import QueryBuilder from '../components/QueryBuilder';
|
||||
import Visualization from '../components/Visualization';
|
||||
import Header from '../containers/Header';
|
||||
import ResizeContainer from 'src/shared/components/ResizeContainer';
|
||||
|
||||
import {
|
||||
setTimeRange as setTimeRangeAction,
|
||||
|
@ -64,7 +65,7 @@ const DataExplorer = React.createClass({
|
|||
actions={{setTimeRange}}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
<div className="page-contents">
|
||||
<ResizeContainer>
|
||||
<Visualization
|
||||
timeRange={timeRange}
|
||||
queryConfigs={queries}
|
||||
|
@ -77,7 +78,7 @@ const DataExplorer = React.createClass({
|
|||
setActiveQuery={this.handleSetActiveQuery}
|
||||
activeQueryID={activeQueryID}
|
||||
/>
|
||||
</div>
|
||||
</ResizeContainer>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -9,8 +9,8 @@ const ResizeContainer = React.createClass({
|
|||
|
||||
getInitialState() {
|
||||
return {
|
||||
leftWidth: '34%',
|
||||
rightWidth: '66%',
|
||||
topHeight: '60%',
|
||||
bottomHeight: '40%',
|
||||
isDragging: false,
|
||||
};
|
||||
},
|
||||
|
@ -32,40 +32,40 @@ const ResizeContainer = React.createClass({
|
|||
return;
|
||||
}
|
||||
|
||||
const appWidth = parseInt(getComputedStyle(this.refs.resizeContainer).width, 10);
|
||||
// handleOffSet moves the resize handle as many pixels as the side bar is taking up.
|
||||
const handleOffSet = window.innerWidth - appWidth;
|
||||
const appHeight = parseInt(getComputedStyle(this.refs.resizeContainer).height, 10);
|
||||
// headingOffset moves the resize handle as many pixels as the page-heading is taking up.
|
||||
const headingOffset = window.innerHeight - appHeight;
|
||||
const turnToPercent = 100;
|
||||
const newLeftPanelPercent = Math.ceil(((e.pageX - handleOffSet) / (appWidth)) * turnToPercent);
|
||||
const newRightPanelPercent = (turnToPercent - newLeftPanelPercent);
|
||||
const newTopPanelPercent = Math.ceil(((e.pageY - headingOffset) / (appHeight)) * turnToPercent);
|
||||
const newBottomPanelPercent = (turnToPercent - newTopPanelPercent);
|
||||
|
||||
// Don't trigger a resize unless the change in size is greater than minResizePercentage
|
||||
const minResizePercentage = 0.5;
|
||||
if (Math.abs(newLeftPanelPercent - parseFloat(this.state.leftWidth)) < minResizePercentage) {
|
||||
if (Math.abs(newTopPanelPercent - parseFloat(this.state.topHeight)) < minResizePercentage) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't trigger a resize if the new sizes are too small
|
||||
const minLeftPanelWidth = 371;
|
||||
const minRightPanelWidth = 389;
|
||||
if (((newLeftPanelPercent / turnToPercent) * appWidth) < minLeftPanelWidth || ((newRightPanelPercent / turnToPercent) * appWidth) < minRightPanelWidth) {
|
||||
const minTopPanelHeight = 300;
|
||||
const minBottomPanelHeight = 250;
|
||||
if (((newTopPanelPercent / turnToPercent) * appHeight) < minTopPanelHeight || ((newBottomPanelPercent / turnToPercent) * appHeight) < minBottomPanelHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({leftWidth: `${(newLeftPanelPercent)}%`, rightWidth: `${(newRightPanelPercent)}%`});
|
||||
this.setState({topHeight: `${(newTopPanelPercent)}%`, bottomHeight: `${(newBottomPanelPercent)}%`});
|
||||
},
|
||||
|
||||
render() {
|
||||
const {leftWidth, rightWidth, isDragging} = this.state;
|
||||
const left = React.cloneElement(this.props.children[0], {width: leftWidth});
|
||||
const right = React.cloneElement(this.props.children[1], {width: rightWidth});
|
||||
const handle = <ResizeHandle isDragging={isDragging} onHandleStartDrag={this.handleStartDrag} />;
|
||||
const {topHeight, bottomHeight, isDragging} = this.state;
|
||||
const top = React.cloneElement(this.props.children[0], {height: topHeight});
|
||||
const bottom = React.cloneElement(this.props.children[1], {height: bottomHeight, top: topHeight});
|
||||
const handle = <ResizeHandle isDragging={isDragging} onHandleStartDrag={this.handleStartDrag} top={topHeight} />;
|
||||
|
||||
return (
|
||||
<div className="resize-container page-contents" onMouseLeave={this.handleMouseLeave} onMouseUp={this.handleStopDrag} onMouseMove={this.handleDrag} ref="resizeContainer" >
|
||||
{left}
|
||||
{top}
|
||||
{handle}
|
||||
{right}
|
||||
{bottom}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
import React from 'react';
|
||||
import cx from 'classnames';
|
||||
|
||||
const {func, bool} = React.PropTypes;
|
||||
const {func, bool, string} = React.PropTypes;
|
||||
const ResizeHandle = React.createClass({
|
||||
propTypes: {
|
||||
onHandleStartDrag: func.isRequired,
|
||||
isDragging: bool.isRequired,
|
||||
top: string,
|
||||
},
|
||||
|
||||
render() {
|
||||
return <div className={cx("resizer__handle", {dragging: this.props.isDragging})} ref="resizer" onMouseDown={this.props.onHandleStartDrag} />;
|
||||
const {isDragging, onHandleStartDrag, top} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx("resizer__handle", {dragging: isDragging})}
|
||||
onMouseDown={onHandleStartDrag}
|
||||
style={{top}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -10,12 +10,12 @@ $resizer-color-hover: $g8-storm;
|
|||
$resizer-color-active: $c-pool;
|
||||
|
||||
.resizer__handle {
|
||||
top: 0;
|
||||
top: 60%;
|
||||
left: 0;
|
||||
width: $resizer-click-area;
|
||||
margin-left: -$resizer-click-area/2;
|
||||
margin-right: -$resizer-click-area/2;
|
||||
height: 100%;
|
||||
height: $resizer-click-area;
|
||||
margin-top: -$resizer-click-area/2;
|
||||
margin-bottom: -$resizer-click-area/2;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
@ -31,7 +31,7 @@ $resizer-color-active: $c-pool;
|
|||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%) rotate(90deg);
|
||||
transform: translate(-50%,-50%);
|
||||
width: 130px;
|
||||
height: $resizer-handle-width;
|
||||
line-height: $resizer-handle-width;
|
||||
|
@ -48,18 +48,18 @@ $resizer-color-active: $c-pool;
|
|||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
height: 100%;
|
||||
width: $resizer-line-width;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
width: 100%;
|
||||
height: $resizer-line-width;
|
||||
background-color: $resizer-color;
|
||||
box-shadow: 0 0 0 transparent;
|
||||
transition:
|
||||
background-color 0.19s ease;
|
||||
}
|
||||
&:hover {
|
||||
cursor: ew-resize;
|
||||
cursor: ns-resize;
|
||||
|
||||
&:before {
|
||||
background-color: $resizer-color-hover;
|
||||
|
@ -85,4 +85,4 @@ $resizer-color-active: $c-pool;
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
$query-editor-gutter: 16px;
|
||||
$query-editor-tab-inactive: $g2-kevlar;
|
||||
$query-editor-tab-active: $g3-castle;
|
||||
$query-editor-height: 250px;
|
||||
$graph-bg-color: $g3-castle;
|
||||
$graph-active-color: $g4-onyx;
|
||||
$graph-radius: 4px;
|
||||
$de-vertical-margin: 16px;
|
||||
$dygraphs-legend-offset: 32px;
|
||||
$de-graph-heading-height: 44px;
|
||||
|
||||
// DE Specific components
|
||||
@import 'data-explorer/query-builder';
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
position: absolute;
|
||||
width: calc(100% - #{($explorer-page-padding * 2)});
|
||||
left: $explorer-page-padding;
|
||||
height: calc(40% - 16px);
|
||||
height: 40%;
|
||||
top: 60%;
|
||||
background-color: $g3-castle;
|
||||
border-radius: $radius;
|
||||
border: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
|
@ -16,6 +14,8 @@
|
|||
.query-builder--tabs {
|
||||
display: flex;
|
||||
width: 250px;
|
||||
margin-top: $de-vertical-margin;
|
||||
height: calc(100% - #{($de-vertical-margin * 2)});
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
@include gradient-v($g3-castle,$g1-raven);
|
||||
|
@ -144,6 +144,8 @@
|
|||
$query-builder--column-heading-height: 60px;
|
||||
.query-builder--tab-contents {
|
||||
width: 100%;
|
||||
margin-top: $de-vertical-margin;
|
||||
height: calc(100% - #{($de-vertical-margin * 2)});
|
||||
background-color: $g4-onyx;
|
||||
border-radius: 0 $radius $radius 0;
|
||||
overflow: hidden;
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
Abbreviated as "qeditor"
|
||||
|
||||
*/
|
||||
$query-editor-gutter: 16px;
|
||||
$query-editor-tab-inactive: $g2-kevlar;
|
||||
$query-editor-tab-active: $g3-castle;
|
||||
$query-editor-height: 250px;
|
||||
|
||||
.query-builder--query-preview {
|
||||
position: relative;
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
$graph-bg-color: $g3-castle;
|
||||
$graph-active-color: $g4-onyx;
|
||||
$graph-radius: 4px;
|
||||
$de-vertical-margin: 16px;
|
||||
$dygraphs-legend-offset: 32px;
|
||||
|
||||
.graph {
|
||||
position: absolute;
|
||||
width: calc(100% - #{($explorer-page-padding * 2)});
|
||||
left: $explorer-page-padding;
|
||||
top: $de-vertical-margin;
|
||||
top: 0;
|
||||
height: 60%;
|
||||
}
|
||||
.graph-heading {
|
||||
position: relative;
|
||||
top: $de-vertical-margin;
|
||||
background-color: $graph-bg-color;
|
||||
border-radius: $graph-radius $graph-radius 0 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
height: $de-graph-heading-height;
|
||||
padding: 0 16px;
|
||||
transition:
|
||||
background-color 0.25s ease;
|
||||
|
@ -48,7 +44,8 @@ $dygraphs-legend-offset: 32px;
|
|||
background-color 0.25s ease;
|
||||
}
|
||||
.data-explorer .graph-container {
|
||||
height: calc(100% - 44px - 32px);
|
||||
top: $de-vertical-margin;
|
||||
height: calc(100% - #{$de-graph-heading-height} - #{($de-vertical-margin * 2)});
|
||||
padding: 0;
|
||||
|
||||
& > div {
|
||||
|
|
Loading…
Reference in New Issue