Closes #13471 - Change split behavior of gauges and metrics vis (#13583)

* Closes #13471 - Change split behavior of gauges and metrics vis

* removing old css classes
This commit is contained in:
Chris Cowan 2017-08-28 11:35:03 -07:00
parent 8071ff5cd6
commit 24c7fdf67f
10 changed files with 141 additions and 5 deletions

View file

@ -0,0 +1,3 @@
export function getDisplayName(Component) {
return Component.displayName || Component.name || 'Component';
}

View file

@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
import { visWithSplits } from '../../vis_with_splits';
import tickFormatter from '../../lib/tick_formatter';
import _ from 'lodash';
import Gauge from 'plugins/metrics/visualizations/components/gauge';
@ -29,6 +30,7 @@ function GaugeVisualization(props) {
const { backgroundColor, model, visData } = props;
const colors = getColors(props);
const series = _.get(visData, `${model.id}.series`, [])
.filter(row => row)
.map((row, i) => {
const seriesDef = model.series.find(s => _.includes(row.id, s.id));
const newProps = {};
@ -41,7 +43,8 @@ function GaugeVisualization(props) {
const params = {
metric: series[0],
type: model.gauge_style || 'half',
reversed: props.reversed
reversed: props.reversed,
additionalLabel: props.additionalLabel
};
if (colors.text) {
@ -70,6 +73,7 @@ function GaugeVisualization(props) {
GaugeVisualization.propTypes = {
backgroundColor: PropTypes.string,
className: PropTypes.string,
additionalLabel: PropTypes.string,
model: PropTypes.object,
onBrush: PropTypes.func,
onChange: PropTypes.func,
@ -77,4 +81,4 @@ GaugeVisualization.propTypes = {
visData: PropTypes.object
};
export default GaugeVisualization;
export default visWithSplits(GaugeVisualization);

View file

@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
import { visWithSplits } from '../../vis_with_splits';
import tickFormatter from '../../lib/tick_formatter';
import _ from 'lodash';
import Metric from 'plugins/metrics/visualizations/components/metric';
@ -29,6 +30,7 @@ function MetricVisualization(props) {
const { backgroundColor, model, visData } = props;
const colors = getColors(props);
const series = _.get(visData, `${model.id}.series`, [])
.filter(row => row)
.map((row, i) => {
const seriesDef = model.series.find(s => _.includes(row.id, s.id));
const newProps = {};
@ -40,7 +42,8 @@ function MetricVisualization(props) {
});
const params = {
metric: series[0],
reversed: props.reversed
reversed: props.reversed,
additionalLabel: props.additionalLabel
};
if (series[1]) {
params.secondary = series[1];
@ -63,6 +66,7 @@ function MetricVisualization(props) {
MetricVisualization.propTypes = {
backgroundColor: PropTypes.string,
className: PropTypes.string,
additionalLabel: PropTypes.string,
model: PropTypes.object,
onBrush: PropTypes.func,
onChange: PropTypes.func,
@ -70,4 +74,4 @@ MetricVisualization.propTypes = {
visData: PropTypes.object
};
export default MetricVisualization;
export default visWithSplits(MetricVisualization);

View file

@ -0,0 +1,68 @@
import React from 'react';
import { getDisplayName } from './lib/get_display_name';
import { last, findIndex, first } from 'lodash';
import calculateLabel from '../../common/calculate_label';
export function visWithSplits(WrappedComponent) {
function SplitVisComponent(props) {
const { model, visData } = props;
if (visData[model.id].series.every(s => s.id.split(':').length === 1)) {
return (<WrappedComponent {...props} />);
}
const splitsVisData = visData[model.id].series.reduce((acc, series) => {
const [seriesId, splitId] = series.id.split(':');
const seriesModel = model.series.find(s => s.id === seriesId);
if (!seriesModel || !splitId) return acc;
const metric = last(seriesModel.metrics);
const label = calculateLabel(metric, seriesModel.metrics);
if (!acc[splitId]) acc[splitId] = { series: [], label: series.label };
acc[splitId].series.push({
...series,
id: seriesId,
color: seriesModel.color,
label: seriesModel.label || label
});
return acc;
}, {});
const nonSplitSeries = first(visData[model.id].series.filter((series) => {
const seriesModel = model.series.find(s => s.id === series.id);
if (!seriesModel) return false;
return ['everything', 'filter'].includes(seriesModel.split_mode);
}));
const indexOfNonSplit = nonSplitSeries ? findIndex(model.series, s => s.id === nonSplitSeries.id) : null;
const rows = Object.keys(splitsVisData).map(key => {
const splitData = splitsVisData[key];
const { series, label } = splitData;
const newSeries = (indexOfNonSplit != null && indexOfNonSplit > 0) ? [...series, nonSplitSeries] : [nonSplitSeries, ...series];
const newVisData = {
[model.id]: {
id: model.id,
series: newSeries || series
}
};
return (
<div key={key} className="splitVis_split">
<div className="splitVis_visualization">
<WrappedComponent
model={model}
visData={newVisData}
onBrush={props.onBrush}
additionalLabel={label}
backgroundColor={props.backgroundColor}
/>
</div>
</div>
);
});
return (
<div className="splitVis">{rows}</div>
);
}
SplitVisComponent.displayName = `SplitVisComponent(${getDisplayName(WrappedComponent)})`;
return SplitVisComponent;
}

View file

@ -36,5 +36,6 @@
@import './sortable.less';
@import './color_picker.less';
@import './error.less';
@import './split_vis.less';

View file

@ -0,0 +1,16 @@
.splitVis {
display: flex;
flex: 1 0 auto;
}
.splitVis_split {
display: flex;
flex: 1 0 0;
flex-direction: column;
overflow: hidden;
}
.splitVis_visualization {
position: relative;
flex: 1 0 auto;
}

View file

@ -88,6 +88,14 @@ class Gauge extends Component {
};
let metrics;
let additionalLabel;
if (this.props.additionalLabel) {
additionalLabel = (
<div className="thorGauge_additionalLabel">
{this.props.additionalLabel}
</div>
);
}
if (type === 'half') {
metrics = (
<div
@ -106,6 +114,7 @@ class Gauge extends Component {
ref="label"
>{ formatter(value) }
</div>
{additionalLabel}
</div>
);
} else {
@ -126,6 +135,7 @@ class Gauge extends Component {
ref="title"
>{ title }
</div>
{additionalLabel}
</div>
);
}
@ -161,6 +171,7 @@ Gauge.propTypes = {
reversed: PropTypes.bool,
type: PropTypes.oneOf(['half', 'circle']),
valueColor: PropTypes.string,
additionalLabel: PropTypes.string
};
export default Gauge;

View file

@ -117,6 +117,15 @@ class Metric extends Component {
);
}
let additionalLabel;
if (this.props.additionalLabel) {
additionalLabel = (
<div className="rhythm_metric__additionalLabel">
{this.props.additionalLabel}
</div>
);
}
return (
<div className="rhythm_metric" style={styles.container}>
<div
@ -129,6 +138,7 @@ class Metric extends Component {
<div style={styles.primary_value} className="rhythm_metric__primary-value">{ primaryValue }</div>
</div>
{ secondarySnippet }
{additionalLabel}
</div>
</div>
</div>
@ -141,7 +151,8 @@ Metric.propTypes = {
backgroundColor: PropTypes.string,
metric: PropTypes.object,
secondary: PropTypes.object,
reversed: PropTypes.bool
reversed: PropTypes.bool,
additionalLabel: PropTypes.string
};
export default Metric;

View file

@ -39,6 +39,15 @@
color: @black;
}
.thorGauge_additionalLabel {
font-size: 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 100%;
padding: 0 5px;
}
.thorCircleGauge__resize {
position: relative;
display: flex;

View file

@ -60,3 +60,12 @@
padding: 0.25em 0.5em 0.5em;
}
.rhythm_metric__additionalLabel {
font-size: 0.25em;
width: 50px;
overflow: hidden;
text-overflow: ellipsis;
padding: 2px 0 0 0;
white-space: nowrap;
text-align: center;
}