mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[TSVB] change how the resize component works to not use timeouts (#14320)
* [WIP] Atempt to use a new resize component that does not use timeouts * remove unused var * add copyright notices
This commit is contained in:
parent
21f22d3334
commit
0638bcac6e
3 changed files with 208 additions and 75 deletions
|
@ -1,6 +1,5 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
import _ from 'lodash';
|
||||
import $ from '../lib/flot';
|
||||
import eventBus from '../lib/events';
|
||||
|
@ -9,7 +8,6 @@ import calculateBarWidth from '../lib/calculate_bar_width';
|
|||
import colors from '../lib/colors';
|
||||
|
||||
class FlotChart extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleResize = this.handleResize.bind(this);
|
||||
|
@ -28,11 +26,13 @@ class FlotChart extends Component {
|
|||
// We need to rerender if the axis change
|
||||
const valuesChanged = props.yaxes.some((axis, i) => {
|
||||
if (this.props.yaxes[i]) {
|
||||
return axis.position !== this.props.yaxes[i].position ||
|
||||
axis.max !== this.props.yaxes[i].max ||
|
||||
axis.min !== this.props.yaxes[i].min ||
|
||||
axis.axisFormatter !== this.props.yaxes[i].axisFormatter ||
|
||||
axis.axisFormatterTemplate !== this.props.yaxes[i].axisFormatterTemplate;
|
||||
return (
|
||||
axis.position !== this.props.yaxes[i].position ||
|
||||
axis.max !== this.props.yaxes[i].max ||
|
||||
axis.min !== this.props.yaxes[i].min ||
|
||||
axis.axisFormatter !== this.props.yaxes[i].axisFormatter ||
|
||||
axis.axisFormatterTemplate !== this.props.yaxes[i].axisFormatterTemplate
|
||||
);
|
||||
}
|
||||
});
|
||||
if (props.yaxes.length !== this.props.yaxes.length || valuesChanged) {
|
||||
|
@ -62,7 +62,7 @@ class FlotChart extends Component {
|
|||
|
||||
filterByShow(show) {
|
||||
if (show) {
|
||||
return (metric) => {
|
||||
return metric => {
|
||||
return show.some(id => _.startsWith(id, metric.id));
|
||||
};
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ class FlotChart extends Component {
|
|||
calculateData(data, show) {
|
||||
return _(data)
|
||||
.filter(this.filterByShow(show))
|
||||
.map((set) => {
|
||||
.map(set => {
|
||||
if (_.isPlainObject(set)) {
|
||||
return set;
|
||||
}
|
||||
|
@ -103,7 +103,9 @@ class FlotChart extends Component {
|
|||
color: '#990000',
|
||||
data: set
|
||||
};
|
||||
}).reverse().value();
|
||||
})
|
||||
.reverse()
|
||||
.value();
|
||||
}
|
||||
|
||||
handleDraw(plot) {
|
||||
|
@ -153,7 +155,7 @@ class FlotChart extends Component {
|
|||
borderWidth,
|
||||
borderColor: lineColor,
|
||||
hoverable: true,
|
||||
mouseActiveRadius: 200,
|
||||
mouseActiveRadius: 200
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -172,15 +174,17 @@ class FlotChart extends Component {
|
|||
return _.assign(opts, props.options);
|
||||
}
|
||||
|
||||
handleResize() {
|
||||
const resize = findDOMNode(this.resize);
|
||||
handleResize(width, height) {
|
||||
this.size = { width, height };
|
||||
console.log(this.size);
|
||||
if (!this.rendered) {
|
||||
this.renderChart();
|
||||
return;
|
||||
}
|
||||
|
||||
if (resize && resize.clientHeight > 0 && resize.clientHeight > 0) {
|
||||
if (this.size.height > 0 && this.size.width > 0) {
|
||||
if (!this.plot) return;
|
||||
console.log('here');
|
||||
this.plot.resize();
|
||||
this.plot.setupGrid();
|
||||
this.plot.draw();
|
||||
|
@ -189,19 +193,24 @@ class FlotChart extends Component {
|
|||
}
|
||||
|
||||
renderChart() {
|
||||
const resize = findDOMNode(this.resize);
|
||||
console.log('here 2');
|
||||
|
||||
if (this.size.height > 0 && this.size.width > 0) {
|
||||
console.log('here 2.3');
|
||||
|
||||
if (resize.clientWidth > 0 && resize.clientHeight > 0) {
|
||||
this.rendered = true;
|
||||
const { series } = this.props;
|
||||
const data = this.calculateData(series, this.props.show);
|
||||
console.log('here 2.3.3.2');
|
||||
|
||||
this.plot = $.plot(this.target, data, this.getOptions(this.props));
|
||||
console.log('here 2.3.3');
|
||||
|
||||
this.handleDraw(this.plot);
|
||||
console.log('here 3');
|
||||
|
||||
_.defer(() => this.handleResize());
|
||||
|
||||
|
||||
this.handleMouseOver = (...args) => {
|
||||
if (this.props.onMouseOver) this.props.onMouseOver(...args, this.plot);
|
||||
};
|
||||
|
@ -214,8 +223,6 @@ class FlotChart extends Component {
|
|||
$(this.target).on('mouseleave', this.handleMouseLeave);
|
||||
|
||||
if (this.props.crosshair) {
|
||||
|
||||
|
||||
this.handleThorPlotover = (e, pos, item, originalPlot) => {
|
||||
if (this.plot !== originalPlot) {
|
||||
this.plot.setCrosshair({ x: _.get(pos, 'x') });
|
||||
|
@ -225,7 +232,7 @@ class FlotChart extends Component {
|
|||
|
||||
this.handlePlotover = (e, pos, item) => eventBus.trigger('thorPlotover', [pos, item, this.plot]);
|
||||
this.handlePlotleave = () => eventBus.trigger('thorPlotleave');
|
||||
this.handleThorPlotleave = (e) => {
|
||||
this.handleThorPlotleave = e => {
|
||||
this.plot.clearCrosshair();
|
||||
if (this.props.plothover) this.props.plothover(e);
|
||||
};
|
||||
|
@ -256,20 +263,14 @@ class FlotChart extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
console.log('render');
|
||||
return (
|
||||
<Resize
|
||||
onResize={this.handleResize}
|
||||
ref={(el) => this.resize = el}
|
||||
className="rhythm_chart__timeseries-container"
|
||||
>
|
||||
<div
|
||||
ref={(el) => this.target = el}
|
||||
className="rhythm_chart__timeseries-container"
|
||||
/>
|
||||
</Resize>
|
||||
<div className="rhythm_chart__timeseries-container">
|
||||
<div ref={el => (this.target = el)} className="rhythm_chart__timeseries-container" />
|
||||
<Resize onResize={this.handleResize} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FlotChart.defaultProps = {
|
||||
|
@ -289,7 +290,7 @@ FlotChart.propTypes = {
|
|||
show: PropTypes.array,
|
||||
tickFormatter: PropTypes.func,
|
||||
showGrid: PropTypes.bool,
|
||||
yaxes: PropTypes.array,
|
||||
yaxes: PropTypes.array
|
||||
};
|
||||
|
||||
export default FlotChart;
|
||||
|
|
|
@ -1,70 +1,176 @@
|
|||
/*
|
||||
* Please note: Much of this code is taken from the MIT licensed react-resize-detector module written by @maslianok
|
||||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { findDOMNode } from 'react-dom';
|
||||
class Resize extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
this.handleResize = this.handleResize.bind(this);
|
||||
const parentStyle = {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
overflow: 'hidden',
|
||||
zIndex: -1,
|
||||
visibility: 'hidden'
|
||||
};
|
||||
|
||||
const shrinkChildStyle = {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '200%',
|
||||
height: '200%'
|
||||
};
|
||||
|
||||
const expandChildStyle = {
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
};
|
||||
|
||||
class Resize extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
expandChildHeight: 0,
|
||||
expandChildWidth: 0,
|
||||
expandScrollLeft: 0,
|
||||
expandScrollTop: 0,
|
||||
shrinkScrollTop: 0,
|
||||
shrinkScrollLeft: 0,
|
||||
lastWidth: 0,
|
||||
lastHeight: 0
|
||||
};
|
||||
|
||||
this.reset = this.reset.bind(this);
|
||||
this.handleScroll = this.handleScroll.bind(this);
|
||||
}
|
||||
|
||||
checkSize() {
|
||||
const el = findDOMNode(this.el);
|
||||
if (!el) return;
|
||||
this.timeout = setTimeout(() => {
|
||||
const { currentHeight, currentWidth } = this.state;
|
||||
if (currentHeight !== el.parentNode.clientHeight || currentWidth !== el.parentNode.clientWidth) {
|
||||
this.setState({
|
||||
currentWidth: el.parentNode.clientWidth,
|
||||
currentHeight: el.parentNode.clientHeight
|
||||
});
|
||||
this.handleResize();
|
||||
}
|
||||
clearTimeout(this.timeout);
|
||||
this.checkSize();
|
||||
}, this.props.frequency);
|
||||
componentWillMount() {
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const el = findDOMNode(this.el);
|
||||
const currentWidth = el.parentNode.clientWidth;
|
||||
const currentHeight = el.parentNode.clientHeight;
|
||||
this.setState({ currentHeight, currentWidth }); // eslint-disable-line react/no-did-mount-set-state
|
||||
this.checkSize();
|
||||
const [width, height] = this.containerSize();
|
||||
this.reset(width, height);
|
||||
this.props.onResize(width, height);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeout);
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
return this.props !== nextProps || this.state !== nextState;
|
||||
}
|
||||
|
||||
handleResize() {
|
||||
if (this.props.onResize) this.props.onResize();
|
||||
componentDidUpdate() {
|
||||
this.expand.scrollLeft = this.expand.scrollWidth;
|
||||
this.expand.scrollTop = this.expand.scrollHeight;
|
||||
|
||||
this.shrink.scrollLeft = this.shrink.scrollWidth;
|
||||
this.shrink.scrollTop = this.shrink.scrollHeight;
|
||||
}
|
||||
|
||||
containerSize() {
|
||||
return [
|
||||
this.props.handleWidth && this.container.parentElement.offsetWidth,
|
||||
this.props.handleHeight && this.container.parentElement.offsetHeight
|
||||
];
|
||||
}
|
||||
|
||||
reset(containerWidth, containerHeight) {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = this.container.parentElement;
|
||||
|
||||
let position = 'static';
|
||||
if (parent.currentStyle) {
|
||||
position = parent.currentStyle.position;
|
||||
} else if (window.getComputedStyle) {
|
||||
position = window.getComputedStyle(parent).position;
|
||||
}
|
||||
if (position === 'static') {
|
||||
parent.style.position = 'relative';
|
||||
}
|
||||
|
||||
this.setState({
|
||||
expandChildHeight: this.expand.offsetHeight + 10,
|
||||
expandChildWidth: this.expand.offsetWidth + 10,
|
||||
lastWidth: containerWidth,
|
||||
lastHeight: containerHeight
|
||||
});
|
||||
}
|
||||
|
||||
handleScroll(e) {
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const { state } = this;
|
||||
|
||||
const [width, height] = this.containerSize();
|
||||
if (width !== state.lastWidth || height !== state.lastHeight) {
|
||||
this.props.onResize(width, height);
|
||||
}
|
||||
|
||||
this.reset(width, height);
|
||||
}
|
||||
|
||||
render() {
|
||||
const style = this.props.style || {};
|
||||
const className = this.props.className || '';
|
||||
return(
|
||||
const { state } = this;
|
||||
|
||||
const expandStyle = Object.assign({}, expandChildStyle, {
|
||||
width: state.expandChildWidth,
|
||||
height: state.expandChildHeight
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
style={style}
|
||||
className={className}
|
||||
ref={(el) => this.el = el}
|
||||
style={parentStyle}
|
||||
ref={e => {
|
||||
this.container = e;
|
||||
}}
|
||||
>
|
||||
{this.props.children}
|
||||
<div
|
||||
style={parentStyle}
|
||||
onScroll={this.handleScroll}
|
||||
ref={e => {
|
||||
this.expand = e;
|
||||
}}
|
||||
>
|
||||
<div style={expandStyle} />
|
||||
</div>
|
||||
<div
|
||||
style={parentStyle}
|
||||
onScroll={this.handleScroll}
|
||||
ref={e => {
|
||||
this.shrink = e;
|
||||
}}
|
||||
>
|
||||
<div style={shrinkChildStyle} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Resize.defaultProps = {
|
||||
frequency: 500
|
||||
};
|
||||
|
||||
Resize.propTypes = {
|
||||
frequency: PropTypes.number,
|
||||
handleWidth: PropTypes.bool,
|
||||
handleHeight: PropTypes.bool,
|
||||
onResize: PropTypes.func
|
||||
};
|
||||
|
||||
Resize.defaultProps = {
|
||||
handleWidth: true,
|
||||
handleHeight: true,
|
||||
onResize: e => e
|
||||
};
|
||||
|
||||
export default Resize;
|
||||
|
|
|
@ -1,6 +1,32 @@
|
|||
Kibana
|
||||
Copyright 2012-2017 Elasticsearch
|
||||
|
||||
---
|
||||
This product bundles react-resize-detector@0.6.0 which is available under a
|
||||
"MIT" license.
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2017 Vitalii Maslianok <maslianok@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---
|
||||
This product bundles angular-ui-bootstrap@0.12.1 which is available under a
|
||||
"MIT" license.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue