Commit 5e7f7e65 by Ryan McKinley Committed by Torkel Ödegaard

Singlestat-v2/Gauge: Show title when repeating (#16477)

* show title in singlestat2

* show title in gauge

* use CSS class for emotion

* use emotion not scss
parent 06dfbb38
// Library // Library
import React, { PureComponent, ReactNode, CSSProperties } from 'react'; import React, { PureComponent, ReactNode, CSSProperties } from 'react';
import $ from 'jquery'; import $ from 'jquery';
import { css } from 'emotion';
// Utils // Utils
import { getColorFromHexRgbOrName } from '../../utils'; import { getColorFromHexRgbOrName } from '../../utils';
...@@ -98,36 +99,67 @@ export class BigValue extends PureComponent<Props> { ...@@ -98,36 +99,67 @@ export class BigValue extends PureComponent<Props> {
return <span style={css}>{value.text}</span>; return <span style={css}>{value.text}</span>;
}; };
render() { renderSparkline(sparkline: BigValueSparkline) {
const { height, width, value, prefix, suffix, sparkline, backgroundColor } = this.props; const { height, width } = this.props;
const plotCss: CSSProperties = {}; const plotCss: CSSProperties = {};
plotCss.position = 'absolute'; plotCss.position = 'absolute';
plotCss.bottom = '0px';
plotCss.left = '0px';
plotCss.width = width + 'px';
if (sparkline) {
if (sparkline.full) { if (sparkline.full) {
plotCss.bottom = '5px';
plotCss.left = '-5px';
plotCss.width = width - 10 + 'px';
const dynamicHeightMargin = height <= 100 ? 5 : Math.round(height / 100) * 15 + 5; const dynamicHeightMargin = height <= 100 ? 5 : Math.round(height / 100) * 15 + 5;
plotCss.height = height - dynamicHeightMargin + 'px'; plotCss.height = height - dynamicHeightMargin + 'px';
} else { } else {
plotCss.bottom = '0px';
plotCss.left = '-5px';
plotCss.width = width - 10 + 'px';
plotCss.height = Math.floor(height * 0.25) + 'px'; plotCss.height = Math.floor(height * 0.25) + 'px';
} }
return <div style={plotCss} ref={element => (this.canvasElement = element)} />;
} }
render() {
const { height, width, value, prefix, suffix, sparkline, backgroundColor } = this.props;
return ( return (
<div className="big-value" style={{ width, height, backgroundColor }}> <div
<span className="big-value__value"> className={css({
position: 'relative',
display: 'table',
})}
style={{ width, height, backgroundColor }}
>
{value.title && (
<div
className={css({
lineHeight: 1,
textAlign: 'center',
zIndex: 1,
display: 'block',
width: '100%',
position: 'absolute',
})}
>
{value.title}
</div>
)}
<span
className={css({
lineHeight: 1,
textAlign: 'center',
zIndex: 1,
display: 'table-cell',
verticalAlign: 'middle',
position: 'relative',
fontSize: '3em',
fontWeight: 500, // TODO: $font-weight-semi-bold
})}
>
{this.renderText(prefix, '0px 2px 0px 0px')} {this.renderText(prefix, '0px 2px 0px 0px')}
{this.renderText(value)} {this.renderText(value)}
{this.renderText(suffix)} {this.renderText(suffix)}
</span> </span>
{sparkline && <div style={plotCss} ref={element => (this.canvasElement = element)} />} {sparkline && this.renderSparkline(sparkline)}
</div> </div>
); );
} }
......
.big-value {
position: relative;
display: table;
}
.big-value__value {
line-height: 1;
display: table-cell;
vertical-align: middle;
text-align: center;
position: relative;
z-index: 1;
font-size: 3em;
font-weight: $font-weight-semi-bold;
}
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import $ from 'jquery'; import $ from 'jquery';
import { css } from 'emotion';
import { getColorFromHexRgbOrName } from '../../utils'; import { getColorFromHexRgbOrName } from '../../utils';
import { DisplayValue, Threshold, GrafanaThemeType, Themeable } from '../../types'; import { DisplayValue, Threshold, GrafanaThemeType, Themeable } from '../../types';
...@@ -119,18 +120,31 @@ export class Gauge extends PureComponent<Props> { ...@@ -119,18 +120,31 @@ export class Gauge extends PureComponent<Props> {
} }
render() { render() {
const { height, width } = this.props; const { height, width, value } = this.props;
return ( return (
<div <div
style={{ style={{
height: `${Math.min(height, width * 1.3)}px`, height: `${Math.min(height, width * 1.3)}px`,
width: `${Math.min(width, height * 1.3)}px`, width: `${Math.min(width, height * 1.3)}px`,
top: '10px',
margin: 'auto', margin: 'auto',
marginTop: '-8px',
}} }}
ref={element => (this.canvasElement = element)} ref={element => (this.canvasElement = element)}
/> >
{value.title && (
<div
className={css({
textAlign: 'center',
bottom: -8,
width: '100%',
position: 'absolute',
})}
>
{value.title}
</div>
)}
</div>
); );
} }
} }
...@@ -74,7 +74,9 @@ export const getSingleStatDisplayValues = (options: GetSingleStatDisplayValueOpt ...@@ -74,7 +74,9 @@ export const getSingleStatDisplayValues = (options: GetSingleStatDisplayValueOpt
}); });
const displayValue = display(stats[stat]); const displayValue = display(stats[stat]);
displayValue.title = series.name; if (series.name) {
displayValue.title = replaceVariables(series.name);
}
values.push(displayValue); values.push(displayValue);
} }
} }
...@@ -86,6 +88,9 @@ export const getSingleStatDisplayValues = (options: GetSingleStatDisplayValueOpt ...@@ -86,6 +88,9 @@ export const getSingleStatDisplayValues = (options: GetSingleStatDisplayValueOpt
numeric: 0, numeric: 0,
text: 'No data', text: 'No data',
}); });
} else if (values.length === 1) {
// Don't show title for single item
values[0].title = undefined;
} }
return values; return values;
......
@import 'CustomScrollbar/CustomScrollbar'; @import 'CustomScrollbar/CustomScrollbar';
@import 'BigValue/BigValue';
@import 'DeleteButton/DeleteButton'; @import 'DeleteButton/DeleteButton';
@import 'ThresholdsEditor/ThresholdsEditor'; @import 'ThresholdsEditor/ThresholdsEditor';
@import 'Table/Table'; @import 'Table/Table';
......
...@@ -55,10 +55,10 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions> ...@@ -55,10 +55,10 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>
const timeColumn = sparkline.show ? getFirstTimeField(series) : -1; const timeColumn = sparkline.show ? getFirstTimeField(series) : -1;
for (let i = 0; i < series.fields.length; i++) { for (let i = 0; i < series.fields.length; i++) {
const column = series.fields[i]; const field = series.fields[i];
// Show all fields that are not 'time' // Show all fields that are not 'time'
if (column.type === FieldType.number) { if (field.type === FieldType.number) {
const stats = calculateStats({ const stats = calculateStats({
series, series,
fieldIndex: i, fieldIndex: i,
...@@ -69,6 +69,7 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions> ...@@ -69,6 +69,7 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>
const v: SingleStatDisplay = { const v: SingleStatDisplay = {
value: display(stats[stat]), value: display(stats[stat]),
}; };
v.value.title = replaceVariables(field.name);
const color = v.value.color; const color = v.value.color;
if (!colorValue) { if (!colorValue) {
...@@ -121,6 +122,11 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions> ...@@ -121,6 +122,11 @@ export class SingleStatPanel extends PureComponent<PanelProps<SingleStatOptions>
} }
} }
// Don't show a title if there is only one item
if (values.length === 1) {
values[0].value.title = null;
}
return values; return values;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment