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)}
}
-
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 (
);