diff --git a/client/app/scripts/components/node-details/node-details-health-item.js b/client/app/scripts/components/node-details/node-details-health-item.js index 2004016ec..be6a205ef 100644 --- a/client/app/scripts/components/node-details/node-details-health-item.js +++ b/client/app/scripts/components/node-details/node-details-health-item.js @@ -4,17 +4,18 @@ import Sparkline from '../sparkline'; import { formatMetric } from '../../utils/string-utils'; function NodeDetailsHealthItem(props) { + const labelStyle = { color: props.labelColor }; return (
- {!props.valueEmpty &&
{formatMetric(props.value, props)}
} + {!props.valueEmpty &&
{formatMetric(props.value, props)}
}
-
+
{props.label}
diff --git a/client/app/scripts/components/node-details/node-details-health-link-item.js b/client/app/scripts/components/node-details/node-details-health-link-item.js index d6a43f662..72f1fc6ec 100644 --- a/client/app/scripts/components/node-details/node-details-health-link-item.js +++ b/client/app/scripts/components/node-details/node-details-health-link-item.js @@ -3,6 +3,7 @@ import React from 'react'; import NodeDetailsHealthItem from './node-details-health-item'; import CloudLink from '../cloud-link'; import { getMetricColor } from '../../utils/metric-utils'; +import { darkenColor } from '../../utils/color-utils'; import { trackMixpanelEvent } from '../../utils/tracking-utils'; export default class NodeDetailsHealthLinkItem extends React.Component { @@ -33,6 +34,7 @@ export default class NodeDetailsHealthLinkItem extends React.Component { render() { const { id, url, ...props } = this.props; const metricColor = getMetricColor(id); + const labelColor = this.state.hovered && !props.valueEmpty && darkenColor(metricColor); return ( diff --git a/client/app/scripts/components/node-details/node-details-health-overflow-item.js b/client/app/scripts/components/node-details/node-details-health-overflow-item.js deleted file mode 100644 index 4372d87de..000000000 --- a/client/app/scripts/components/node-details/node-details-health-overflow-item.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; - -import { formatMetric } from '../../utils/string-utils'; - -function NodeDetailsHealthOverflowItem(props) { - return ( -
-
- {!props.valueEmpty && formatMetric(props.value, props)} -
-
{props.label}
-
- ); -} - -export default NodeDetailsHealthOverflowItem; diff --git a/client/app/scripts/components/node-details/node-details-health-overflow.js b/client/app/scripts/components/node-details/node-details-health-overflow.js deleted file mode 100644 index 537c3a695..000000000 --- a/client/app/scripts/components/node-details/node-details-health-overflow.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; - -import NodeDetailsHealthOverflowItem from './node-details-health-overflow-item'; - -export default class NodeDetailsHealthOverflow extends React.Component { - - constructor(props, context) { - super(props, context); - this.handleClick = this.handleClick.bind(this); - } - - handleClick(ev) { - ev.preventDefault(); - this.props.handleClick(); - } - - render() { - const items = this.props.items.slice(0, 4); - - return ( -
- {items.map(item => )} -
- ); - } -} diff --git a/client/app/scripts/components/node-details/node-details-health.js b/client/app/scripts/components/node-details/node-details-health.js index 58fad14a3..8d763656d 100644 --- a/client/app/scripts/components/node-details/node-details-health.js +++ b/client/app/scripts/components/node-details/node-details-health.js @@ -1,7 +1,6 @@ import React from 'react'; import ShowMore from '../show-more'; -import NodeDetailsHealthOverflow from './node-details-health-overflow'; import NodeDetailsHealthLinkItem from './node-details-health-link-item'; export default class NodeDetailsHealth extends React.Component { @@ -25,30 +24,38 @@ export default class NodeDetailsHealth extends React.Component { topologyId, } = this.props; - const primeCutoff = metrics.length > 3 && !this.state.expanded ? 2 : metrics.length; - const primeMetrics = metrics.slice(0, primeCutoff); - const overflowMetrics = metrics.slice(primeCutoff); - const showOverflow = overflowMetrics.length > 0 && !this.state.expanded; - const flexWrap = showOverflow || !this.state.expanded ? 'nowrap' : 'wrap'; - const justifyContent = showOverflow || !this.state.expanded ? 'space-around' : 'flex-start'; - const notShown = overflowMetrics.length; + let primeMetrics = metrics.filter(m => !m.valueEmpty); + let emptyMetrics = metrics.filter(m => m.valueEmpty); + + if (primeMetrics.length === 0 && emptyMetrics.length > 0) { + primeMetrics = emptyMetrics; + emptyMetrics = []; + } + + const shownWithData = this.state.expanded ? primeMetrics : primeMetrics.slice(0, 3); + const shownEmpty = this.state.expanded ? emptyMetrics : []; + const notShown = metrics.length - shownWithData.length - shownEmpty.length; return ( -
+
- {primeMetrics.map(item => )} +
+
+ {shownEmpty.map(item => )} - {showOverflow && }
+ handleClick={this.handleClickMore} collection={metrics} + expanded={this.state.expanded} notShown={notShown} hideNumber={this.state.expanded} + />
); } diff --git a/client/app/scripts/components/sparkline.js b/client/app/scripts/components/sparkline.js index b11e12262..898bd5f41 100644 --- a/client/app/scripts/components/sparkline.js +++ b/client/app/scripts/components/sparkline.js @@ -7,11 +7,11 @@ import { line, curveLinear } from 'd3-shape'; import { scaleLinear } from 'd3-scale'; import { formatMetricSvg } from '../utils/string-utils'; -import { brightenColor, darkenColor } from '../utils/color-utils'; const HOVER_RADIUS_MULTIPLY = 1.5; const HOVER_STROKE_MULTIPLY = 5; +const MARGIN = 2; export default class Sparkline extends React.Component { constructor(props, context) { @@ -24,11 +24,15 @@ export default class Sparkline extends React.Component { .y(d => this.y(d.value)); } - initRanges() { + initRanges(hasCircle) { // adjust scales and leave some room for the circle on the right, upper, and lower edge - const padding = 2 + Math.ceil(this.props.circleRadius * HOVER_RADIUS_MULTIPLY); - this.x.range([2, this.props.width - padding]); - this.y.range([this.props.height - padding, padding]); + let circleSpace = MARGIN; + if (hasCircle) { + circleSpace += Math.ceil(this.props.circleRadius * HOVER_RADIUS_MULTIPLY); + } + + this.x.range([MARGIN, this.props.width - circleSpace]); + this.y.range([this.props.height - circleSpace, circleSpace]); this.line.curve(this.props.curve); } @@ -36,7 +40,7 @@ export default class Sparkline extends React.Component { // data is of shape [{date, value}, ...] and is sorted by date (ASC) let data = this.props.data; - this.initRanges(); + this.initRanges(true); // Convert dates into D3 dates data = data.map(d => ({ @@ -75,7 +79,7 @@ export default class Sparkline extends React.Component { } getEmptyGraphData() { - this.initRanges(); + this.initRanges(false); const first = new Date(0); const last = new Date(15); this.x.domain([first, last]); @@ -93,43 +97,30 @@ export default class Sparkline extends React.Component { } render() { - let strokeColor = this.props.strokeColor; - let strokeWidth = this.props.strokeWidth; - let radius = this.props.circleRadius; - let fillOpacity = 0.6; - let circleColor; - let graph = {}; - - if (!this.props.data || this.props.data.length === 0 || this.props.data[0].date === undefined) { - // no data means just a dead line w/o circle - graph = this.getEmptyGraphData(); - strokeColor = brightenColor(strokeColor); - radius = 0; - } else { - graph = this.getGraphData(); - - if (this.props.hovered) { - strokeColor = this.props.hoverColor; - circleColor = strokeColor; - strokeWidth *= HOVER_STROKE_MULTIPLY; - radius *= HOVER_RADIUS_MULTIPLY; - fillOpacity = 1; - } else { - circleColor = darkenColor(strokeColor); - } - } + const dash = 5; + const hasData = this.props.data && this.props.data.length > 0; + const strokeColor = this.props.hovered && hasData + ? this.props.hoverColor + : this.props.strokeColor; + const strokeWidth = this.props.strokeWidth * (this.props.hovered ? HOVER_STROKE_MULTIPLY : 1); + const strokeDasharray = hasData || `${dash}, ${dash}`; + const radius = this.props.circleRadius * (this.props.hovered ? HOVER_RADIUS_MULTIPLY : 1); + const fillOpacity = this.props.hovered ? 1 : 0.6; + const circleColor = hasData && this.props.hovered ? strokeColor : strokeColor; + const graph = hasData ? this.getGraphData() : this.getEmptyGraphData(); return (
- + />}
);