2019-08-13 00:32:43 -05:00
|
|
|
import React, { PureComponent } from 'react';
|
2021-04-01 07:15:23 -05:00
|
|
|
import { css, cx } from '@emotion/css';
|
2020-04-27 08:28:06 -05:00
|
|
|
import { GrafanaTheme, TimeZone, AbsoluteTimeRange, GraphSeriesXY, dateTime } from '@grafana/data';
|
2019-08-26 01:11:07 -05:00
|
|
|
|
|
|
|
import {
|
|
|
|
selectThemeVariant,
|
|
|
|
Themeable,
|
|
|
|
GraphWithLegend,
|
|
|
|
LegendDisplayMode,
|
|
|
|
withTheme,
|
|
|
|
Collapse,
|
|
|
|
GraphSeriesToggler,
|
|
|
|
GraphSeriesTogglerAPI,
|
2021-04-20 02:45:41 -05:00
|
|
|
VizTooltip,
|
2020-04-12 15:20:02 -05:00
|
|
|
Icon,
|
2021-04-20 02:45:41 -05:00
|
|
|
TooltipDisplayMode,
|
2019-08-26 01:11:07 -05:00
|
|
|
} from '@grafana/ui';
|
2019-08-13 00:32:43 -05:00
|
|
|
|
|
|
|
const MAX_NUMBER_OF_TIME_SERIES = 20;
|
|
|
|
|
2019-08-26 01:11:07 -05:00
|
|
|
const getStyles = (theme: GrafanaTheme) => ({
|
|
|
|
timeSeriesDisclaimer: css`
|
|
|
|
label: time-series-disclaimer;
|
|
|
|
width: 300px;
|
|
|
|
margin: ${theme.spacing.sm} auto;
|
|
|
|
padding: 10px 0;
|
|
|
|
border-radius: ${theme.border.radius.md};
|
|
|
|
text-align: center;
|
2020-04-12 08:05:49 -05:00
|
|
|
background-color: ${selectThemeVariant({ light: theme.palette.white, dark: theme.palette.dark4 }, theme.type)};
|
2019-08-26 01:11:07 -05:00
|
|
|
`,
|
|
|
|
disclaimerIcon: css`
|
|
|
|
label: disclaimer-icon;
|
2020-04-12 08:05:49 -05:00
|
|
|
color: ${theme.palette.yellow};
|
2019-08-26 01:11:07 -05:00
|
|
|
margin-right: ${theme.spacing.xs};
|
|
|
|
`,
|
|
|
|
showAllTimeSeries: css`
|
|
|
|
label: show-all-time-series;
|
|
|
|
cursor: pointer;
|
|
|
|
color: ${theme.colors.linkExternal};
|
|
|
|
`,
|
|
|
|
});
|
|
|
|
|
|
|
|
interface Props extends Themeable {
|
2020-08-28 11:59:56 -05:00
|
|
|
ariaLabel?: string;
|
2020-07-09 08:16:35 -05:00
|
|
|
series?: GraphSeriesXY[] | null;
|
2019-08-13 00:32:43 -05:00
|
|
|
width: number;
|
2019-08-26 01:11:07 -05:00
|
|
|
absoluteRange: AbsoluteTimeRange;
|
2019-11-26 03:01:32 -06:00
|
|
|
loading?: boolean;
|
2019-08-26 01:11:07 -05:00
|
|
|
showPanel: boolean;
|
|
|
|
showBars: boolean;
|
|
|
|
showLines: boolean;
|
|
|
|
isStacked: boolean;
|
2019-11-26 03:01:32 -06:00
|
|
|
timeZone?: TimeZone;
|
2019-08-26 01:11:07 -05:00
|
|
|
onUpdateTimeRange: (absoluteRange: AbsoluteTimeRange) => void;
|
2019-08-13 00:32:43 -05:00
|
|
|
onHiddenSeriesChanged?: (hiddenSeries: string[]) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface State {
|
|
|
|
hiddenSeries: string[];
|
|
|
|
showAllTimeSeries: boolean;
|
|
|
|
}
|
|
|
|
|
2019-08-26 01:11:07 -05:00
|
|
|
class UnThemedExploreGraphPanel extends PureComponent<Props, State> {
|
2019-08-13 00:32:43 -05:00
|
|
|
state: State = {
|
|
|
|
hiddenSeries: [],
|
|
|
|
showAllTimeSeries: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
onShowAllTimeSeries = () => {
|
|
|
|
this.setState({
|
|
|
|
showAllTimeSeries: true,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-09-16 02:31:22 -05:00
|
|
|
onChangeTime = (from: number, to: number) => {
|
2019-08-26 01:11:07 -05:00
|
|
|
const { onUpdateTimeRange } = this.props;
|
2019-09-16 02:31:22 -05:00
|
|
|
onUpdateTimeRange({ from, to });
|
2019-08-13 00:32:43 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
renderGraph = () => {
|
|
|
|
const {
|
2020-08-28 11:59:56 -05:00
|
|
|
ariaLabel,
|
2019-08-13 00:32:43 -05:00
|
|
|
width,
|
|
|
|
series,
|
|
|
|
onHiddenSeriesChanged,
|
|
|
|
timeZone,
|
|
|
|
absoluteRange,
|
2019-08-26 01:11:07 -05:00
|
|
|
showPanel,
|
|
|
|
showBars,
|
|
|
|
showLines,
|
|
|
|
isStacked,
|
2019-08-13 00:32:43 -05:00
|
|
|
} = this.props;
|
|
|
|
const { showAllTimeSeries } = this.state;
|
|
|
|
|
|
|
|
if (!series) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const timeRange = {
|
2020-04-27 08:28:06 -05:00
|
|
|
from: dateTime(absoluteRange.from),
|
|
|
|
to: dateTime(absoluteRange.to),
|
2019-08-13 00:32:43 -05:00
|
|
|
raw: {
|
2020-04-27 08:28:06 -05:00
|
|
|
from: dateTime(absoluteRange.from),
|
|
|
|
to: dateTime(absoluteRange.to),
|
2019-08-13 00:32:43 -05:00
|
|
|
},
|
|
|
|
};
|
2020-04-27 08:28:06 -05:00
|
|
|
|
2020-09-22 10:31:42 -05:00
|
|
|
const height = showPanel ? 200 : 100;
|
2019-08-26 01:11:07 -05:00
|
|
|
const lineWidth = showLines ? 1 : 5;
|
2019-08-13 00:32:43 -05:00
|
|
|
const seriesToShow = showAllTimeSeries ? series : series.slice(0, MAX_NUMBER_OF_TIME_SERIES);
|
|
|
|
return (
|
|
|
|
<GraphSeriesToggler series={seriesToShow} onHiddenSeriesChanged={onHiddenSeriesChanged}>
|
2019-08-26 01:11:07 -05:00
|
|
|
{({ onSeriesToggle, toggledSeries }: GraphSeriesTogglerAPI) => {
|
2019-08-13 00:32:43 -05:00
|
|
|
return (
|
|
|
|
<GraphWithLegend
|
2020-08-28 11:59:56 -05:00
|
|
|
ariaLabel={ariaLabel}
|
2020-11-13 10:08:55 -06:00
|
|
|
legendDisplayMode={LegendDisplayMode.List}
|
2019-08-13 00:32:43 -05:00
|
|
|
height={height}
|
2020-11-09 08:31:03 -06:00
|
|
|
placement={'bottom'}
|
2019-08-13 00:32:43 -05:00
|
|
|
width={width}
|
|
|
|
timeRange={timeRange}
|
|
|
|
timeZone={timeZone}
|
|
|
|
showBars={showBars}
|
|
|
|
showLines={showLines}
|
|
|
|
showPoints={false}
|
|
|
|
onToggleSort={() => {}}
|
|
|
|
series={toggledSeries}
|
|
|
|
isStacked={isStacked}
|
|
|
|
lineWidth={lineWidth}
|
|
|
|
onSeriesToggle={onSeriesToggle}
|
2019-09-16 02:31:22 -05:00
|
|
|
onHorizontalRegionSelected={this.onChangeTime}
|
2019-11-07 05:37:46 -06:00
|
|
|
>
|
|
|
|
{/* For logs we are using mulit mode until we refactor logs histogram to use barWidth instead of lineWidth to render bars */}
|
2021-04-20 02:45:41 -05:00
|
|
|
<VizTooltip mode={showBars ? TooltipDisplayMode.Multi : TooltipDisplayMode.Single} />
|
2019-11-07 05:37:46 -06:00
|
|
|
</GraphWithLegend>
|
2019-08-13 00:32:43 -05:00
|
|
|
);
|
|
|
|
}}
|
|
|
|
</GraphSeriesToggler>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
2020-09-22 10:31:42 -05:00
|
|
|
const { series, showPanel, loading, theme } = this.props;
|
2019-08-13 00:32:43 -05:00
|
|
|
const { showAllTimeSeries } = this.state;
|
2019-08-26 01:11:07 -05:00
|
|
|
const style = getStyles(theme);
|
2019-08-13 00:32:43 -05:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{series && series.length > MAX_NUMBER_OF_TIME_SERIES && !showAllTimeSeries && (
|
2019-08-26 01:11:07 -05:00
|
|
|
<div className={cx([style.timeSeriesDisclaimer])}>
|
2020-04-12 15:20:02 -05:00
|
|
|
<Icon className={style.disclaimerIcon} name="exclamation-triangle" />
|
2019-08-13 00:32:43 -05:00
|
|
|
{`Showing only ${MAX_NUMBER_OF_TIME_SERIES} time series. `}
|
2019-11-19 07:59:39 -06:00
|
|
|
<span
|
|
|
|
className={cx([style.showAllTimeSeries])}
|
|
|
|
onClick={this.onShowAllTimeSeries}
|
|
|
|
>{`Show all ${series.length}`}</span>
|
2019-08-13 00:32:43 -05:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
|
2019-08-26 01:11:07 -05:00
|
|
|
{showPanel && (
|
2020-09-22 10:31:42 -05:00
|
|
|
<Collapse label="Graph" loading={loading} isOpen>
|
2019-08-13 00:32:43 -05:00
|
|
|
{this.renderGraph()}
|
2019-08-26 01:11:07 -05:00
|
|
|
</Collapse>
|
2019-08-13 00:32:43 -05:00
|
|
|
)}
|
|
|
|
|
2019-08-26 01:11:07 -05:00
|
|
|
{!showPanel && this.renderGraph()}
|
2019-08-13 00:32:43 -05:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-26 01:11:07 -05:00
|
|
|
export const ExploreGraphPanel = withTheme(UnThemedExploreGraphPanel);
|
|
|
|
ExploreGraphPanel.displayName = 'ExploreGraphPanel';
|