diff --git a/src/legacy/core_plugins/metrics/public/visualizations/components/_top_n.scss b/src/legacy/core_plugins/metrics/public/visualizations/components/_top_n.scss index 6392e437bc0a6..fb6be95dba2a2 100644 --- a/src/legacy/core_plugins/metrics/public/visualizations/components/_top_n.scss +++ b/src/legacy/core_plugins/metrics/public/visualizations/components/_top_n.scss @@ -35,7 +35,12 @@ } .tvbVisTopN__innerBar { - min-height: $euiSize; + position: relative; + + > div { + width: 100%; + min-height: $euiSize; + } } .tvbVisTopN--reversed { diff --git a/src/legacy/core_plugins/metrics/public/visualizations/components/top_n.js b/src/legacy/core_plugins/metrics/public/visualizations/components/top_n.js index ea8f795b7620d..5734d101a09d2 100644 --- a/src/legacy/core_plugins/metrics/public/visualizations/components/top_n.js +++ b/src/legacy/core_plugins/metrics/public/visualizations/components/top_n.js @@ -22,6 +22,12 @@ import React, { Component } from 'react'; import { getLastValue } from '../../../common/get_last_value'; import reactcss from 'reactcss'; +const RENDER_MODES = { + POSITIVE: 'positive', + NEGATIVE: 'negative', + MIXED: 'mixed', +}; + export class TopN extends Component { constructor(props) { super(props); @@ -59,20 +65,61 @@ export class TopN extends Component { }; } - renderRow(maxValue) { + static getRenderMode = (min, max) => { + if (min >= 0) { + return RENDER_MODES.POSITIVE; + } else if (max < 0) { + return RENDER_MODES.NEGATIVE; + } + return RENDER_MODES.MIXED; + }; + + static calcInnerBarStyles = (renderMode, isPositive) => { + if (renderMode === RENDER_MODES.MIXED) { + return { + [isPositive ? 'marginLeft' : 'marginRight']: '50%', + }; + } + return {}; + }; + + static calcInnerBarDivStyles = (item, width, isPositive) => { + return { + backgroundColor: item.color, + width: width + '%', + float: isPositive ? 'left' : 'right', + }; + }; + + static calcDomain = (renderMode, min, max) => { + if (renderMode === RENDER_MODES.MIXED) { + return Math.max(max, Math.abs(min)); + } else if (renderMode === RENDER_MODES.NEGATIVE) { + return Math.abs(min); + } + + return max; + }; + + renderRow({ min, max }) { return item => { + const renderMode = TopN.getRenderMode(min, max); const key = `${item.id || item.label}`; const lastValue = getLastValue(item.data); const formatter = item.tickFormatter || this.props.tickFormatter; - const value = formatter(lastValue); - const width = `${100 * (lastValue / maxValue)}%`; - const backgroundColor = item.color; + const isPositiveValue = lastValue >= 0; + + const intervalLength = TopN.calcDomain(renderMode, min, max); + const width = 100 * (Math.abs(lastValue) / intervalLength); + const styles = reactcss( { default: { innerBar: { - width, - backgroundColor, + ...TopN.calcInnerBarStyles(renderMode, isPositiveValue), + }, + innerBarValue: { + ...TopN.calcInnerBarDivStyles(item, width, isPositiveValue), }, label: { maxWidth: this.state.labelMaxWidth, @@ -92,10 +139,12 @@ export class TopN extends Component { {item.label}