From 50e2cd543fb20d520f182496ea08c3aa045ba528 Mon Sep 17 00:00:00 2001 From: shaharmor Date: Mon, 13 Nov 2017 11:00:39 +0200 Subject: [PATCH 1/2] make tooltip show all series --- .../components/timeseries_chart.js | 86 +++++++++++++------ src/ui/public/visualize/visualize.less | 1 - 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js b/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js index 1b4015ed920b1..5abf7019a36d4 100644 --- a/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js +++ b/src/core_plugins/metrics/public/visualizations/components/timeseries_chart.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import moment from 'moment'; import reactcss from 'reactcss'; +import { findIndex } from 'lodash'; import FlotChart from './flot_chart'; import Annotation from './annotation'; @@ -61,23 +62,28 @@ class TimeseriesChart extends Component { } handleMouseOver(e, pos, item, plot) { - if (typeof this.state.mouseHoverTimer === 'number') { window.clearTimeout(this.state.mouseHoverTimer); } if (item) { + const offset = plot.offset(); + const width = plot.width(); + const height = plot.height(); const plotOffset = plot.getPlotOffset(); - const point = plot.pointOffset({ x: item.datapoint[0], y: item.datapoint[1] }); + const mouseX = Math.max(0, Math.min(pos.pageX - offset.left, width)); + const mouseY = Math.max(0, Math.min(pos.pageY - offset.top, height)); const [left, right ] = this.calculateLeftRight(item, plot); - const top = point.top; this.setState({ showTooltip: true, item, left, right, - top: top + 10, - bottom: plotOffset.bottom + mouseX, + mouseY, + width, + leftOffset: plotOffset.left, + rightOffset: plotOffset.right }); } } @@ -102,18 +108,38 @@ class TimeseriesChart extends Component { } render() { - const { item, right, top, left } = this.state; + const { item, right, left, mouseX, mouseY, width, leftOffset, rightOffset } = this.state; const { series } = this.props; let tooltip; + let timestamp; + let dataPoints = []; + + if (item) { + timestamp = item.datapoint[0]; + dataPoints = series.reduce((points, series) => { + const index = findIndex(series.data, (d => d[0] === timestamp)); + if (index > -1) { + const datapoint = series.data[index]; + if (datapoint) { + const point = { + series, + datapoint, + }; + points = [...points, point]; + } + } + return points; + }, []); + } const styles = reactcss({ showTooltip: { tooltipContainer: { pointerEvents: 'none', position: 'absolute', - top: top - 28, - left, - right, + top: mouseY - (dataPoints.length * 17 + 10) / 2, + left: left ? mouseX + leftOffset : null, + right: right ? width - mouseX + rightOffset : null, zIndex: 100, display: 'flex', alignItems: 'center', @@ -137,17 +163,22 @@ class TimeseriesChart extends Component { date: { color: this.props.reversed ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.7)', fontSize: '12px', - lineHeight: '12px' + lineHeight: '12px', + marginTop: 2 }, items: { display: 'flex', - alignItems: 'center' + alignItems: 'center', + height: '17px' }, text: { whiteSpace: 'nowrap', fontSize: '12px', lineHeight: '12px', - marginRight: 5 + marginRight: 5, + maxWidth: '300px', + overflow: 'hidden', + textOverflow: 'ellipsis' }, icon: { marginRight: 5 @@ -156,7 +187,7 @@ class TimeseriesChart extends Component { fontSize: '12px', flexShrink: 0, lineHeight: '12px', - marginLeft: 5 + marginLeft: 'auto' } }, hideTooltip: { @@ -168,21 +199,28 @@ class TimeseriesChart extends Component { }); if (item) { - const metric = series.find(r => r.id === item.series.id); - const formatter = metric && metric.tickFormatter || this.props.tickFormatter || ((v) => v); - const value = item.datapoint[2] ? item.datapoint[1] - item.datapoint[2] : item.datapoint[1]; + const rows = dataPoints.map(point => { + const metric = series.find(r => r.id === point.series.id); + const formatter = metric && metric.tickFormatter || this.props.tickFormatter || ((v) => v); + const value = point.datapoint[2] ? point.datapoint[1] - point.datapoint[2] : point.datapoint[1]; + + return ( +
+
+ +
+
{point.series.label}
+
{formatter(value)}
+
+ ); + }, this); + tooltip = (
-
-
- -
-
{ item.series.label }
-
{ formatter(value) }
-
-
{ moment(item.datapoint[0]).format(this.props.dateFormat) }
+ {rows} +
{ moment(timestamp).format(this.props.dateFormat) }
diff --git a/src/ui/public/visualize/visualize.less b/src/ui/public/visualize/visualize.less index caf6292b44c64..0739036f08c5a 100644 --- a/src/ui/public/visualize/visualize.less +++ b/src/ui/public/visualize/visualize.less @@ -5,7 +5,6 @@ visualization { flex-direction: column; height: auto; width: 100%; - overflow: auto; position: relative; padding: 8px 8px 8px 8px; From 6562bc7f93c9dec535b47b5c6177f8c54bc15b2b Mon Sep 17 00:00:00 2001 From: shaharmor Date: Mon, 27 Nov 2017 12:22:54 +0200 Subject: [PATCH 2/2] only take into consideration the x axis when choosing a nearby point --- src/ui/public/flot-charts/jquery.flot.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/ui/public/flot-charts/jquery.flot.js b/src/ui/public/flot-charts/jquery.flot.js index 39f3e4cf3efe5..e748651856263 100644 --- a/src/ui/public/flot-charts/jquery.flot.js +++ b/src/ui/public/flot-charts/jquery.flot.js @@ -2010,7 +2010,7 @@ Licensed under the MIT license. ctx.lineTo(xrange.to + subPixel, yrange.to); } else { ctx.moveTo(xrange.from, yrange.to + subPixel); - ctx.lineTo(xrange.to, yrange.to + subPixel); + ctx.lineTo(xrange.to, yrange.to + subPixel); } ctx.stroke(); } else { @@ -2525,9 +2525,9 @@ Licensed under the MIT license. radius = series.points.radius, symbol = series.points.symbol; - // If the user sets the line width to 0, we change it to a very + // If the user sets the line width to 0, we change it to a very // small value. A line width of 0 seems to force the default of 1. - // Doing the conditional here allows the shadow setting to still be + // Doing the conditional here allows the shadow setting to still be // optional even with a lineWidth of 0. if( lw == 0 ) @@ -2854,22 +2854,18 @@ Licensed under the MIT license. if (s.lines.show || s.points.show) { for (j = 0; j < points.length; j += ps) { - var x = points[j], y = points[j + 1]; + var x = points[j]; if (x == null) continue; + // calculate the "distance" from the the datapoint + var dist = Math.abs(x - mx); + // For points and lines, the cursor must be within a // certain distance to the data point - if (x - mx > maxx || x - mx < -maxx || - y - my > maxy || y - my < -maxy) + if (dist > maxx) continue; - // We have to calculate distances in pixels, not in - // data units, because the scales of the axes may be different - var dx = Math.abs(axisx.p2c(x) - mouseX), - dy = Math.abs(axisy.p2c(y) - mouseY), - dist = dx * dx + dy * dy; // we save the sqrt - // use <= to ensure last point takes precedence // (last generally means on top of) if (dist < smallestDistance) {